Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC4 Templates can be used only with field access

I have a MVC model similar to this

public class Model
{
     public string Name {get;set;}
     public int Number {get;set;}
}

I receive the error

Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.

when trying to create a label for the number field, with the model lambda expression stored in a variable.

For example, in my view I have:

@Html.LabelFor(model => model.Name) // Works fine
@Html.LabelFor(model => model.Number) // Works fine

@{
    Expression<Func<Offer, object>> nameExpression = model => model.Name;
    Expression<Func<Offer, object>> numberExpression = model => model.Number;
}
@Html.LabelFor(nameExpression) // Works fine
@Html.LabelFor(numberExpression) // Error!

I noticed using the debugger that the lambda expression is model => Convert(model.Number), instead of model => model.Number, but this only happens to value types from what I can tell, as I have tested with integers (nullable and non-nullable) and DateTime objects. It seems that the NodeType for the lambda expression is Convert, for strings is Member access.

I know the cause of the error itself, but I don't know what causes the compiler to evaluate model=>model.Number to model => Convert(model.Number).

Thanks!

like image 809
florinszilagyi Avatar asked Dec 16 '13 14:12

florinszilagyi


1 Answers

There is a cast to convert model.Number from int to object. You can check that by looking at the expression with the debugger

.Lambda #Lambda1<System.Func`2[Model,System.Object]>(Model $model) {
    (System.Object)$model.Number
}

If you want to get the right expression you have to use Expression<Func<Model, int>>

Expression<Func<Model, int>> numberExpression = model => model.Number;

This expression is translated to

.Lambda #Lambda1<System.Func`2[Model,System.Int32]>(Model $model) {
    $model.Number
}
like image 70
meziantou Avatar answered Nov 11 '22 16:11

meziantou