Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Extension Method Not Found in MVC4 Razor View?

Tags:

Given the following string extension method

namespace JHS.ExtensionMethods {   public static class StringExtensions   {     public static string ToUSAPhone(this String str)     {       return String.Format("{0:(###) ###-####}", Double.Parse(str));     }   } } 

A @using statement was added to the MVC4 Razor view

@using JHS.ExtensionMethods; 

and the following string value calls the extension method

@Model.producer.phone.ToUSAPhone() 

which results in the following error

'string' does not contain a definition for 'ToUSAPhone' 

I also tried putting the namespace in the web.config of the /Views folder and receive the same error.

<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.Optimization"/>     <add namespace="System.Web.Routing" />     <add namespace="JHS.ExtensionMethods"/>   </namespaces> </pages> 

I have verified the extension method works by putting the same call in a C# class

string test=producer.phone.ToUSAPhone(); 

It seems the reference to the extension method is not available in the MVC4 Razor view but I can't figure out why?

like image 671
ChrisP Avatar asked Oct 08 '13 18:10

ChrisP


People also ask

What will be the extension for the Razor file?

The Razor syntax consists of Razor markup, C#, and HTML. Files containing Razor generally have a . cshtml file extension.

What is the file extension for using Razor view with Visual Basic syntax?

Razor allows you to write a mix of HTML and server-side code using C# or Visual Basic. Razor view with visual basic syntax has . vbhtml file extension and C# syntax has . cshtml file extension.

Where we can use extension method in C#?

You can use extension methods to extend a class or interface, but not to override them. An extension method with the same name and signature as an interface or class method will never be called. At compile time, extension methods always have lower priority than instance methods defined in the type itself.

What is extension method in MVC?

What is extension method? Extension methods in C# are methods applied to some existing class and they look like regular instance methods. This way we can "extend" existing classes we cannot change. Perhaps the best example of extension methods are HtmlHelper extensions used in ASP.NET MVC.


2 Answers

This happens if the type you are trying to use the extension method on is actually a dynamic. Check to see if the exception is being generated by the CSharp RuntimeBinder. If so, you can either use the method as a common or garden static method:

@StringExtensions.ToUSAPhone(Model.producer.phone) 

Or you can cast the value to a string:

@(((string)Model.producer.phone).ToUSAPhone()) 

According to Eric Lippert (formerly of MSFT):

The reason behind the fact that dynamics do not support extension types is because in regular, non-dynamic code extension methods work by doing a full search of all the classes known to the compiler for a static class that has an extension method that match. The search goes in order based on the namespace nesting and available "using" directives in each namespace.

That means that in order to get a dynamic extension method invocation resolved correctly, somehow the DLR has to know at runtime what all the namespace nestings and "using" directives were in your source code. There is no mechanism handy for encoding all that information into the call site.

like image 102
Mike Brind Avatar answered Oct 09 '22 07:10

Mike Brind


It's not just if the type you're calling the extension method on is dynamic, but if anything in the expression is dynamic and not cast.

eg this is clearly dynamic:

@ViewBag.ToJSON() 

But I first thought Mike's answer did not apply to me because I was doing this :

@(ViewBag.UserProfile.GetJSONProfile().ToJSON()) 

where ToJSON() is my extension method and GetJSONProfile() just returns object.

I was just spacing out and being stupid but wanted to mention this.

like image 20
Simon_Weaver Avatar answered Oct 09 '22 07:10

Simon_Weaver