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 = "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!

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

This entry was posted in General Posts and tagged , , , , . Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Pingback: The Morning Brew - Chris Alcock » The Morning Brew #892

  • John mc

    Helpful and informative as always Scott, thanks!

  • Battaile Fauber

    Hey Hugo,
    This is the conceptual hurdle that I would’ve had in coming up with this approach:
    @<strong>User is offline!</strong>
    being able to be used as a Func
    …could you elaborate on that at all?

    • Hugo Bonacci

      Hi Battalie,

      You’re able to use the @<tag>CONTENT_HERE</tag> syntax for the Func<object, object> argument (if that was what you were asking)

  • http://www.raishussain.com Rais Hussain

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

    Can you tell me where from item object comes?

    Can you elaborate the following part?

    @helper user_status(IEnumerable users,
    Func online,
    Func offline)

    Thanks for sharing informative tip.

    • Hugo Bonacci

      The “item” object is the value passed into the “template” provided – why it is named “item” and why intellisense knows about it is a complete mystery to me. :)

      The example I used probably would have made more sense if I used something along the lines of logged in versus logged out – Two entirely different templates used in the same place.

  • http://www.swqee.com tarig

    Thanks Hugo, very helpful

  • Pingback: Define something like for in ASP.NET MVC 3 to pass real html

  • Pingback: Define something like for in ASP.NET MVC 3 to pass real html | PHP Developer Resource

  • Pingback: R&D | Study Notes for 70-486 – Developing ASP.NET MVC 4 Web Applications