从 HtmlHelper 的扩展方法中传递的 lambda 表达式中获取属性值的最简单方法是啥?

Posted

技术标签:

【中文标题】从 HtmlHelper 的扩展方法中传递的 lambda 表达式中获取属性值的最简单方法是啥?【英文标题】:What is the easiest way to get the property value from a passed lambda expression in an extension method for HtmlHelper?从 HtmlHelper 的扩展方法中传递的 lambda 表达式中获取属性值的最简单方法是什么? 【发布时间】:2011-02-20 06:22:56 【问题描述】:

我正在为 htmlHelper 编写一个肮脏的小扩展方法,以便我可以说类似 HtmlHelper.WysiwygFor(lambda) 并显示 CKEditor。

我目前有这个工作,但它似乎比我希望的要麻烦一些。我希望有更直接的方法来做到这一点。

这是我目前所拥有的。

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;

谢谢!

【问题讨论】:

我测试了你的 Getvalue 方法,当助手是一个选择列表时得到了很好的结果。在这种情况下,这里的其他方法都失败了。 【参考方案1】:

试试这样:

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());

【讨论】:

我最感兴趣的是上面的这一行 - var value = ModelMetadata.FromLambdaExpression( expression, htmlHelper.ViewData ).Model;效果很好!我确实发现您的 expression.Name 返回 null。我将其交换为指向我的 MemberName 方法以使其适用于 ID。另外,我发现有一个 TagBuilder.GenerateId() 用于添加 ID 属性。谢谢。我一定会在我即将出版的书中提到你(ASP.NET MVC Cookbook - groups.google.com/group/aspnet-mvc-2-cookbook-review) 嘿达林,你能解释一下这行吗? var value = ModelMetadata.FromLambdaExpression( expression, htmlHelper.ViewData ).Model;【参考方案2】:
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Object value = metadata.Model;
String name = metadata.PropertyName;

【讨论】:

这对我有用,并通过 PropertyName 正确获取属性名称,其中 expression.Name 返回 null。编辑添加 - 我正在运行 MVC5 以防万一【参考方案3】:

我知道这是一个旧线程,但以防万一有人在寻找它,生成 id / name 属性的方法也是:

System.Web.Mvc.ExpressionHelper.GetExpressionText(expression);

我在我的扩展程序中使用它并且从未遇到任何问题。它也适用于嵌套属性。

【讨论】:

这将获得属性的名称,而不是它的值【参考方案4】:

最简单的方法是将其全部包装在一个扩展方法中:

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;
      


所以调用语法是:

expression.Value(htmlHelper.ViewData)

【讨论】:

【参考方案5】:

ASP.NET MVC 3 Futures 包含一个帮助器。

【讨论】:

【参考方案6】:

彼得或 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 ) );

然后你就可以像往常一样从模型元数据中读取你需要的东西了;

var mm = GetModelMetaData( model, m => m.SomeProperty );
string name = mm.PropertyName;
object value = mm.Model;

【讨论】:

以上是关于从 HtmlHelper 的扩展方法中传递的 lambda 表达式中获取属性值的最简单方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

查找HTMLHelper,URLHelper和AJAXHelper类型的所有扩展方法

在 ASP.net core mvc 3.1 中的 HtmlHelper 扩展方法中使用 DataAnnotation 本地化器

.NET MVC3中扩展一个HtmlHelper方法CheckBoxList

ASP.Net MVC开发基础学习笔记:二HtmlHelper与扩展方法

MVC4.0 我使用用 HtmlHelper类的扩展方法 html 标签被转义,怎么处理?

HtmlHelper 扩展改变传入的属性的值