Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting full property name using ModelMetadata

Tags:

c#

asp.net-mvc

I'm trying to create an HtmlHelper that will create Bootstrap-compatible form fields. My first goal was to create an HtmlHelper that will create the surrounding div:

<div class="control-group"> ... </div>

Following the excellent advice here and also here I managed to get it to work relatively quickly. But it doesn't always work.

I have a ViewModel with a complex property, so in my form I access the field m=>m.Complex.Element . In my helper I check the element for validation errors. I use ModelMetadata.FromLambdaExpression(expression, html.ViewData) . The metadata I get back has the property name Element, and not Complex.Element.

When I check the ModelState for this property, I can't find it, because the ModelState keeps the full name - Complex.Element.

I can look for partial matches, hoping there's no other Element, but that seems like a nasty bug waiting to happen. How can I get the full property name from the expression?

like image 393
zmbq Avatar asked Oct 06 '12 23:10

zmbq


3 Answers

It's a good thing the MVC sources are out in the open. The proper way to get the ModelState property name is by using

var propertyName = ExpressionHelper.GetExpressionText(expression);
like image 163
zmbq Avatar answered Oct 22 '22 11:10

zmbq


I've used the following to get it for the current model before, you may have to append the property name to this to get it for the property though.

ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix;

Otherwise pull out reflector/ilspy/whatever and check what your EditorFor/TextBoxFor or whatever method is rendering your editor does.

like image 6
Betty Avatar answered Oct 22 '22 12:10

Betty


I've used a combination of both answers for an attribute I needed. Together, both of these answers provide a working attribute I can use in both views and nested editor templates. Here's my example:

public static MvcHtmlString HasErrorClassFor<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TProperty>> expression)
{
    string expressionText = ExpressionHelper.GetExpressionText(expression);

    string htmlFieldPrefix = htmlHelper.ViewData.TemplateInfo.HtmlFieldPrefix;

    string fullyQualifiedName;

    if (htmlFieldPrefix.Length > 0)
    {
        fullyQualifiedName = string.Join(".", htmlFieldPrefix, expressionText);
    }
    else
    {
        fullyQualifiedName = expressionText;
    }

    bool isValid = htmlHelper.ViewData.ModelState.IsValidField(fullyQualifiedName);

    if (!isValid)
    {
        return MvcHtmlString.Create("has-error");
    }

    return MvcHtmlString.Empty;
}
like image 4
Adrian Thompson Phillips Avatar answered Oct 22 '22 11:10

Adrian Thompson Phillips