【问题标题】:Using MVC HtmlHelper extensions from Razor declarative views从 Razor 声明式视图中使用 MVC HtmlHelper 扩展
【发布时间】:2011-06-10 07:09:18
【问题描述】:

我试图在我的 App_Code 文件夹中为 MVC 3 RTM 项目创建 Razor 声明性帮助程序。

我遇到的问题是 MVC HtmlHelper 扩展(如 ActionLink)不可用。这是因为编译后的助手派生自System.Web.WebPages.HelperPage,虽然它公开了Html 属性,但它的类型是System.Web.WebPages.HtmlHelper,而不是System.Web.Mvc.HtmlHelper

我遇到的错误类型的一个例子是:

'System.Web.Mvc.HtmlHelper' 没有 包含“ActionLink”的定义 并且没有扩展方法'ActionLink' 接受类型的第一个参数 'System.Web.Mvc.HtmlHelper' 可能是 找到(您是否缺少使用 指令还是程序集引用?)

我唯一的解决方案是创建自己的 HelperPage 并覆盖 Html 属性:

using System.Web.WebPages;

public class HelperPage : System.Web.WebPages.HelperPage 
{
    // Workaround - exposes the MVC HtmlHelper instead of the normal helper
    public static new HtmlHelper Html
    {
        get { return ((System.Web.Mvc.WebViewPage) WebPageContext.Current.Page).Html; }
    }
}

然后我必须在每个助手的顶部写下以下内容:

@inherits FunnelWeb.Web.App_Code.HelperPage
@using System.Web.Mvc
@using System.Web.Mvc.Html

@helper DoSomething()
{
    @Html.ActionLink("Index", "Home")
}

这意味着在 MVC 3 中这么难,还是我做错了什么?

【问题讨论】:

  • 如果您还需要 Url 助手,您可以将这行代码添加到 HelperPage: public static UrlHelper Url { get { return new UrlHelper(Html.ViewContext.RequestContext); } }

标签: asp.net-mvc asp.net-mvc-3 razor


【解决方案1】:

为了搜索者的利益,我在创建 MVC 视图作为类库的一部分时遇到了同样的错误(用于组件重用)。上面部分提到的解决方案是在 .cshtml 文件的顶部添加以下 using 语句:

@using System.Web.Mvc
@using System.Web.Mvc.Html

无需进一步的工作。

【讨论】:

  • 我在 App_Code 下的 .cshtml 中的助手在 Intellisense 中无法识别。在 App_code 下的 .cshtml 顶部添加 @using System.Web.Mvc.Html 有效。
  • 当我这样做时,我在悬停@using System.Web.Mvc 时得到"Could not load type 'System.Web.WebPages.Instrumentation.InstrumentationService' from assembly 'System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'."。有什么想法吗?
  • 这对我来说没什么区别
【解决方案2】:

我的方法是简单地将页面作为参数传递给辅助方法。因此,在您的示例中,它将是:

@helper DoSomething(WebViewPage page)
{
    @page.Html.ActionLink("Index", "Home")
}

然后在你需要它的 Razor 视图中这样调用它:

@YourHelperFilename.DoSomething(this)

立即执行此操作可让您访问您通常拥有的页面属性,例如 HtmlUrl(并通过这些属性获得 HtmlHelper 扩展名)。

作为额外的好处(如果您需要),您还可以访问实例属性,例如页面的ViewData

