Stefan Rusek | Using Razor with ASP.NET MVC in Four Easy Steps

Using Razor with ASP.NET MVC in Four Easy Steps

Saturday, July 17, 2010

I love Scott Guthrie’s blog, even though he is always taunting us with awesome new stuff. Recently, he posted about Razor, which is a new view engine for ASP.NET MVC. Normally views in ASP.NET MVC are just .ASPX files without codebehind files. This works decently well, because it turns out that ASP.NET is better than you’d think as a template language. That said, it could be a lot better. Since the release of ASP.NET MVC, several people have written alternatives to the default WebForms view engine (Spark, NHaml, even me). Razor is Microsoft’s attempt to create a view engine that better fits the needs of MVC developers than the WebForms engine. You can read all about it on Scott Guthries’s blog and on the WebMatrix Razor site. At work we use the WebForms engine, and we would love to switch to something that doesn’t require a web server. While the Xronos view engine would fit our technical needs, I am the first to admit that Xronos isn’t something I want to force on my coworkers. So, Jacob (the other lead developer) and I were pretty excited to read about Razor.

Of course, Microsoft has yet to actually release a CTP for using Razor in MVC, but they did release the Razor engine as part of the latest WebMatric CTP. I had a hunch that there might be enough pieces to put together something that works in MVC, and I was right! Below are the minimum steps needed to get it running for yourself.

Step 1:

Download and install WebMatrix. http://www.microsoft.com/web/webmatrix/download/

After it is installed the Razor files are in the GAC, but I wanted to make it so that I could just install my web app on my server and not have to mess with installing WebMatrix everywhere, so I copied the file dlls from C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\Assemblies (C:\Program Files\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\Assemblies on 32bit Windows) to a directory in my source tree.

Step 2:

Add the following dlls to your web project.

  • Microsoft.Data.dll
  • Microsoft.Web.Infrastructure.dll
  • Microsoft.WebPages.Compilation.dll
  • Microsoft.WebPages.Configuration.dll
  • Microsoft.WebPages.dll
  • Microsoft.WebPages.Helpers.dll
  • Microsoft.WebPages.Helpers.Toolkit.dll

You will also need to add a reference to Microsoft.WebPages.Configuration.dll in your web.config file:

<compilation debug="true" targetFramework="4.0">
  <assemblies>
    <add assembly="Microsoft.WebPages.Configuration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  </assemblies>
</compilation>

You probably already have a few other assemblies list, so just add the <add /> tag to the end of the list.

Step 3:

Since the WebMatrix release lacks the needed Razor=>MVC dlls, you’ll need a RazorViewEngine, here is one:

public class RazorViewEngine : VirtualPathProviderViewEngine
{
    public RazorViewEngine()
    {
        MasterLocationFormats = new[] {"~/Views/{1}/{0}.cshtml"};
        AreaMasterLocationFormats = new[] {"~/Areas/{2}/Views/{1}/{0}.cshtml"};
        PartialViewLocationFormats = ViewLocationFormats = new[] {
            "~/Views/{1}/{0}.cshtml", "~/Views/Shared/{0}.cshtml"};
        AreaPartialViewLocationFormats = AreaViewLocationFormats = new[] {
            "~/Areas/{2}/Views/{1}/{0}.cshtml",
            "~/Areas/{2}/Views/Shared/{0}.cshtml"};
    }

    protected override IView CreatePartialView(
        ControllerContext controllerContext,
        string partialPath)
    {
        return new RazorView {ViewPath = partialPath};
    }

    protected override IView CreateView(
        ControllerContext controllerContext,
        string viewPath, string masterPath)
    {
        return new RazorView {ViewPath = viewPath};
    }

    private class RazorView : IView
    {
        public string ViewPath;

