从Razor声明式视图使用MVC HtmlHelper扩展


121

我试图在MVC 3 RTM项目的App_Code文件夹中创建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'的第一个参数(您是否缺少using指令?或装配参考?)

我唯一的解决方案是创建自己的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中会变得如此困难,还是我做错了什么?


4
如果还需要Url帮助程序,则可以将此代码行添加到HelperPage:public static UrlHelper Url {get {return new UrlHelper(Html.ViewContext.RequestContext); }
马克·斯塔法利

Answers:


42

看一下对这个问题Marcind的回答。您遇到的限制是在App_Code文件夹中放置声明性视图。

将您的助手放入App_Code中是可行的,但是有一些限制会影响某些MVC方案(例如:无法访问标准MVC Html。)


1
请注意其他读者:这个答案是绝对正确的,但是请在下面查看Andrew Nurse的其他贡献,以寻求可能的解决方法。
约旦·格雷

38

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

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

4
用法:@Html.GetPageHelper().ActionLink("actioname")
deerchao 2011年

这对我有用,但是我必须在App_Code中添加@using System.Web.Mvc并添加@using System.Web.Mvc.Html到cshtml helpers文件中
Tomino

1
为什么会有单独的HtmlHelper类?无论是在App_Code中还是在Views中都应该相同。史诗般的半实现设计失败。
Triynko

weblogs.asp.net/scottgu/…在这里得到了引用,它很好地描述了如何创建“全局” Razor帮助器。因此,如果您只需要HtmlHelper出于编码目的的类,我发现一种更快捷的方法是通过静态类,Microsoft.Security.Application.Encoder例如:Encoder.HtmlAttributeEncode(value)
Matt Borja

11

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知道您是否有评论。


2
有计划在下一版本的Razor中修复此问题吗?我注意到这在VS 11 Beta中仍然是一个问题。
2012年

9

类似于@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-编程Microsoft ASP.NET MVC


1
这甚至是必要的,这很荒谬,而且这些不只是App_Code中视图的基类的一部分。
Triynko

7

替代解决方案:

将此添加到您的razor-helper文件之上:

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

然后这样称呼它:

@HHtml.ActionLink("actionname")

看起来一开始它对我来说是有效的,但是当再次呼叫助手时,我得到“价值不在期望范围内”。
d219 '18

3

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

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

然后在需要的Razor视图中按以下方式调用它:

@YourHelperFilename.DoSomething(this)

立即执行此操作,即可访问通常具有的Html或的页面属性Url(并通过HtmlHelper扩展名)。

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


3

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

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

无需进一步的工作。


我的.cshtml中App_Code下的帮助程序在Intellisense中无法识别。在App_code下的.cshtml顶部添加@using System.Web.Mvc.Html可以正常工作。

当我这样做时,我会"Could not load type 'System.Web.WebPages.Instrumentation.InstrumentationService' from assembly 'System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'."徘徊@using System.Web.Mvc。有任何想法吗?
JoeBrockhaus 2013年

这对我来说没有什么不同
回忆录,

0

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

刚刚实现了MVC 3 RTM,您使用的是此版本还是Beta版本?


0

不,一点也不。Intellisense没有选择扩展方法,并且我有VS2013 update5。我@using System.Web.Mvc.Html在App_Code的cshtml文件顶部,但是编写@Html ....并没有显示任何扩展方法,例如EditorFor。荒谬的是,在2个主要版本和博客文章声称已实现后,此方法不起作用。不是。实际上,扩展方法不起作用,因为它们的目标是System.Web.Mvc.HtmlHelper类,而不是System.Web.WebPages.HtmlHelper类,该类由System.Web.WebPages.HelperPage类公开。
Triynko
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.