有没有可能用Razor创build一个通用的@helper方法?

我正在试图写一个Razor的帮手,如下所示:

@helper DoSomething<T, U>(Expression<Func<T, U>> expr) where T : class 

不幸的是,parsing器认为<T是一个HTML元素的开始,我最终得到一个语法错误。 是否有可能用Razor创build一个通用方法的帮助器? 如果是这样,语法是什么?

不,这是不可能的。 你可以编写一个普通的HTML帮助器。

 public static MvcHtmlString DoSomething<T, U>( this HtmlHelper htmlHelper, Expression<Func<T, U>> expr ) where T : class { ... } 

接着:

 @(Html.DoSomething<SomeModel, string>(x => x.SomeProperty)) 

或者如果您将模型作为第一个通用参数:

 public static MvcHtmlString DoSomething<TModel, TProperty>( this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expr ) where T : class { ... } 

这将允许你像这样调用它(当然,假设你的视图是强types的,但是这是一个安全的假设,因为所有的视图都应该是强types的:-)):

 @Html.DoSomething(x => x.SomeProperty) 

这可以通过@functions语法在帮助文件中实现,但是如果您想要的是指向您的razor式可读性,您还需要调用常规帮助器来完成HTML合并和完成。

请注意,Helper文件中的函数是静态的,所以如果您打算使用它的方法,您仍然需要从页面传入HtmlHelper实例。

例如Views \ MyView.cshtml:

 @MyHelper.DoSomething(Html, m=>m.Property1) @MyHelper.DoSomething(Html, m=>m.Property2) @MyHelper.DoSomething(Html, m=>m.Property3) 

App_Code文件\ MyHelper.cshtml:

 @using System.Web.Mvc; @using System.Web.Mvc.Html; @using System.Linq.Expressions; @functions { public static HelperResult DoSomething<TModel, TItem>(HtmlHelper<TModel> html, Expression<Func<TModel, TItem>> expr) { return TheThingToDo(html.LabelFor(expr), html.EditorFor(expr), html.ValidationMessageFor(expr)); } } @helper TheThingToDo(MvcHtmlString label, MvcHtmlString textbox, MvcHtmlString validationMessage) { <p> @label <br /> @textbox @validationMessage </p> } ... 

在所有情况下, TModel将是相同的(为视图声明的模型),在我的情况下, TValue将是相同的,所以我能够声明Expression参数types:

 @helper FormRow(Expression<Func<MyViewModel, MyClass>> expression) { <div class="form-group"> @(Html.LabelFor(expression, new { @class = "control-label col-sm-6 text-right" })) <div class="col-sm-6"> @Html.EnumDropDownListFor(expression, new { @class = "form-control" }) </div> @Html.ValidationMessageFor(expression) </div> } 

如果你的模型字段都是string ,那么你可以用stringreplaceMyClass

用定义的TValue定义两个或三个助手可能并不坏,但是如果你还有更多的会产生一些难看的代码,我真的找不到一个好的解决scheme。 我尝试从@functions {}块中放入一个函数来包装@helper ,但是我从来没有把它放在那个path上。

如果你的主要问题是使用l​​ambdaexpression式来获取绑定的name属性值,就像@Html.TextBoxFor(x => x.MyPoperty) ,如果你的组件具有非常复杂的html标签,并且应该在剃刀助手上实现,那么为什么不要只是创build一个HtmlHelper<TModel>的扩展方法来parsing绑定名称:

 namespace System.Web.Mvc { public static class MyHelpers { public static string GetNameForBinding<TModel, TProperty> (this HtmlHelper<TModel> model, Expression<Func<TModel, TProperty>> property) { return ExpressionHelper.GetExpressionText(property); } } } 

你的剃刀帮手应该像往常一样:

 @helper MyComponent(string name) { <input name="@name" type="text"/> } 

那么在这里你可以使用它

 @TheHelper.MyComponent(Html.GetNameForBinding(x => x.MyProperty))