4

I have a form with several inputs using Html.TextBoxFor and each input has a ValidationMessageFor which gets it's error message from the ViewModel attributes. For this example, we'll pretend there's just one input:

@Html.TextBoxFor(x => x.Code)
@Html.ValidationMessageFor(x => x.Code)

When there's a model error, the validator displays it's error message within a couple of spans which looks like this:

<input type="text" value="" name="Code" id="Code" data-val-required="Personalised code is required" data-val="true" class="input-validation-error">
<span data-valmsg-replace="true" data-valmsg-for="Code" class="field-validation-error">
    <span for="Code" generated="true" class="">Personalised code is required</span>
</span>

How do I customise this error message?

For example change the outer span to a div and give both the div and span clases?

<div class="myOuterSpan" data-valmsg-replace="true" data-valmsg-for="Code" class="field-validation-error">
    <span class="myInnerSpan" for="Code" generated="true" class="">Personalised code is required</span>
</div>

Or just have one span?

<span class="errorWrapper" for="Code" generated="true">Code is required</span>

Or wrap the whole lot in a div?

<div class="myOuterDiv">
    <span data-valmsg-replace="true" data-valmsg-for="Code" class="field-validation-error">
        <span for="Code" generated="true" class="">Personalised code is required</span>
    </span>
</div>

You get the idea...

THE SOLUTION

I based my solution on Darin's answer and created a CustomValidationMessage, not the customValidationMessageFOR as I was initially intending on creating.

CONTROLLER

ModelState.AddModelError("Code", "Invalid Code");

VIEW

@Html.CustomValidationMessage("Code")

EXTENSION

public static class Extensions
{
    public static MvcHtmlString CustomValidationMessage(this HtmlHelper htmlHelper, string modelName)
    {
        var modelState = htmlHelper.ViewData.ModelState[modelName];
        var modelErrors = modelState == null ? null : modelState.Errors;
        var modelError = ((modelErrors == null) || (modelErrors.Count == 0))
            ? null
            : modelErrors.FirstOrDefault(e => !string.IsNullOrEmpty(e.ErrorMessage)) ?? modelErrors[0];

        if (modelError != null)
        {
            return MvcHtmlString.Create("<span class='validation_wrapper customValidation'><span>" + modelError.ErrorMessage +"</span></span>");
        }

        return new MvcHtmlString(string.Empty);
    }
}
1
  • have you see this? Commented Feb 27, 2013 at 12:34

2 Answers 2

5

There's no way to modify the markup generated by the ValidationMessageFor helper. If you want to do that you will have to write a custom helper. Here's how the signature of this helper might look like:

public static MvcHtmlString CustomValidationMessageFor<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper, 
    Expression<Func<TModel, TProperty>> expression
)
{
    ...
}

You might also checkout a similar post.

Sign up to request clarification or add additional context in comments.

1 Comment

You can modify the markup slightly. I updated my answer below.
1

There's really no need for a custom extension. For example:

Controller:

ModelState.AddModelError("InvalidLogin", "Your credentials are invalid.")

View:

@Html.ValidationMessageFor
(
  model => model.InvalidLogin, 
  "", 
  htmlAttributes: new { @class = "text-error" }, 
  tag: "div"
)

2 Comments

Yeah that works if you've only got one validation message, but what if you have several, do you wrap each one in a span?
Yes. Unless you have some complex markup. However, most of the time a div or a span with a custom class does the trick.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.