Razor Template in ASP.NET MVC 3

Update:  There is no need to inherit _ViewStart view class with ViewStartPageWithHelpers in ASP.NET MVC 3 RTM. 

 

     Introduction:

          Templates are used to display a predetermined portion of the page layout which also contains fill-in-the-blanks that can be filled at run time. Template saves a lot of time because it can be reused in many places. Razor view engine includes a feature called Inline Template which allows you to define a portion of dynamic HTML that can reused. Also using Razor template you can pass template as a parameter to a method. In this article I will show you how to use Razor template in ASP.NET MVC. I will also show you how you can define an inline Razor template once and then reuse this template in your application.

 

    Description:

          Let's say that you need to show all student's Name and Age in many places in your application. First of all create a new MVC 3 Project. Now create a new class file Student.cs inside Model folder and add the following code, 

 

    public class Student
    {
        public string Name { get; set; }

        public int Age { get; set; }

        public static List<Student> CreateTestStudents()
        {
            List<Student> students = new List<Student>();
            for (int i = 1; i <= 10; i++)
            {
                Student student = new Student()
                {
                    Age=25+i,
                    Name="Student "+i
                };
                students.Add(student);
            }
            return students;
        }
    }

 

          This is a simple Student class with Name and Age properties. It also includes a static method which is used for creating and returning some students for the testing purpose.

          Now we need to put the template so that it can be reused all over the application. I think _ViewStart.cshtml file is the best place to put this template. Because code inside _ViewStart.cshtml file runs before any view run. So just open _ViewStart.cshtml file and add the following code,

 

@inherits ViewStartPageWithHelpers
@{
    Layout = "~/Views/Shared/_Layout.cshtml";
    Func<List<Student>,HelperResult> h = 
	@<table>
		<tr>
			<th align="center">
	          		Student Name:
			</th>
			<th align="center">
                    		Student Age:
               		</th>
		</tr>
		@foreach (var itm in item) {
		<tr>
			<td align="center">
                    		@itm.Name
                	</td>
                	<td align="center">
                    		@itm.Age
			</td>
		</tr>
		}
	</table>;
	ViewContext.Controller.ViewData["StudentsTemplate"]=h;
}

 

          You can create an inline template in Razor by using @<tag>...</tag> syntax. The above code simply create an inline template which contains a table layout showing all students Name and Age. Note here that the template always return a delegate of type Func<T,HelperResult> where T is a Place Holder for a any defined type. Here I am using List<Student> for T type. You can use item parameter in your inline template which is of type T(in this case List<Student>). The view which calls this delegate method is responsible for sending this parameter. Next I am simply saving this delegate to ViewContext.Controller.ViewData so that it will be reused in any view. 

          Also note that I am inheriting the _ViewStart view class with ViewStartPageWithHelpers class. The reason for inheriting with this new class is that there is a bug in ViewStartPage class. The bug is that the WriteLiteralTo and WriteTo methods are absent in ViewStartPage class. This custom class will fill this gap by adding these methods. According to Andrew Nurse(ASP.NET team member), this bug will be fixed in RTM. So no need for doing this in ASP.NET MVC 3 RTM. So let's create a new class file ViewStartPageWithHelpers.cs inside Helper folder and add the following code,

 

    public abstract class ViewStartPageWithHelpers : ViewStartPage
    {
        public static void WriteLiteralTo(TextWriter writer, object content)
        {
            writer.Write(content);
        }
        public static void WriteTo(TextWriter writer, object content)
        {
            writer.Write(HttpUtility.HtmlEncode(content));
        }
    }

 

          Now let's see how to use this inline template in your view. First of all just open HomeController.cs and add the following code,

 

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View(Student.CreateTestStudents());
        }
    }

 

          The above code simply add a Index action with List<Student> Model. Next add a view for Index action and add the following lines inside this view, 

 

@model List<Student>
@{
    View.Title = "Home Page";
    Func<List<Student>,HelperResult> lst = ViewContext.Controller.ViewData["StudentsTemplate"] as Func<List<Student>,HelperResult>;	
}
@lst(Model)

 

          In this view first of all I am setting the Model for this view as List<Student>. Next I am retrieving the delegate from ViewContext.Controller.ViewData which was saved in _ViewStart.cshtml file. Finally, I am invoking the delegate method and passing the Model as parameter. Now just run this application. You will find the following screen,

 

 

          

 

          Now you can reuse this code in any view where you need to show all the students Name and Age.

 

    Summary:

          In this article I showed you how you can use Razor Inline Template in your ASP.NET MVC project. I explained you with example. I also showed you how you can define the inline template once and then reuse it all over in your application. Don't forget to download the sample application. Hopefully you will enjoy this article too.


17 Comments

  • So this looks like it fills the role of a RenderPartial in the webforms view engine, yes? It seems to be more limited in that you have to stuff the template delegate into view data for it to work; is there any way to put the template in its own file and then get it when needed (rather tahn in every view request?

  • I'm curious how is differs from using partial views and Html.Action() or Html.RenderAction(). I'm new to Razor so I don't know if there are issues using those helpers rather than the templates described here.

  • @Paul, RenderPartial is works in Razor as well. Inline Template get more importance where you need to pass this delegate to a method parameter. See this for detail http://blog.andrewnurse.net/2010/08/02/InsideRazorPart3Templates.aspx.

  • Like Paul I can't see the advantage of this over RenderPartial? RenderPartial seems more straightforward than this. The argument that its another file in the solution is not great. As longs as the solution is tidy there isn't a problem. However I could be missing the point with templates? I want to know more about jQuery templates as well but again can't see the point if you return a partial view from your action and then output that via jQuery to a HTML element.

  • Thanks I now see the point but with the webpage posted above it just looks as if he is creating a method in a class returning a string.

    In your approach, is there a neater way to do it, its almost webforms-esque returning the template from a session type object.

  • @Jonathan,

    ViewData is just an example of sharing this with other views. You can use local variable for local usage, Request.Items, static variable etc.

  • this is awesome Post. It is Help full.

  • with Razor RC has the location of MyHelpers.cshtml file changed? ScottGu said this file should be place in Views/Helpers but i am not able to see my helpers in this file. Is there a web.config setting for this?

  • @Jack,
    You can't

  • So I'm guessing there might be a performance issue with using a large number RenderPartial in a complex page? I would have thought a file existance check is an expensive operation since it's relying on disk speed etc. Does the .net framework cache the file existance check? I'm thinking of a high volume web site scenario here.

  • @deejbee,
    I don't think .NET Framework cache file checking.

  • hi
    sure
    i can not find helper folder in mvc3 project

  • @sarina
    You need to create this folder.

  • i add helper folder add and i have error in @lst(Model)
    : null reference Exception was unhandled by user code

  • @sarina
    Just download the sample project.

  • The example is nice but I really don't want the Model to have business logic work inside of it, is there a way to populate the model using an action?

  • @Zubrowka,
    What do you mean?

Comments have been disabled for this content.