ExpressionHelper.GetExpressionText(表达式)不返回我的属性的名称

时间:2012-05-10 12:39:46

标签: asp.net-mvc-3 lambda

我已经实现了一个MVC扩展来格式化我的应用程序中的数字。它基于找到的代码here。如下

public static MvcHtmlString DecimalBoxFor<TModel>(this HtmlHelper<TModel> html, Expression<Func<TModel, double?>> expression, string format, object htmlAttributes = null)
{
    var name = ExpressionHelper.GetExpressionText(expression);   
    double? dec = expression.Compile().Invoke(html.ViewData.Model);
    var value = dec.HasValue ? (!string.IsNullOrEmpty(format) ? dec.Value.ToString(format) : dec.Value.ToString()): "";
    return html.TextBox(name, value, htmlAttributes);
}

当我使用以下Razor语法行调用它时

@Html.DecimalBoxFor(model => Model.PointAttributes[i].Data.Y,"0.000", new { @class = "span1 number" })

我得到一个例外,因为我的扩展名中的变量'name'是一个空字符串。我已经尝试将var name行更改为this但它只给了我'Y'的属性名,而不是我需要将模型绑定回MVC的完整'Model.PointAttributes [i] .Data.Y'。 / p>

var name = ((expression.Body is MemberExpression ?((MemberExpression)expression.Body).Member : ((MemberExpression)((UnaryExpression)expression.Body).Operand).Member)).Name;

5 个答案:

答案 0 :(得分:8)

尝试使用此功能:

    static public string GetExpressionText(LambdaExpression p)
    {
        if (p.Body.NodeType == ExpressionType.Convert || p.Body.NodeType == ExpressionType.ConvertChecked)
        {
            p = Expression.Lambda(((UnaryExpression)p.Body).Operand,
                p.Parameters);
        }
        return ExpressionHelper.GetExpressionText(p);
    }

答案 1 :(得分:6)

这是一种已知的行为。我已经想出了编写我自己的ExpressionHelper版本来处理这个特定情况。现在你有两个选择:

  1. 使用NuGet包:

    Install-Package Mariuzzo.Web.Mvc.Extras
    
  2. 或者只需抓住the source code of the aforementioned ExpressionHelper并将其粘贴到您的项目中。

答案 2 :(得分:1)

这里有一个&#39;混合&#39;一:)

    public static void AddModelError<TModel>(this ModelStateDictionary state, Expression<Func<TModel, object>> expression, string message)
    {
        LambdaExpression lambdaExpression = null;
        string fieldName = string.Empty;

        if (expression.Body.NodeType == ExpressionType.Convert || expression.Body.NodeType == ExpressionType.ConvertChecked)
        {
            lambdaExpression = Expression.Lambda(((UnaryExpression)expression.Body).Operand, expression.Parameters);
            fieldName = ExpressionHelper.GetExpressionText(lambdaExpression);
        } else {
            fieldName = ExpressionHelper.GetExpressionText(expression);
        }

        state.AddModelError(fieldName, message);
    }

这个更紧凑,可能是更好的解决方案:

https://stackoverflow.com/a/12689563/951001

答案 3 :(得分:0)

如果你可以在不使用可空类型的情况下离开它似乎工作(即删除?后双,或在我的情况下十进制)。所以

Expression<Func<TModel, double?>> 

成为

Expression<Func<TModel, double>>.  

如果你使用可空类型单步执行它,你会看到表达式中有一个convert()函数,它似乎是'问题'。我肯定和我一样,你会对如何使这个函数适用于可空类型感兴趣。

答案 4 :(得分:0)

我知道它已关闭但是为了记录;

最好由模板处理,以便您可以指定模型中使用的数据类型以及模板中的表示方式(单一责任)。 您也不需要修改MVC框架。

MSDN UiHint attribute