        public void Render(ViewContext viewContext, TextWriter writer)
        {
            var pc = new WebPageContext();

            const BindingFlags bindingFlags = BindingFlags.SetProperty
                | BindingFlags.Instance
                | BindingFlags.NonPublic;
            typeof(WebPageContext).InvokeMember("HttpContext", bindingFlags,
                null, pc, new[] {viewContext.HttpContext});
            typeof(WebPageContext).InvokeMember("ViewContext", bindingFlags,
                null, pc, new[] {viewContext});

            var wb = WebPageBase.CreateInstanceFromVirtualPath(ViewPath);
            wb.ExecutePageHierarchy(pc, writer);
        }
    }
}

Step 4:

Register the RazorViewEngine from the same place you register your MVC routes.

protected void Application_Start()
{
    RegisterRoutes(RouteTable.Routes);
    ViewEngines.Engines.Add(new RazorViewEngine());
}

Here are some things that either don’t work right yet or you may need to change.

  • Html.BeginForm() and Ajax.BeginForm() do some tricks with the HttpResponse object, and Razor doesn’t quite support it, so these methods don’t work like you want. Luckily, Html.BeginForm() is easily replaced by <form action=”@Url.Action()” method=”POST”>.
  • Razor uses its own HttpApplication class, so you may need to change the base class for you Global.asax file.

Have fun!


RenaWilcox said...

on Sunday, August 15, 2010
RenaWilcox said...

on Sunday, August 15, 2010
RenaWilcox said...

on Sunday, August 15, 2010
RenaWilcox said...

on Sunday, August 15, 2010
RenaWilcox said...

on Sunday, August 15, 2010
RenaWilcox said...

on Sunday, August 15, 2010
RenaWilcox said...

on Sunday, August 15, 2010
RenaWilcox said...

on Sunday, August 15, 2010
RenaWilcox said...

on Sunday, August 15, 2010
RenaWilcox said...

on Sunday, August 15, 2010
RenaWilcox said...

on Sunday, August 15, 2010
RenaWilcox said...

on Sunday, August 15, 2010
RenaWilcox said...

on Sunday, August 15, 2010
RenaWilcox said...

on Sunday, August 15, 2010
RenaWilcox said...

on Sunday, August 15, 2010
AltaRamirez22 said...

on Thursday, September 02, 2010
AltaRamirez22 said...

on Thursday, September 02, 2010
AltaRamirez22 said...

on Thursday, September 02, 2010
AltaRamirez22 said...

on Thursday, September 02, 2010
AltaRamirez22 said...

on Thursday, September 02, 2010
AltaRamirez22 said...

on Thursday, September 02, 2010
AltaRamirez22 said...

on Thursday, September 02, 2010
AltaRamirez22 said...

on Thursday, September 02, 2010
AltaRamirez22 said...

on Thursday, September 02, 2010
AltaRamirez22 said...

on Thursday, September 02, 2010
AltaRamirez22 said...

on Thursday, September 02, 2010
AltaRamirez22 said...

on Thursday, September 02, 2010
AltaRamirez22 said...

on Thursday, September 02, 2010
AltaRamirez22 said...

on Thursday, September 02, 2010
AltaRamirez22 said...

on Thursday, September 02, 2010
HuntJosie said...

freelance writer

on Tuesday, September 06, 2011
HuntJosie said...

freelance writer

on Tuesday, September 06, 2011
HuntJosie said...

freelance writer

on Tuesday, September 06, 2011
HuntJosie said...

freelance writer

on Tuesday, September 06, 2011
HuntJosie said...

freelance writer

on Tuesday, September 06, 2011
HuntJosie said...

freelance writer

on Tuesday, September 06, 2011
HuntJosie said...

freelance writer

on Tuesday, September 06, 2011
HuntJosie said...

freelance writer

on Tuesday, September 06, 2011
HuntJosie said...

freelance writer

on Tuesday, September 06, 2011
HuntJosie said...

freelance writer

on Tuesday, September 06, 2011
HuntJosie said...

freelance writer

on Tuesday, September 06, 2011
HuntJosie said...

freelance writer

on Tuesday, September 06, 2011
HuntJosie said...

freelance writer

on Tuesday, September 06, 2011
HuntJosie said...

freelance writer

on Tuesday, September 06, 2011
HuntJosie said...

freelance writer

on Tuesday, September 06, 2011
Please log in or register to comment.