ExpressionHelper.GetExpressionText (expression) does not return the name of my property

I have implemented the MVC extension for formatting numbers in my application. It is based on the code found here . And it looks like this

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

When I call it with the next line of Razor syntax

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

I get an exception because the 'name' variable in my extension is an empty string. I tried to change the var name string to this, but it only gives me the property name β€œY” and not the full β€œModel.PointAttributes [i] .Data.Y” that I need to bind the model to MVC.

 var name = ((expression.Body is MemberExpression ?((MemberExpression)expression.Body).Member : ((MemberExpression)((UnaryExpression)expression.Body).Operand).Member)).Name; 
+6
source share
5 answers

This is a known behavior. I realized that I wrote my own version of ExpressionHelper that handles this particular case. You now have two options:

+6
source

Try using this function:

  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); } 
+8
source

Here's the "hybrid":

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

This is a more compact and probably better solution:

fooobar.com/questions/288385 / ...

+1
source

If you can leave without using a null type, it seems to work (i.e. removes? After double, or as in my case decimal). So,

 Expression<Func<TModel, double?>> 

becomes

 Expression<Func<TModel, double>>. 

If you go through it with a null type, you will see that the expression has a convert () function, which seems to be the "problem". I am sure that, like you, you will be interested in how to make this function work for types with a zero value.

0
source

I know that it is closed, but for the record;

This is handled better by the template, so you can specify what type of data you use in the model and how it is represented in the template (single responsibility). Also, you will not need to change the structure of MVC.

MSDN attribute UiHint

0
source

Source: https://habr.com/ru/post/915401/


All Articles