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.
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 = "https://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 (@
@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!