Server Side Model Validation in MVC Razor


Server side validations are required for ensuring that the received data is correct and valid. If the received data is valid then we do the further processing with the data. Server side validations are very important before playing with sensitive information of a user.
Server-side validation must be done whether we validate the received data on the client side. User could disable script in his browser or do something else to bypass client-side validation. In this case server-side validation must required to protect our data from dirty input.

Server-side model validation technique

In MVC Razor, we can validate a model server side by below two ways:
  1. Explicit Model Validation
  2. Model Validation with Data Annotations

Explicit Model Validation

Suppose, you want to validate the registration process of a user for which the Registration model and view are defined as below:

RegistrationModel.cs

  1. public class RegistrationModel
  2. {
  3. public string UserName { get; set; }
  4. public string Password { get; set; }
  5. public string ConfirmPassword { get; set; }
  6. public Country Country { get; set; }
  7. public City City { get; set; }
  8. public string Address { get; set; }
  9. public string MobileNo { get; set; }
  10. public bool TermsAccepted { get; set; }
  11. }
  12.  
  13. public class Country
  14. {
  15. public int? ID { get; set; }
  16. public string Name { get; set; }
  17. }
  18.  
  19. public class City
  20. {
  21. public int? ID { get; set; }
  22. public string Name { get; set; }
  23. public int? Country { get; set; }
  24. }

ExplicitServer.cshtml

  1. @model Mvc4_Client_ServerSideValidation.Models.RegistrationModel
  2. @{
  3. ViewBag.Title = "Explicit Server Side Validation";
  4. }
  5. <script src="../../Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
  6. <script type="text/jscript">
  7. $(function () {
  8. $('#Country_ID').change(function () {
  9. var id = $("#Country_ID :selected").val();
  10. if (id != "") {
  11. $.ajax({
  12. type: "GET",
  13. contentType: "application/json; charset=utf-8",
  14. url: '@Url.Action("CityList", "Home")',
  15. data: { "mCountry": id },
  16. dataType: "json",
  17. success: function (data) {
  18. var items = "";
  19. $.each(data, function (i, city) {
  20. items += "<option value='" + city.Value + "'>" + city.Text + "</option>";
  21. });
  22. $('#City_ID').html(items);
  23. },
  24. error: function (result) {
  25. alert('Service call failed: ' + result.status + ' Type :' + result.statusText);
  26. }
  27. });
  28. }
  29. else
  30. {
  31. var items = '<option value="">Select</option>';
  32. $('#City_ID').html(items);
  33. } });
  34. });
  35. </script>
  36. <h2>Explicit Server Side Validation</h2> @using (Html.BeginForm())
  37. {
  38. <fieldset>
  39. <ol>
  40. <li>
  41. @Html.LabelFor(m => m.UserName)
  42. @Html.TextBoxFor(m => m.UserName, new { maxlength = 50 })
  43. @Html.ValidationMessageFor(m => m.UserName)
  44. </li>
  45. <li>
  46. @Html.LabelFor(m => m.Password)
  47. @Html.PasswordFor(m => m.Password, new { maxlength = 50, value = ViewBag.Selpwd })
  48. @Html.ValidationMessageFor(m => m.Password)
  49. </li>
  50. <li>
  51. @Html.LabelFor(m => m.ConfirmPassword)
  52. @Html.PasswordFor(m => m.ConfirmPassword, new { maxlength = 50, value = ViewBag.Selconfirmpwd })
  53. @Html.ValidationMessageFor(m => m.ConfirmPassword)
  54. </li>
  55. <li>
  56. @Html.LabelFor(m => m.Country)
  57. @Html.DropDownListFor(m => m.Country.ID, new SelectList(ViewBag.Country, "ID", "Name"), new { style = "width:310px" })
  58. @Html.ValidationMessageFor(m => m.Country)
  59. </li>
  60. <li>
  61. @Html.LabelFor(m => m.City)
  62. @Html.DropDownListFor(m => m.City.ID, new SelectList(ViewBag.City, "ID", "Name"), new { style = "width:310px" })
  63. @Html.ValidationMessageFor(m => m.City)
  64. </li>
  65. <li>
  66. @Html.LabelFor(m => m.Address)
  67. @Html.TextAreaFor(m => m.Address, new { maxlength = 200 })
  68. @Html.ValidationMessageFor(m => m.Address)
  69. </li>
  70. <li>
  71. @Html.LabelFor(m => m.MobileNo)
  72. @Html.TextBoxFor(m => m.MobileNo, new { maxlength = 10 })
  73. @Html.ValidationMessageFor(m => m.MobileNo)
  74. </li>
  75. <li>
  76. @Html.CheckBoxFor(m => m.TermsAccepted) I accept the terms & conditions
  77. @Html.ValidationMessageFor(m => m.TermsAccepted)
  78. </li>
  79. </ol>
  80. <input type="submit" value="Submit" />
  81. </fieldset>
  82. }
