asp.net-mvc 从 HtmlHelper 的扩展方法中传递的 lambda 表达式获取属性值的最简单方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2846778/
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
What is the easiest way to get the property value from a passed lambda expression in an extension method for HtmlHelper?
提问by Andrew Siemer
I am writing a dirty little extension method for HtmlHelper so that I can say something like HtmlHelper.WysiwygFor(lambda) and display the CKEditor.
我正在为 HtmlHelper 编写一个肮脏的小扩展方法,以便我可以说 HtmlHelper.WysiwygFor(lambda) 之类的内容并显示 CKEditor。
I have this working currently but it seems a bit more cumbersome than I would prefer. I am hoping that there is a more straight forward way of doing this.
我目前有这个工作,但它似乎比我希望的要麻烦一些。我希望有一种更直接的方法来做到这一点。
Here is what I have so far.
这是我到目前为止所拥有的。
public static MvcHtmlString WysiwygFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
{
return MvcHtmlString.Create(string.Concat("<textarea class=\"ckeditor\" cols=\"80\" id=\"",
expression.MemberName(), "\" name=\"editor1\" rows=\"10\">",
GetValue(helper, expression),
"</textarea>"));
}
private static string GetValue<TModel, TProperty>(HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
{
MemberExpression body = (MemberExpression)expression.Body;
string propertyName = body.Member.Name;
TModel model = helper.ViewData.Model;
string value = typeof(TModel).GetProperty(propertyName).GetValue(model, null).ToString();
return value;
}
private static string MemberName<T, V>(this Expression<Func<T, V>> expression)
{
var memberExpression = expression.Body as MemberExpression;
if (memberExpression == null)
throw new InvalidOperationException("Expression must be a member expression");
return memberExpression.Member.Name;
}
Thanks!
谢谢!
回答by Darin Dimitrov
Try like this:
像这样尝试:
public static MvcHtmlString Try<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression
)
{
var builder = new TagBuilder("textarea");
builder.AddCssClass("ckeditor");
builder.MergeAttribute("cols", "80");
builder.MergeAttribute("name", "editor1");
builder.MergeAttribute("id", expression.Name); // not sure about the id - verify
var value = ModelMetadata.FromLambdaExpression(
expression, htmlHelper.ViewData
).Model;
builder.SetInnerText(value.ToString());
return MvcHtmlString.Create(builder.ToString());
}
回答by Peter Hedberg
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Object value = metadata.Model;
String name = metadata.PropertyName;
回答by Ales Potocnik Hahonina
I Know this is an old thread but just in case if someone is looking for it, the way to generate id / name attribute is also:
我知道这是一个旧线程,但以防万一有人在寻找它,生成 id / name 属性的方法也是:
System.Web.Mvc.ExpressionHelper.GetExpressionText(expression);
I'm using this in my extensions and never had any issues with it. It also works great with nested properties.
我在我的扩展中使用了它,并且从来没有遇到过任何问题。它也适用于嵌套属性。
回答by BigMomma
Simplest way is to wrap it all up in an extension method:
最简单的方法是将其全部包装在扩展方法中:
public static class ExtensionMethods
{
public static object Value<TModel, TProperty>(this Expression<Func<TModel, TProperty>> expression, ViewDataDictionary<TModel> viewData)
{
return ModelMetadata.FromLambdaExpression(expression, viewData).Model;
}
}
So the calling syntax is:
所以调用语法是:
expression.Value(htmlHelper.ViewData)
回答by user571646
ASP.NET MVC 3 Futuresincludes a helper for that.
ASP.NET MVC 3 Futures包含一个帮助程序。
回答by Triynko
This isn't addressed by either Peter or BigMomma's answer, but it combines both. If you're calling this from a controller method, where you don't have access to an HtmlHelper instance, just create a base controller method like this:
Peter 或 BigMomma 的回答都没有解决这个问题,但它结合了两者。如果您从控制器方法调用它,而您无权访问 HtmlHelper 实例,只需创建一个基本控制器方法,如下所示:
public ModelMetadata GetModelMetadata<TModel, TProperty>( TModel model, Expression<Func<TModel, TProperty>> expression )
{
ViewData.Model = model; //model is null in Controller; you must set it here (or earlier) in order to extract values from the returned ModelMetadata.
return ModelMetadata.FromLambdaExpression( expression, new ViewDataDictionary<TModel>( ViewData ) );
}
Then you can read what you need from the model metadata as usual;
然后你可以像往常一样从模型元数据中读取你需要的内容;
var mm = GetModelMetaData( model, m => m.SomeProperty );
string name = mm.PropertyName;
object value = mm.Model;