为啥在 MVC4 Razor 视图中找不到扩展方法?

Posted

技术标签:

【中文标题】为啥在 MVC4 Razor 视图中找不到扩展方法?【英文标题】:Why is Extension Method Not Found in MVC4 Razor View?为什么在 MVC4 Razor 视图中找不到扩展方法? 【发布时间】:2013-10-15 20:20:17 【问题描述】:

给定以下字符串扩展方法

namespace JHS.ExtensionMethods

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

在 MVC4 Razor 视图中添加了 @using 语句

@using JHS.ExtensionMethods;

下面的字符串值调用扩展方法

@Model.producer.phone.ToUSAPhone()

导致以下错误

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

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

<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>

我已通过将相同的调用放入 C# 类中验证了扩展方法的工作原理

string test=producer.phone.ToUSAPhone();

在 MVC4 Razor 视图中似乎没有对扩展方法的引用,但我不知道为什么?

【问题讨论】:

你能显示更多的视图代码吗?您可能有一些语法错误。您还确定phonestring 类型而不是null 旁注:将一个定义为整数的数字解析为double只是疯狂... 旁注:@usingclausule 后面不需要分号。 你为什么要把输入字符串解析为双精度,只是为了将双精度转换回返回的字符串? 您是否尝试过关闭并重新打开您的视图?有时 IntelliSense 的行为很奇怪。 【参考方案1】:

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

@StringExtensions.ToUSAPhone(Model.producer.phone)

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

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

According to Eric Lippert(前 MSFT):

动态不支持扩展的原因 types 是因为在常规的非动态代码扩展方法中起作用 通过对编译器已知的所有类进行全面搜索 具有匹配的扩展方法的静态类。搜索进行 根据命名空间嵌套和可用的“使用”顺序 每个命名空间中的指令。

也就是说为了得到一个动态的扩展方法调用 正确解决,不知何故 DLR 必须在运行时知道所有 命名空间嵌套和“使用”指令在您的源代码中 代码。没有方便的机制来编码所有这些信息 进入呼叫站点。

【讨论】:

引用的错误 OP 是:'string' does not contain a definition for 'ToUSAPhone'。 Razor 已经知道这是string 实际上,Razor 对数据类型一无所知。它是一种模板语言,而不是编译器。如果类型是动态的,正如我在回答中所说,它不是字符串。 OP 报告的错误消息是由 RuntimeBinder 生成的。请参阅 Eric Lippert 对这里发生的事情的解释:***.com/questions/5311465/… 我实际上并不确定这是一个 RuntimeBinder 错误。但是错误信息和症状描述肯定闻起来像一个。希望@ChrisP 会回来并提供更多细节的确认。 TL;博士。因为 razor 和相关的工具真的很麻烦。 我知道这是一个旧线程,但由于没有人提到它,解决方案 #1 (@StringExtensions.ToUSAPhone(Model.producer.phone)) 确实有效。【参考方案2】:

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

例如,这显然是动态的:

@ViewBag.ToJSON()

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

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

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

我只是在胡思乱想,很愚蠢,但想提一下。

【讨论】:

【参考方案3】:

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

【讨论】:

【参考方案4】:

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

我在其中创建扩展的文件将“内容”作为 VS 文件属性窗格上构建操作属性的值。

将其切换为“编译”立即解决了问题,自然...

【讨论】:

【参考方案5】:

我遇到了同样的错误信息,但在我的情况下,我以某种奇怪的方式修复了它,通过放置“;”

那是什么

@var subti = item.subtitle.Truncate(18)

已用 ; 修复

@var subti = item.subtitle.Truncate(18);

这可能对某人有帮助

【讨论】:

以上是关于为啥在 MVC4 Razor 视图中找不到扩展方法?的主要内容,如果未能解决你的问题,请参考以下文章

C# MVC4 Razor 部分视图 - 切换视图时刷新整页?

翻译转载官方教程Asp.Net MVC4入门指南:添加一个视图

IntelliSense 在 Razor Pages 项目中找不到 ViewComponent Invoke() 方法

C# MVC 4 RAZOR - JSON 使用 @foreach 从控制器返回列表到视图

MVC 4 Razor - 创建动态下拉列表

如何使用 MVC4 和 Razor 设置 javascript 变量