18

Is there a way to check if Validation Message exists for a particualr field in ASP.Net MVC 5. I need to check this in Razaor form

Currently is IsNullOrEmpty but i think ValidationMessage does return some html tags even if there are no validation errors ?

I need to show a div only if a Validation Message Exists i.e. validation has failed for that for a particaulr field.

abatishchev
  • 98,240
  • 88
  • 296
  • 433
knowledgeseeker
  • 1,163
  • 4
  • 15
  • 32

5 Answers5

44

You can access the ModelState through a property of ViewData in order to check for validation errors before outputting any HTML:

 @if(!ViewData.ModelState.IsValid) {
      @Html.ValidationMessageFor(...)
 }

Edit: or, if you're wanting to check a specific property:

 @if(ViewData.ModelState["PropertyName"] != null && ViewData.ModelState["PropertyName"].Errors.Any()) {
       @Html.ValidationMessageFor(...)
  }
Joseph Woodward
  • 9,191
  • 5
  • 44
  • 63
Ben Griffiths
  • 1,676
  • 15
  • 13
  • 1
    If the property key doesn't exist then you'll receive a `NullReferenceException`, so don't forget to check for null before trying to access the `Errors` property. – Joseph Woodward Sep 09 '15 at 11:37
5

This is the span created by @ValidationMessagefor() :

<span class="field-validation-error" data-valmsg-for="FieldName" data-valmsg-replace="true"><span for="FieldName" generated="true" class="">Field name is required.</span></span>

You can just check class "field-validation-error" whether it exists or not.

Kartikeya Khosla
  • 18,743
  • 8
  • 43
  • 69
3

This is a pretty dumb test, but usually sufficient, and has the added benefit of utilizing Intellisense in Visual Studio:

  1. Create Project/Helpers/HtmlHelper.cs as a new class

    using System.Web.Mvc;
    using System.Web.Mvc.Html;
    
    namespace Project.Helpers
    {
        public static class HtmlHelper
        {
            public static bool HasValidationMessageFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
            {
                var value = htmlHelper.ValidationMessageFor(expression).ToString();
    
                return value.Contains("field-validation-error");
            }
        }
    }
    
  2. Add that namespace to Views/Web.config:

    <configuration>
      <system.web.webPages.razor>
        <pages pageBaseType="System.Web.Mvc.WebViewPage">
          <namespaces>
            <add namespace="Project.Helpers" />
    
  3. Close and reopen the solution in Visual Studio, which I had to to for VS 2013 or Intellisense didn't pick up the new HTML helper in my Razor views

  4. Use it:

    @if (Html.HasValidationMessageFor(model => model.Property))
    {
        @* Do stuff *@
    }
    

Kartikeya's answer provided the markup generated by the Html.ValidatorMessageFor(...) method call:

<span class="field-validation-error" data-valmsg-for="FieldName" data-valmsg-replace="true">
    <span for="FieldName" generated="true" class="">
        Field name is required.
    </span>
</span>

(Code formatting, mine)

And as he said, testing for the field-validation-error class name should work fine.

Greg Burghardt
  • 17,900
  • 9
  • 49
  • 92
2

a) unknown or general custom added error display (non model property specific)

  if (ViewData.ModelState.Any(x => x.Key == string.Empty))
  {
      @Html.ValidationSummary(true, string.Empty, new { @class = "error")
  }

b) model property specific error display

@Html.ValidationMessageFor(m => m.Email, string.Empty, new { @class = "error" })
Rahul Uttarkar
  • 3,367
  • 3
  • 35
  • 40
0

I created a Html Helper to check if the ModelState is valid, and if has a error on the field, return a string (class name). I could have done this directly on the view, but I like a cleaner view. So, my class:

public static class ErrorHelper
{
    private static string GetPropertyName<TModel, TValue>(Expression<Func<TModel, TValue>> expression)
    {
        // Get field name
        // Code from: https://stackoverflow.com/a/2916344/4794469
        MemberExpression body = expression.Body as MemberExpression;
        if (body != null) return body.Member.Name;

        UnaryExpression ubody = expression.Body as UnaryExpression;
        if (ubody != null) body = ubody.Operand as MemberExpression;

        return body?.Member.Name;
    }

    public static MvcHtmlString ReturnOnError<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression, string @class)
    {
        var propertyName = GetPropertyName(expression);
        if (propertyName == null)
            return MvcHtmlString.Empty;

        if (htmlHelper.ViewData.ModelState.IsValid || !htmlHelper.ViewData.ModelState.ContainsKey(propertyName))
            return MvcHtmlString.Empty;

        return htmlHelper.ViewData.ModelState[propertyName].Errors.Any()
            ? MvcHtmlString.Create(@class)
            : MvcHtmlString.Empty;
    }
}

Imports:

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Web.Mvc;

How to use in the view:

<div class="form-group @Html.ReturnOnError(m => m.Name, "has-error")">
    ...
</div>

My original answer: https://stackoverflow.com/a/45329194/4794469

Roberto Correia
  • 1,696
  • 5
  • 20
  • 36