Now let's see how we validate the model explicitly?. To validate a model explicitly we need to validate received data with in the action method like as:
  1. [HttpPost]
  2. public ActionResult ExplicitServer(RegistrationModel mRegister)
  3. {
  4. //Write custom logic to validate RegistrationModel
  5. if (string.IsNullOrEmpty(mRegister.UserName))
  6. {
  7. ModelState.AddModelError("UserName", "Please enter your name");
  8. }
  9. if (!string.IsNullOrEmpty(mRegister.UserName))
  10. {
  11. Regex emailRegex = new Regex(".+@.+\\..+");
  12. if (!emailRegex.IsMatch(mRegister.UserName))
  13. ModelState.AddModelError("UserName", "Please enter correct email address");
  14. }
  15. if (string.IsNullOrEmpty(mRegister.Password))
  16. {
  17. ModelState.AddModelError("Password", "Please enter password");
  18. }
  19. if (string.IsNullOrEmpty(mRegister.ConfirmPassword))
  20. {
  21. ModelState.AddModelError("ConfirmPassword", "Please enter confirm password");
  22. }
  23. if (string.IsNullOrEmpty(mRegister.ConfirmPassword) && string.IsNullOrEmpty(mRegister.ConfirmPassword))
  24. {
  25. if (mRegister.ConfirmPassword != mRegister.Password)
  26. ModelState.AddModelError("ConfirmPassword", "Confirm password doesn't match");
  27. }
  28. if (mRegister.Country.ID == null || mRegister.Country.ID == 0)
  29. {
  30. ModelState.AddModelError("Country", "Please select Country");
  31. }
  32. if (mRegister.City.ID == null || mRegister.City.ID == 0)
  33. {
  34. ModelState.AddModelError("City", "Please select City");
  35. }
  36. if (string.IsNullOrEmpty(mRegister.Address))
  37. {
  38. ModelState.AddModelError("Address", "Please enter your address");
  39. }
  40. if (string.IsNullOrEmpty(mRegister.MobileNo))
  41. {
  42. ModelState.AddModelError("MobileNo", "Please enter your mobile no");
  43. }
  44. if (!mRegister.TermsAccepted)
  45. {
  46. ModelState.AddModelError("TermsAccepted", "You must accept the terms");
  47. }
  48. if (ModelState.IsValid)
  49. {
  50. return View("Completed");
  51. }
  52. else
  53. {
  54. ViewBag.Selpwd = mRegister.Password;
  55. ViewBag.Selconfirmpwd = mRegister.ConfirmPassword;
  56. BindCountry();
  57. if (mRegister.Country != null)
  58. BindCity(mRegister.Country.ID);
  59. else BindCity(null);
  60. return View();
  61. }
  62. }

How it works...

Afer running the project and navigating to ExplicitServer page you will get the below page. When you press the submit button on this page then it will post the data to the server and the code written with in ExplicitServer action will validate the input data. If input data is not valid then add error to model state by using method AddModelError() as shown above.
 
When all the validation will be passed then ModelState.IsValid returns true and you will be shown Completed view as shown in fig.

Model Validation with Data Annotations

