asp.net-mvc 是否可以使用 Razor 创建通用的 @helper 方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4760783/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is it possible to create a generic @helper method with Razor?
提问by mkedobbs
I am trying to write a helper in Razor that looks like the following:
我正在尝试在 Razor 中编写一个如下所示的助手:
@helper DoSomething<T, U>(Expression<Func<T, U>> expr) where T : class
Unfortunately, the parser thinks that <T
is the beginning of an HTML element and I end up with a syntax error. Is it possible to create a helper with Razor that is a generic method? If so, what is the syntax?
不幸的是,解析器认为这<T
是 HTML 元素的开始,而我却以语法错误告终。是否可以使用作为通用方法的 Razor 创建帮助程序?如果是这样,语法是什么?
采纳答案by Darin Dimitrov
No, this is not possible. You could write a normal HTML helper instead.
不,这是不可能的。您可以改为编写一个普通的 HTML 帮助程序。
public static MvcHtmlString DoSomething<T, U>(
this HtmlHelper htmlHelper,
Expression<Func<T, U>> expr
) where T : class
{
...
}
and then:
进而:
@(Html.DoSomething<SomeModel, string>(x => x.SomeProperty))
or if you are targeting the model as first generic argument:
或者,如果您将模型作为第一个通用参数:
public static MvcHtmlString DoSomething<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expr
) where T : class
{
...
}
which will allow you to invoke it like this (assuming of course that your view is strongly typed, but that's a safe assumption because all views should be strongly typed anyways :-)):
这将允许您像这样调用它(当然假设您的视图是强类型的,但这是一个安全的假设,因为无论如何所有视图都应该是强类型的 :-)):
@Html.DoSomething(x => x.SomeProperty)
回答by chrismilleruk
This ispossible to achieve inside a helper file with the @functions
syntax but if you want the razor-style readability you are referring to you will also need to call a regular helper to do the HTML fit and finish.
这是有可能实现与一个帮助文件中@functions
的语法,但如果你想你指的是你的剃须刀式的可读性也需要调用一个常规帮手做HTML适应和完成。
Note that functions in a Helper file are static so you would still need to pass in the HtmlHelper instance from the page if you were intending to use its methods.
请注意,Helper 文件中的函数是静态的,因此如果您打算使用其方法,您仍然需要从页面传入 HtmlHelper 实例。
e.g. Views\MyView.cshtml:
例如 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:
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>
}
...
回答by bradlis7
In all cases the TModel
will be the same (the model declared for the view), and in my case, the TValue
was going to be the same, so I was able to declare the Expression argument type:
在所有情况下TModel
都将相同(为视图声明的模型),在我的情况下,TValue
将相同,因此我能够声明 Expression 参数类型:
@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>
}
If your model fields are all string
, then you can replace MyClass
with string
.
如果您的模型字段都是string
,那么您可以替换MyClass
为string
.
It might not be bad to define two or three helpers with the TValue
defined, but if you have any more that would generate some ugly code, I didn't really find a good solution. I tried wrapping the @helper
from a function I put inside the @functions {}
block, but I never got it to work down that path.
用定义的方法定义两个或三个帮助器可能不错TValue
,但是如果您还有更多会生成一些丑陋代码的帮助器,我真的没有找到好的解决方案。我尝试@helper
从我放在@functions {}
块中的函数中包装,但我从来没有让它沿着那个路径工作。
回答by ktutnik
if your main problem is to get nameattribute value for binding using lambda expression seems like the @Html.TextBoxFor(x => x.MyPoperty)
, and if your component having very complex html tags and should be implemented on razor helper, then why don't just create an extension method of HtmlHelper<TModel>
to resolve the binding name:
如果你的主要问题是获得名称属性值使用lambda表达式结合似乎是@Html.TextBoxFor(x => x.MyPoperty)
,如果有非常复杂的HTML标签,并应在剃刀帮助实现你的组件,那么为什么不只是创建一个扩展方法HtmlHelper<TModel>
来解决绑定名称:
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);
}
}
}
your razor helper should be like usual:
您的剃须刀助手应该像往常一样:
@helper MyComponent(string name)
{
<input name="@name" type="text"/>
}
then here you can use it
那么在这里你可以使用它
@TheHelper.MyComponent(Html.GetNameForBinding(x => x.MyProperty))