Eugene Gluhotorenko
Eugene Gluhotorenko

Reputation: 3164

Asp.net mvc validation. How to specify several validation messages for one field in view

I have FormModel like this:

public class Model
{   
    [Required]
    [StringLength(10)]
    public string Name { get; set; }
}

I want to specify 2 different messages for RequiredAttribute and StringLengthAttribute. I don't want to specify my error messages in the validation attributes. I want to specify them in my view. But in my view I can do only something like this:

@Html.TextBoxFor(x => x.Name)
@Html.ValidationMessageFor(x => x.Name, "validation error")  

Anybody encountered this problem? Thanks in advance....

Upvotes: 1

Views: 574

Answers (1)

JimmiTh
JimmiTh

Reputation: 7449

There's no built-in way to do that. It was intentionally left out by the MVC developers, as far as I recall because they figured it would lead to a cluttered UI. It also introduces the question "How would you like them to be output?

So you'd have to make your own helper method, which can easily be based on ValidationMessageFor, e.g. - to concatenate all the error messages separated by commas (untested, just for the concept):

public static class ValidationHelpers
{
    public static MvcHtmlString MultiValidationMessageFor<TModel, TProperty>(
       this HtmlHelper<TModel> htmlHelper, 
       Expression<Func<TModel, TProperty>> expression, 
       object htmlAttributes = null
       )
    {
        var propertyName = ModelMetadata.FromLambdaExpression(
                              expression, htmlHelper.ViewData).PropertyName;
        var modelState = htmlHelper.ViewData.ModelState;

        if (modelState.ContainsKey(propertyName) && 
            modelState[propertyName].Errors.Count > 1)
        {
            // We have multiple error messages

            string messages = String.Join(", ", 
               modelState[propertyName].Errors.Select(e => e.ErrorMessage)
            );

            // Reuse the built-in helper that takes a string as the message:
            return htmlHelper.ValidationMessageFor(
               expression, 
               messages, 
               htmlAttributes as IDictionary<string, object> ?? htmlAttributes
            );
        }

        // We only have a single message, so just call the standard helper
        return htmlHelper.ValidationMessageFor(
           expression, 
           null, 
           htmlAttributes as IDictionary<string, object> ?? htmlAttributes
        );
    }
}

Or you could do a complete validation message <span> for each (also untested):

// Only the multiple error case changes from the version above:

if (modelState.ContainsKey(propertyName) && 
   modelState[propertyName].Errors.Count > 1)
{
   StringBuilder builder = new StringBuilder();

   // Build a complete validation message for each message
   foreach (ModelError error in modelState[propertyName].Errors)
   {
      builder.Append(
         htmlHelper.ValidationMessageFor(
            expression, error.ErrorMessage, htmlAttributes
         )
      );
   }

   return MvcHtmlString.Create(builder.ToString());
}

Upvotes: 3

Related Questions