In ASP.NET MVC view pages, extension methods must be public

Posted: (EET/GMT+2)

 

Another ASP.NET MVC tip. If you are using extension methods in your controller action methods (I find extension methods useful from time to time, even though they can be thought of as being "code smells"), you might also wish to use them in your view pages (the .aspx files in the Views folder).

Personally, I usually write my classes and methods as being internal if they are designed only to be used from the same application/assembly. For instance, the code might something like this:

internal static class Extensions
{
  internal static string ToShortTimeValue(this TimeSpan time)
  {
    return time.Hours + ":" +
      string.Format("{0:00}", time.Minutes);
  }
}

However, if you are writing ASP.NET MVC applications and try to use these classes in your view pages, there's a catch. Try it, and you will get errors like this:

c:\Documents\Visual Studio 2008\Projects\MvcApplication1\Views\Customers\Detail.aspx(32,33): error CS1061:
'System.TimeSpan' does not contain a definition for 'ToShortTimeValue' and no extension method
'ToShortTimeValue' accepting a first argument of type 'System.TimeSpan' could be found (are you missing
a using directive or an assembly reference?)
c:\Documents\Visual Studio 2008\Projects\MvcApplication1\Views\Customers\Detail.aspx(36,31): error CS1061:
'System.TimeSpan' does not contain a definition for 'ToShortTimeValue' and no extension method
'ToShortTimeValue' accepting a first argument of type 'System.TimeSpan' could be found (are you missing
a using directive or an assembly reference?)

Why does this happen? The error message gives you a clue, as you will have to refresh in your mind the way ASP.NET applications are compiled. If you are using MVC, you might think that all code goes into a single assembly, but in the case of view pages, this is not true. Instead, the view page code goes into its own assembly, usually located somewhere under C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root. Because the view pages are in a different assembly, the "internal" access modifier will not be visible enough to the view page assembly.

Of course, the remedy is very simple. Simply change the extension class and method(s) be public:

public static class Extensions
{
  public static string ToShortTimeValue(this TimeSpan time)
  {
    return time.Hours + ":" +
      string.Format("{0:00}", time.Minutes);
  }
}

Good luck!