【问题标题】:ExpressionHelper.GetExpressionText(expression) not returning the name of my propertyExpressionHelper.GetExpressionText(expression) 不返回我的属性的名称
【发布时间】:2012-05-10 12:39:45
【问题描述】:

我已经实现了一个 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" })

我得到一个异常,因为我的扩展中的变量“名称”是一个空字符串。我尝试将 var name 行更改为此,但它只给了我“Y”的属性名称,而不是我需要将模型绑定回 MVC 的完整“Model.PointAttributes[i].Data.Y”。

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

【问题讨论】:

    标签: asp.net-mvc-3 lambda


    【解决方案1】:

    试试这个功能:

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

    【讨论】:

    【解决方案2】:

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

    1. 使用 NuGet 包:

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

    【讨论】:

    • 感谢@AarolamaBluenk,我会考虑您的建议,并最终提高自己。再次感谢。
    • 我们遇到了这个问题,这对我们来说非常有效。谢谢!
    【解决方案3】:

    这是一个“混合”的:)

        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

    【讨论】:

      【解决方案4】:

      如果您可以在不使用可为空类型的情况下逃脱,它似乎可以工作(即删除 ? 在 double 之后,或者在我的情况下为十进制)。所以

      Expression<Func<TModel, double?>> 
      

      变成

      Expression<Func<TModel, double>>.  
      

      如果您使用可空类型单步执行它,您会看到表达式中有一个 convert() 函数,这似乎是“问题”。我相信您会像我一样对如何使此函数也适用于可空类型感兴趣。

      【讨论】:

      • 不幸的是它需要是一个可以为空的类型。
      【解决方案5】:

      我知道它已经关闭但记录在案;

      这最好由模板处理,因此您可以指定在模型中使用的数据类型以及它在模板中的表示方式(单一责任)。 此外,您无需修改​​ MVC 框架。

      MSDN UiHint attribute

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-08-01
        • 1970-01-01
        • 2014-05-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多