ASP.NET MVC 4 Validation Notes

2013-11-15


Server Validation and Client side Validation:

We should know in ASP.NET MVC 4 (or 5 also), the web config items ClientValidationEnabled and UnobtrusiveJavaScriptEnabled are set to false by default, so unless we specified, all validations in ASP.MVC 4 are occurring on Server side.

If need Client Validation, we should either add the following into web.config:

… 
<configuration> 
  <appSettings> 
     <add key="ClientValidationEnabled" value="true" /> 
     <add key="UnobtrusiveJavaScriptEnabled" value="true" /> 
</appSettings> 
…

Or, Add the following code to Global.asax.cs file:

HtmlHelper.ClientValidationEnabled = true;

Or, Add the following code to a view file:

<% Html.ElableClientValidation(); %>
…
@section Scripts { 
    @Scripts.Render("~/bundles/jqueryval") 
}

Different ways to implement MVC validation:

1: In Action method in controller:

For example:

Model file:

public class MyTestModel 
{ 
     public string Name { get; set; } 
     public DateTime Date{ get; set; } 
     … 
}

in Controller:

[HttpGet] 
public ActionResult Test() 
{ 
    return View(); 
}

[HttpPost] 
public ActionResult Test(MyTestModel aTest) 
{
    if (string.IsNullOrEmpty(aTest.Name)) 
    { 
        ModelState.AddModelError("Name", "Please enter your name"); 
    }

    if (ModelState.IsValid) 
    { 
      // to do next after validation is ok 
      … 
    } 
    else 
    { 
        return View(); 
    } 
} 

View file:

@model testMvc4.Models.MyTestModel

@{ 
    ViewBag.Title = "Test"; 
}

<h2>Test</h2>

@using (Html.BeginForm()) { 
    
@Html.ValidationSummary()    
    
<p>Your name: @Html.EditorFor(x => x.Name) </p> 
<p>Your Date: @Html.TextBoxFor(x => x.Date)</p> 
<p>Your phone: @Html.TextBoxFor(x => x.Phone)</p>

<input type="submit" value="Submit" />  
}

2: Using Data Annotations (Metadata)

public class MyTestModel{ 
[Required] 
public string Name{ get; set; }

[DataType(DataType.Date)] 
[Required(ErrorMessage="Please enter a date")] 
public DateTime Date { get; set; } 
…}

The difference with above 1 is that we do not need to the following code in our controller action:

if (string.IsNullOrEmpty(aTest.Name)) 
    { 
        ModelState.AddModelError("Name", "Please enter your name"); 
    }

All other code should be the keep without changing.

 

Model level errors and Property level errors:

Please know both 1 and 2 in above Different ways to implement MVC validation section are belongs Property level errors (or call Property level validation), because they affect properties.

There is another validation or error: Model level errors.

We just add one line of code in our controller file to know what model level validation (error), please check the below bold code, it is just model level validation:

in Controller:

[HttpGet] 
public ActionResult Test() 
{ 
    return View(); 
}

[HttpPost] 
public ActionResult Test(MyTestModel aTest) 
{

    if (string.IsNullOrEmpty(aTest.Name)) 
    { 
        ModelState.AddModelError("Name", "Please enter your name"); 
    }

…

if (ModelState.IsValidField("Name") && ModelState.IsValidField("Date") 
&& …) { 
ModelState.AddModelError("", "this is model level error message"); 
}

    if (ModelState.IsValid) 
    { 
      // to do next after validation is ok 
      … 
    } 
    else 
    { 
        return View(); 
    } 
}

so how to display model level error message and property level message?

We should know something about Html.ValidationSummary:

  • Html.ValidationSummary():
    Generates a summary for all validation errors.

  • Html.ValidationSummary(bool):
    If the bool parameter is true, then only model-level errors are displayed (see the explanation after the table). If the parameter is false, then all errors are shown.

  • Html.ValidationSummary(string):
    Displays a message (contained in the string parameter) before a summary of all the validation errors.

  • Html.ValidationSummary(bool, string):
    Displays a message before the validation errors. If the bool parameter is true, only model-level errors will be shown.

So if you add Html.ValidationSummary(true) in View file, there will be only model level error display, otherwise, both model level error and property level errors will display. so we can use Html.ValidationSummary(true) combined with separate property error message to limit specified properties errors shown:

@model testMvc4.Models.MyTestModel

@{ 
    ViewBag.Title = "Test"; 
}

<h2>Test</h2>

@using (Html.BeginForm()) { 
    
@Html.ValidationSummary(true)    
    
<p>Your name: @Html.EditorFor(x => x.Name) </p> 
<p>@Html.ValidationMessageFor(x => x.Name)</p> 
<p>Your email: @Html.TextBoxFor(x => x.Date)</p> 

<p>Your phone: @Html.TextBoxFor(x => x.Phone)</p>

<input type="submit" value="Submit" />  
}

(here we only display the property Name’s error and Model level error, the date validation will not work.)