Wednesday, February 2, 2011

Getting custom extension methods to work in ASP.NET MVC 3 & Razor View Engine

I am going through the process of converting my site to use ASP.NET MVC 3 with the new razor view engine.  I use many extension methods that I have added to the HtmlHelper.  I store all these helpers in the following namespace “DevDave.Infrastructure.Helpers”.

In MVC 2 I added the namespace “DevDave.Infrastructure.Helpers” to the web.config file in the root of my MVC project like so:

<pages>
  <namespaces>
    <add namespace="System.Web.Mvc" />
    <add namespace="System.Web.Mvc.Ajax" />
    <add namespace="System.Web.Mvc.Html" />
    <add namespace="System.Web.Routing" />
    <add namespace="DevDave.Infrastructure.Helpers"/>
  </namespaces>
</pages>

This allowed me to use my custom helpers in all of my pages. So naturally I figured that the same thing would work for the MVC 3 application.  As it turns out it doesn’t, I get this stupid error instead:

image

As you can see it can’t seem to find my extension method “MainMenu”.  Now I did figure out that you could just add a using statement to the top of each page like this:

@using DevDave.Infrastructure.Helpers

Well I don’t want to have to put this in every view so then I tried to add the using statement into the _ViewStart file in the root of the views folder.  Like so:

@{
    using DevDave.Infrastructure.Helpers;
    
    Layout = "~/Views/Shared/_Layout.cshtml";
}

This did not work either something about having a using statement inside a code nugget.  So I moved it to its own line like so:

@using DevDave.Infrastructure.Helpers

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

This still did not work.

To fix this I had to add the name space to the web.config inside of the views folder instead.  Like so:

<system.web.webPages.razor>
  <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
  <pages pageBaseType="System.Web.Mvc.WebViewPage">
    <namespaces>
      <add namespace="System.Web.Mvc" />
      <add namespace="System.Web.Mvc.Ajax" />
      <add namespace="System.Web.Mvc.Html" />
      <add namespace="System.Web.Routing" />
      <add namespace="DevDave.Infrastructure.Helpers"/>
    </namespaces>
  </pages>
</system.web.webPages.razor>

This fixed the problem.

4 comments:

  1. if you use the same HTML Helper namespace, there is no additional imports to add in a view or any additions any web.config. You can just call it in ANY page:

    namespace System.Web.Mvc.Html

    ReplyDelete
  2. Zeb

    Thanks for the information. I will have to give that a try.

    ReplyDelete
  3. if Helpers is a class, and if I add to webconfig , it gives error " A using namespace directive can only be applied to namespaces"

    so I wonder how you got it working?

    ReplyDelete