The another and best way to validate a model by using Data Annotations. Data Annotations was introduced with .Net 3.5 SP1. It has a set of attributes and classes defined in the System.ComponentModel.DataAnnotations assembly. Data Annotations allow us to decorate model classes with metadata. This metadata describes a set of rules that are used to validate a property. For more help refer the article MVC Data Annotation.
In RegistrationModel.cs, I have defined one more model class RegistrationMetaModel by using data annotation and for which the view is defined as below:

RegistrationModel.cs

  1. public class RegistrationMetaModel
  2. {
  3. [Required(ErrorMessage = "Please Enter Email Address")]
  4. [Display(Name = "UserName (Email Address)")]
  5. [RegularExpression(".+@.+\\..+", ErrorMessage = "Please Enter Correct Email Address")]
  6. public string UserName { get; set; }
  7. [Required(ErrorMessage = "Please Enter Password")]
  8. [StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
  9. [DataType(DataType.Password)]
  10. [Display(Name = "Password")]
  11. public string Password { get; set; }
  12. [Required(ErrorMessage = "Please Enter Confirm Password")]
  13. [StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
  14. [DataType(DataType.Password)]
  15. [Display(Name = "Confirm password")]
  16. [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
  17. public string ConfirmPassword { get; set; }
  18. [Display(Name = "Country")] [ValidCountryAttribute(ErrorMessage = "Please Select Country")]
  19. public Country Country { get; set; }
  20. [Display(Name = "City")]
  21. [ValidCityAttribute(ErrorMessage = "Please Select City")]
  22. public City City { get; set; }
  23. [Required(ErrorMessage = "Please Enter Address")]
  24. [Display(Name = "Address")]
  25. [MaxLength(200)]
  26. public string Address { get; set; }
  27. [Required(ErrorMessage = "Please Enter Mobile No")]
  28. [Display(Name = "Mobile")]
  29. [StringLength(10, ErrorMessage = "The Mobile must contains 10 characters", MinimumLength = 10)]
  30. public string MobileNo { get; set; }
  31. [MustBeTrue(ErrorMessage = "Please Accept the Terms & Conditions")]
  32. public bool TermsAccepted { get; set; }
  33. }
  34.  
  35. public class MustBeTrueAttribute : ValidationAttribute
  36. {
  37. public override bool IsValid(object value)
  38. {
  39. return value is bool && (bool)value;
  40. }
  41. }
  42. public class ValidCountryAttribute : ValidationAttribute
  43. {
  44. public override bool IsValid(object value)
  45. {
  46. if (((Country)value).ID == null || ((Country)value).ID == 0)
  47. return false;
  48. else
  49. return true;
  50. }
  51. }
  52. public class ValidCityAttribute : ValidationAttribute
  53. {
  54. public override bool IsValid(object value)
  55. {
  56. if (((City)value).ID == null || ((City)value).ID == 0)
  57. return false;
  58. else
  59. return true;
  60. }
  61. }

ServerMeta.cshtml

  1. @model Mvc4_Model_ServerSideValidation.Models.RegistrationMetaModel
  2. @{
  3. ViewBag.Title = "Server Side Validation by Specifying Validation Rules Using Metadata";
  4. }
  5. <script src="../../Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
  6. <script type="text/jscript">
  7. $(function ()
  8. {
  9. $('#Country_ID').change(function ()
  10. {
  11. var id = $("#Country_ID :selected").val();
  12. if (id != "")
  13. {
  14. $.ajax({
  15. type: "GET",
  16. contentType: "application/json; charset=utf-8",
  17. url: '@Url.Action("CityList", "Home")',
  18. data: { "mCountry": id },
  19. dataType: "json",
  20. beforeSend: function () {
  21. },
  22. success: function (data) {
  23. var items = "";
  24. $.each(data, function (i, city) {
  25. items += "<option value='" + city.Value + "'>" + city.Text + "</option>";
  26. });
  27. $('#City_ID').html(items);
  28. },
  29. error: function (result) {
  30. alert('Service call failed: ' + result.status + ' Type :' + result.statusText);
  31. }
  32. });
  33. }
  34. else {
  35. var items = '<option value="">Select</option>';
  36. $('#City_ID').html(items);
  37. }
  38. });
  39. });
  40. </script>
  41. <h2>Server Side Validation by Specifying Validation Rules Using Metadata</h2>
  42. @using (Html.BeginForm())
  43. {
  44. <fieldset>
  45. <ol>
  46. <li>
  47. @Html.LabelFor(m => m.UserName)
  48. @Html.TextBoxFor(m => m.UserName, new { maxlength = 50 })
  49. @Html.ValidationMessageFor(m => m.UserName)
  50. </li>
  51. <li>
  52. @Html.LabelFor(m => m.Password)
  53. @Html.PasswordFor(m => m.Password, new { maxlength = 50, value = ViewBag.Selpwd })
  54. @Html.ValidationMessageFor(m => m.Password)
  55. </li>
  56. <li>
  57. @Html.LabelFor(m => m.ConfirmPassword)
  58. @Html.PasswordFor(m => m.ConfirmPassword, new { maxlength = 50, value = ViewBag.Selconfirmpwd })
  59. @Html.ValidationMessageFor(m => m.ConfirmPassword)
  60. </li>
  61. <li>
  62. @Html.LabelFor(m => m.Country)
  63. @Html.DropDownListFor(m => m.Country.ID, new SelectList(ViewBag.Country, "ID", "Name", ViewBag.SelCountry), new { style = "width:310px" })
  64. @Html.ValidationMessageFor(m => m.Country)
  65. </li>
  66. <li>
  67. @Html.LabelFor(m => m.City)
  68. @Html.DropDownListFor(m => m.City.ID, new SelectList(ViewBag.City, "ID", "Name", ViewBag.SelCity), new { style = "width:310px" })
  69. @Html.ValidationMessageFor(m => m.City)
  70. </li>
  71. <li>
  72. @Html.LabelFor(m => m.Address)
  73. @Html.TextAreaFor(m => m.Address, new { maxlength =200 })
  74. @Html.ValidationMessageFor(m => m.Address)
  75. </li>
  76. <li>
  77. @Html.LabelFor(m => m.MobileNo)
  78. @Html.TextBoxFor(m => m.MobileNo ,new { maxlength = 10 })
  79. @Html.ValidationMessageFor(m => m.MobileNo)
  80. </li>
  81. <li>
  82. @Html.CheckBoxFor(m => m.TermsAccepted) I accept the terms & conditions
  83. @Html.ValidationMessageFor(m => m.TermsAccepted)
  84. </li>
  85. </ol>
  86. <input type="submit" value="Submit" />
  87. </fieldset>
  88. }
Now let's see how we validate the model using data annotation?. To validate a model explicitly we need to validate received data with in the action method by checking ModelState.IsValid property. If it is false then error message will be shown automatically against each propety of model as shown below in fig.
  1. [HttpPost]
  2. public ActionResult ServerMeta(RegistrationMetaModel mRegister)
  3. {
  4. if (ModelState.IsValid)
  5. {
  6. return View("Completed");
  7. }
  8. else
  9. {
  10. ViewBag.Selpwd = mRegister.Password;
  11. ViewBag.Selconfirmpwd = mRegister.ConfirmPassword;
  12. BindCountry();
  13. if (mRegister.Country != null)
  14. BindCity(mRegister.Country.ID);
  15. else
  16. BindCity(null);
  17. return View();
  18. }
  19. }

How it works...

After running the project and navigating to Data Annotation-Server-Side page you will get the below page. When you press the submit button on this page then it will post the data to the server and the code written with in ServerMeta action will validate the input data by checking ModelState.IsValid property. If input data is not valid then ModelState.IsValid will return false and shown error as shown below.
 
When all the validation will be passed then ModelState.IsValid returns true and you will be shown Completed view as shown in fig.


Do you want more TechChaitu Updates ?
Enter your email address:

Comments

Popular posts from this blog

Download Visakhapatnam Tirupati AC Double Decker Express Act