为什么在MVC4 Razor View中找不到扩展方法?

给出以下字符串扩展方法

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

@using语句被添加到MVC4 Razor视图中

 @using JHS.ExtensionMethods; 

以下字符串值调用扩展方法

 @Model.producer.phone.ToUSAPhone() 

这会导致以下错误

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

我还尝试将命名空间放在/ Views文件夹的web.config中并收到相同的错误。

           

我通过在C#类中调用相同的调用来validation扩展方法的工作原理

 string test=producer.phone.ToUSAPhone(); 

看来扩展方法的引用在MVC4 Razor视图中不可用,但我无法弄清楚为什么?

如果您尝试使用扩展方法的类型实际上是dynamic ,则会发生这种情况。 检查CSharp RuntimeBinder是否生成exception。 如果是这样,您可以将该方法用作公共或园区静态方法:

 @StringExtensions.ToUSAPhone(Model.producer.phone) 

或者您可以将值转换为字符串:

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

根据Eric Lippert (前MSFT)的说法 :

动态不支持扩展类型这一事实背后的原因是因为在常规的非动态代码扩展方法中,通过对编译器已知的所有类的完整搜索来处理具有匹配的扩展方法的静态类。 搜索按顺序进行,基于命名空间嵌套和每个命名空间中可用的“using”指令。

这意味着为了正确解析动态扩展方法调用,DLR必须在运行时知道所有命名空间嵌套和“using”指令都在源代码中。 没有将所有信息编码到呼叫站点中的机制。

这不仅仅是您调用扩展方法的类型是动态的,而且表达式中的任何内容都是动态的而不是强制转换。

这显然是动态的:

 @ViewBag.ToJSON() 

但我首先认为迈克的答案不适用于我,因为我这样做:

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

其中ToJSON()是我的扩展方法,而GetJSONProfile()只返回object

我只是间歇而且愚蠢但是想提一下。

在为视图添加扩展的自定义命名空间之前构建项目。

可能还有另一个微不足道的原因,它发生在我身上。

我创建扩展的文件在VS文件属性窗格中将“Content”作为Build Action属性的值。

将其切换为“编译”立即修复了问题,自然……