I'm currently attempting to create an HtmlHelper which takes in the same kind of expression as the built-in helpers LabelFor<>, DisplayFor<>, EditorFor<>, etc. but specifically for enumerated types:
e.g. model => model.MyEnumProperty
I'm new to the whole lambda expression thing and although I have been doing more or less okay so far (with a lot of help from other answers by the SackOverflow community) I'm now getting the following exception while trying to retrieve the object (i.e., model
) in the expression:
"variable 'model' of type 'WCSFAMembershipDatabase.Models.Address' referenced from scope '', but it is not defined"
public static MvcHtmlString EnumDisplayFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
{
// memberExp represents "model.MyEnumProperty"
MemberExpression memberExp = (MemberExpression)expression.Body;
if (memberExp == null)
{
throw new ArgumentException(string.Format(
"Expression '{0}' refers to a method, not a property.",
expression.ToString()));
}
// modelExp represents "model"
Expression modelExp = memberExp.Expression;
// Convert modelExp to a Lambda Expression that can be compiled into a delegate that returns a 'model' object
Expression<Func<TModel>> modelLambda = Expression.Lambda<Func<TModel>>(modelExp);
// Compile modelLambda into the delegate
// The next line is where the exception occurs...
Func<TModel> modelDel = modelLambda.Compile();
// Retrieve the 'model' object
TModel modelVal = modelDel();
// Compile the original expression into a delegate that accepts a 'model' object and returns the value of 'MyEnumProperty'
Func<TModel, TEnum> valueDel = expression.Compile();
// Retrieve 'MyEnumProperty' value
TEnum value = valueDel(modelVal);
// return the description or string value of 'MyEnumProperty'
return MvcHtmlString.Create(GetEnumDescription(value));
}
// Function returns the Description Attribute (if one exists) or the string
// representation for the specified enum value.
private static string GetEnumDescription<TEnum>(TEnum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
if ((attributes != null) && (attributes.Length > 0))
return attributes[0].Description;
else
return value.ToString();
}
The expression related code in EnumDisplayFor was cobbled together from details found at the following locations:
- http://blogs.msdn.com/b/csharpfaq/archive/2010/03/11/how-can-i-get-objects-and-property-values-from-expression-trees.aspx
- https://stackoverflow.com/a/672212
I did locate a few other questions that mention the same exception in relation to lambda expressions but they were all in a context where someone was manually crafting the expression tree and I couldn't figure out how the information in the answers might apply to my case.
I would really appreciate if anyone can explain (a) why the exception is occurring and (b) how I can fix it. :-)
Thanks, in advance.