Importing Namespaces into Razor Views in ASP.NET MVC 3

The way that namespaces are imported into views is quite different in ASP.NET MVC 3 depending on whether you choose to use the original ASPX view engine or the newer Razor engine. This article discuses these differences and shows how you can make namespaces available to all views without an explicit import statement in each view.

Do I really need to import namespaces into views?

Depending on your project size and complexity, you may not have ever needed access to any non-standard namespaces in your views - particularly if you are a fan of the var keyword. However, as soon as you start writing your own HTML helpers or using resource files, you will almost certainly find that it becomes essential.

Of course, there are workarounds. Some of those that I have seen (in companies that will remain nameless!) include using the full type name throughout the view (e.g. CompanyName.ProjectName.Resources.ErrorMessages.LoginFailure) and using an incorrect namespace that is already available globally such as System.Web.Mvc. Obviously both of these workarounds are pretty horrible but without the correct knowledge it is amazing the hacks that some developers resort to!

To avoid such ugliness and keep your code clean, read on...

Importing namespaces in MVC2 and MVC3 with the ASPX View Engine

If you are using the standard ASPX view engine, then regardless of the version of MVC, the mechanism for importing namespaces is the same. To make a namespace available to a single view, you use the following directive:

<%@ Import Namespace="CompanyName.ProjectName.Resources" %>

This is sufficient in some situations, but in the case of say a resources assembly (for localisation in a multi-language application), pretty much every view will require access to this namespace. We do not want to clutter up every view with this statement. What we need is a global namespace available to ALL views.

Because the ASPX view engine is essentially just ASP.NET WebForms, the way to add a global namespace is exactly the same as you would do with a non-MVC WebForm Application. Just open up your web.config and add the namespace under system.web/pages/namespaces:

<system.web>
  ...
  <pages>
    <namespaces>
      <add namespace="System.Web.Helpers" />
      <add namespace="System.Web.Mvc" />
      <add namespace="System.Web.Mvc.Ajax" />
      <add namespace="System.Web.Mvc.Html" />
      <add namespace="System.Web.Routing" />
      <add namespace="System.Web.WebPages"/>
      <add namespace="CompanyName.ProjectName.Resources"/>
    </namespaces>
  </pages>
</system.web>

Importing namespaces in MVC3 with the Razor View Engine

The new MVC3 Razor view engine has a completely different syntax to the earlier ASPX one and does not use the <%@ style directives that are so familiar to ASP.NET WebForm developers. The good news is that the syntax is much cleaner. To import a namespace into a single Razor view, we use:

@using CompanyName.ProjectName.Resources

Very clean I think you will agree, but as we have already mentioned, if all or most of your views need access to certain namespaces, you do not want to be forced to add this statement to every view. Just as with the built-in HTML helpers, you want every view, partial view and template to have immediate access to your custom helpers, resources etc., without any messing about with using statements. We need global namespaces.

In an ideal world, this would work the same way as with WebForms, but the Razor view engine is not part of core ASP.NET and as such, we cannot use ASP.NET specific configuration sections. Instead, the MVC team have added their own configuration section, but to find it we must look inside the second web.config that is found in the Views folder of your MVC application:

<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="CompanyName.ProjectName.Resources"/>
    </namespaces>
  </pages>
</system.web.webPages.razor>

If you have issues with types not being found even though you have added them to the global namespaces list, you may find that closing and reopening the view (or even the solution) should fix the issue.

What about the Global.asax?

If you worked with beta releases of MVC3, you may have come across an alternative method of registering global namespaces:

protected void Application_Start()
{
  ...
  CodeGeneratorSettings.AddGlobalImport("CompanyName.ProjectName.Resources");
}
	

Alas, this is no more. This code-based method of registration was removed from the final release of MVC3 in favour of the system.web.webPages.razor config section that we have discussed above.

Conclusion

Both ASPX and Razor MVC view engines allow you to import a namespace into a single view or globally, so that the namespace is available to all views, partial views and templates. Both mechanisms are useful for different scenarios depending on how many views will need access to the types in the imported namespace. For site-wide types such as resource files, global namespaces are essential.

The syntax for each view engine is slightly different, as is the method for creating global namespaces, but in either case it is very simple. Whilst there are hacks available for those who are not familiar with namespace importing, for anyone who has read this article, there is no excuse :-)

Comments

Be the first person to comment on this article.