Templates With Razor

Razor is a great way to create views with ASP.NET MVC. One feature I use quite often are custom helpers. Instead of duplicating the same few lines of markup I simply create a reusable helper to generate HTML.

MVC4_Logo

For example, you could create a helper to do something simple like render out a series of values…

@helper tabs(params Tab[] tabs) {
<ul>
@foreach(var tab in tabs) {
<li><a href="@tab.Url" >@tab.Text</a></li>
}
</ul>
}

Then use the helper by providing the parameters it needs…

@tabs(
new Tab { Text = "Google.com", Url = "http://google.com" },
new Tab { Text = "Hugoware.net", Url = "http://hugoware.net" },
new Tab { Text = "LosTechies.com", Url = "http://lostechies.com" })

This works pretty well for the most part but it is pretty limited in what it can do. Lets look at another approach.

Providing A ‘Template’

In the previous example values were passed into the helper and used to generate the markup required. This time, the helper accepts slightly different arguments that will allow a bit more control.

@helper dialog(string title, 
Func<object, object> content) {
<div class="dialog-box" >
<h3>@title</h3>
<div class="dialog-box-content" >
@content(null)
</div>
</div>
}

This example uses a simple lambda (Func<object, object>) as an argument to provide markup to render. This allows the Razor block (@<text>…</text>) to be passed in as an argument for the helper.

@dialog("User Status", 
@<strong>User is offline!</strong>
)

Now, the content is generated by an external source!

Using Types With Your Templates

So far the examples have used Func<object,object> as a template argument and then invoked the method with null as the argument. As it turns out, not only can you provide a value for that argument, if the argument type for the Func<…> is provided then it can be used from within a template.

@helper user_status(IEnumerable<User> users, 
Func<User, object> online,
Func<User, object> offline) {

<div class="user-status-list" >
<div class="user-status" >
@foreach(var user in users) {
<h3>@user.Username</h3>

if (user.IsOnline) { @online(user); }
else { @offline(user); }
}
</div>
</div>
}

The helper above passes each User into the correct template. Now, a User can be referenced by using item from within the template.

@user_status(users, 

online:@<div class="user-online" >
User @item.Username is online!
</div>,

offline: @<div class="user-offline" >
User @item.Username is offline!
<a href="#" >Send a message!</a>
</div>
)

Now, the contents of each template is unique to the User that was provided!

Leave a comment

Send a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.