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!
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With