【讨论】:

    【解决方案3】:

    另一种解决方案:

    将此添加到您的 razor-helper 文件顶部:

    @functions {
        public static System.Web.Mvc.HtmlHelper<object> HHtml = ((System.Web.Mvc.WebViewPage)WebPageContext.Current.Page).Html;
    }
    

    然后这样称呼它:

    @HHtml.ActionLink("actionname")
    

    【讨论】:

    • 这看起来最初对我有用,但是当再次调用帮助程序时,我得到“值不在预期范围内”。
    【解决方案4】:

    看起来 ASP.NET MVC 已在 VS 2013 中修复了此问题。请参阅此帖子 http://aspnet.uservoice.com/forums/41201-asp-net-mvc/suggestions/3670180-support-helper-extensionmethod-this-htmlhelper-ht

    【讨论】:

    • 不,一点也不。 Intellisense 没有采用扩展方法,我有 VS2013 更新 5。我在 App_Code 中的 cshtml 文件顶部有 @using System.Web.Mvc.Html,但编写 @Html.... 没有显示任何扩展方法,例如 EditorFor。可笑的是,在 2 个主要版本和声称已实施的博客文章之后,这不起作用。它不是。实际上,扩展方法是行不通的,因为它们针对的是 System.Web.Mvc.HtmlHelper 类,而不是 System.Web.WebPages.HtmlHelper 类,它是由 System.Web.WebPages.HelperPage 类公开的。
    【解决方案5】:

    类似于@Jakes 的回答:

    public static class MvcIntrinsics {
        public static System.Web.Mvc.HtmlHelper Html {
            get { return ((System.Web.Mvc.WebViewPage)WebPageContext.Current.Page).Html; }
        }
    
        public static System.Web.Mvc.AjaxHelper Ajax {
            get { return ((System.Web.Mvc.WebViewPage)WebPageContext.Current.Page).Ajax; }
        }
    
        public static System.Web.Mvc.UrlHelper Url {
            get { return ((System.Web.Mvc.WebViewPage)WebPageContext.Current.Page).Url; }
        }
    
    }
    

    用法:

    @MvcIntrinsics.Html.Raw("test")
    

    来源:Dino Esposito - Programming Microsoft ASP.NET MVC

    【讨论】:

    • 荒谬的是,这甚至是必要的,而且这些不仅仅是 App_Code 中视图的基类的一部分。
    【解决方案6】:

    我为 WebPages 助手创建了一个扩展方法,以便我可以访问页面助手。

    public static HtmlHelper GetPageHelper(this System.Web.WebPages.Html.HtmlHelper html)
    {
     return ((System.Web.Mvc.WebViewPage) WebPageContext.Current.Page).Html;
    }
    

    【讨论】:

    • 用法:@Html.GetPageHelper().ActionLink("actioname")
    • 这对我有用,但我必须将 @using System.Web.Mvc@using System.Web.Mvc.Html 添加到 App_Code 内的 cshtml 帮助文件中
    • 为什么会有单独的HtmlHelper类?无论是在 App_Code 还是 Views 中都应该是一样的。史诗般的半实现设计失败。
    • 在这里被weblogs.asp.net/scottgu/… 引用,它很好地描述了如何创建“全局”Razor 助手。那么,如果您只需要 HtmlHelper 类进行编码,我发现了一种更快的方法是通过静态类 Microsoft.Security.Application.Encoder ,如:Encoder.HtmlAttributeEncode(value)
    【解决方案7】:

    Omar 在这里得到了正确答案,但我想补充一点(请随时将 Omar 的回答标记为答案)。

    我们在 v1 中就意识到了这一点,因此无法在产品中得到很好的修复,但 David Ebbo(ASP.Net 团队的架构师)发布了一个 Visual Studio Code Generator 示例,它基本上是一个第一次探索我们正在寻找的使这项工作正常工作的想法:http://blogs.msdn.com/b/davidebb/archive/2010/10/27/turn-your-razor-helpers-into-reusable-libraries.aspx

    试试看,看看你的想法!通过在他的博客上发帖让 David 知道您是否有 cmets。

    【讨论】:

    • 是否有计划在下一版本的 Razor 中解决此问题?我注意到这在 VS 11 Beta 中仍然是一个问题。
    【解决方案8】:

    看看Marcind's answer这个问题。您遇到的是将声明性视图放在 App_Code 文件夹中的限制。

    将您的助手放入 App_Code 工作 但有一定的局限性 影响某些 MVC 场景(对于 示例:无法访问标准 MVC html。帮手)

    【讨论】:

    • 其他读者请注意:这个答案是绝对正确的,但也请查看下面 Andrew Nurse 的额外贡献以了解潜在的解决方法。
    【解决方案9】:

    我知道 MVC 3 存在一些智能感知问题。我认为如果您在 web.config 中设置了命名空间,帮助程序仍然可以工作。

    MVC 3 RTM 刚刚发布,您使用的是这个版本还是 beta 版本?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-15
      • 1970-01-01
      • 2023-03-25
      • 2011-05-07
      • 2015-04-04
      • 2016-03-22
      • 2010-10-27
      相关资源
      最近更新 更多