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