代码之家  ›  专栏  ›  技术社区  ›  Andrew Siemer

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

  •  53
  • Andrew Siemer  · 技术社区  · 14 年前

    我正在为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;
    }
    

    谢谢!

    6 回复  |  直到 8 年前
        1
  •  80
  •   Darin Dimitrov    14 年前

    尝试这样:

    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());
    }
    
        2
  •  25
  •   Peter Hedberg    14 年前
    ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
    Object value = metadata.Model;
    String name = metadata.PropertyName;
    
        3
  •  10
  •   Ales Potocnik Hahonina    13 年前

    我知道这是一个旧线程,但为了防止有人在寻找它,生成id/name属性的方法还包括:

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

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

        4
  •  5
  •   BigMomma    12 年前

    最简单的方法是用一个扩展方法将其包装起来:

    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
  •  2
  •   user571646    13 年前

    ASP.NET MVC 3 Futures 包括一个助手。

        6
  •  1
  •   Triynko    8 年前

    彼得和毕格莫玛的答案都没有提到这一点,但两者都有。如果您是从一个控制器方法调用这个方法,而您没有访问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;