Donate

ASP.NET Core MVC Model Validation Using Data Annotation Attributes And Bootstrap 4

Hi All!

In this post, I'll demonstrate how to perform a model validation to a form in ASP.NET Core 3.1 MVC using Data Annotation Attributes and Bootstrap 4+ with reference to jQuery unobtrusive validation scripts to show error on the page. This concept has been applied since the early days of ASP.NET until it's recent release of .NET 5. I have applied this solution to some of the projects I've worked either ASP.NET MVC 4 or ASP.NET MVC 5. Enough talk and let's get down to business by applying this topic in a ASP.NET Core 3.1 project.

First is to create an ASP.NET Core 3.1 MVC project using Visual Studio 2019 and add Bootstrap 4.0 package via NuGet as this will be used to style our form. In our Models folder, add an Employee class that contains common properties to describe an employee such as ID, Name and related data. Most of the properties are decorated with DataAnnotations attribute except for the Dependents since I'm only using a boolean value for that.
public class Employee
{
  public int EmployeeID { get; set; }

  [Display(Name ="Government ID")]
  [Required(ErrorMessage = "Government ID is required")]
  public string EmployeeGovtID { get; set; }

  [Display(Name = "Employee Name")]
  [Required(ErrorMessage = "Name is required")]
  public string EmployeeName { get; set; }

  [Required(ErrorMessage = "Age is required")]
  [Range(0, int.MaxValue, ErrorMessage = "Please enter integer number")]
  public int Age { get; set; }

  [Required(ErrorMessage = "Address is required")]
  public string Address { get; set; }

  [Required]
  [Range(1000, 99999.99, ErrorMessage = "Please enter value from 1000 to 99999.99")]
  public decimal Salary { get; set; }

  [Required(ErrorMessage = "Designation is required")]
  [MinLength(2, ErrorMessage = "Min length of designation is 2 characters")]
  public string Designation { get; set; }

  public bool HasDependents { get; set; }

  public Employee()
  {
	 EmployeeID = 0;
	 Address = string.Empty;
	 Salary = 0;
	 Age = 0;
	 Address = string.Empty;
	 EmployeeName = string.Empty;
	 Designation = string.Empty;
	 EmployeeGovtID = string.Empty;
	 HasDependents = false;
  }
}
Add another class in the Models folder called EmployeeViewModel with three properties for an Employee class, status message and a list of employees. For now, the list property has no direct use with the project. You may expand this tutorial to show save the employee record during form submission to the list object and display them using a separate view.
public class EmployeeViewModel
   {
      public Employee EmployeeRecord { get; set; }
      public string EmployeeSaveStatus { get; set; }
      public List<Employee> EmployeeRecords { get; set; }

      public EmployeeViewModel()
      {
         EmployeeRecord = new Employee();
         EmployeeSaveStatus = string.Empty;
         EmployeeRecords = new List<Employee>();
      }
   }
In the HomeController class, I added two IActionResult methods called CustomerRegistration that handle the GET and POST event of the form. The significant code here is in the POST method which assigns a success message to the view model's save status property if the form is successfully submitted. I also cleared the state of the model so that when the form reloads, the controls on the form will be reset.
public class HomeController : Controller
{
  private readonly ILogger<HomeController> _logger;

  public HomeController(ILogger<HomeController> logger)
  {
	 _logger = logger;
  }

  public IActionResult Index()
  {
	 return RedirectToAction("CustomerRegistration");
  }

  public IActionResult CustomerRegistration()
  {
	 return View();
  }

  [HttpPost]
  [ValidateAntiForgeryToken]
  public IActionResult CustomerRegistration(EmployeeViewModel empVM)
  {
	 if (ModelState.IsValid)
	 {
		empVM = new EmployeeViewModel();
		empVM.EmployeeSaveStatus = "Successfully submitted the form!";
	 }

	 ModelState.Clear();
	 return View(empVM);
  }

  public IActionResult Privacy()
  {
	 return View();
  }

  [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
  public IActionResult Error()
  {
	 return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
  }
}
Then add a view for the CustomerRegistration() action that has a form element with a collection of input elements that stores the user input and binds them to the model and span tags to display the error messages if a certain rule has been violated during form submission. The page also checks if the save status message has value and if true, display the status message inside a div with alert and dismissible classes.
@model ASPCoreValidation.Models.EmployeeViewModel

@{
    ViewData["Title"] = "Customer Registration";
}

<div id="status">
    @if (Model != null)
    {
        if (!string.IsNullOrEmpty(Model.EmployeeSaveStatus))
        {
            <div class="alert alert-success alert-dismissible">
                <button type="button" class="close" data-dismiss="alert">&times;</button>
                @Model.EmployeeSaveStatus
            </div>
        }
    }
</div>
<div class="container">
    <form id="frmCustomerRegistration" asp-controller="Home" asp-action="CustomerRegistration">
        <div id="headLine">
            <span>Customer Registration</span>
        </div>
        <hr />
        <div class="form-group row">
            <label asp-for="EmployeeRecord.EmployeeGovtID" class="col-3 col-form-label"></label>
            <div class="col-9">
                <input asp-for="EmployeeRecord.EmployeeGovtID" class="form-control" />
                <span id="validationGovt" asp-validation-for="EmployeeRecord.EmployeeGovtID" class="inputValidation"></span>
            </div>
        </div>
        <div class="form-group row">
            <label asp-for="EmployeeRecord.EmployeeName" class="col-3 col-form-label"></label>
            <div class="col-9">
                <input asp-for="EmployeeRecord.EmployeeName" class="form-control" />
                <span id="validationName" asp-validation-for="EmployeeRecord.EmployeeName" class="inputValidation"></span>
            </div>
        </div>
        <div class="form-group row">
            <label asp-for="EmployeeRecord.Age" class="col-3 col-form-label"></label>
            <div class="col-9">
                <input asp-for="EmployeeRecord.Age" class="form-control" />
                <span id="validationAge" asp-validation-for="EmployeeRecord.Age" class="inputValidation"></span>
            </div>
        </div>
        <div class="form-group row">
            <label asp-for="EmployeeRecord.Address" class="col-3 col-form-label"></label>
            <div class="col-9">
                <input asp-for="EmployeeRecord.Address" class="form-control" />
                <span id="validationAddress" asp-validation-for="EmployeeRecord.Address" class="inputValidation"></span>
            </div>
        </div>
        <div class="form-group row">
            <label asp-for="EmployeeRecord.Salary" class="col-3 col-form-label"></label>
            <div class="col-9">
                <input asp-for="EmployeeRecord.Salary" class="form-control" />
                <span id="validationSalary" asp-validation-for="EmployeeRecord.Salary" class="inputValidation"></span>
            </div>
        </div>
        <div class="form-group row">
            <label asp-for="EmployeeRecord.Designation" class="col-3 col-form-label"></label>
            <div class="col-9">
                <input asp-for="EmployeeRecord.Designation" class="form-control" />
                <span id="validationDesignation" asp-validation-for="EmployeeRecord.Designation" class="inputValidation"></span>
            </div>
        </div>
        <div class="form-group row">
            <div class="col-3">
            </div>
            <div class="col-9">
                <input id="chkDependents" class="form-check-input" type="checkbox" name="remember" asp-for="EmployeeRecord.HasDependents" />
                <span id="spnDependents">Dependents?</span>
            </div>
        </div>
        <div class="form-group row">
            <div class="col-3">
            </div>
            <div class="col-9">
                <button id="btnSubmit" type="submit" class="btn btn-primary">Submit</button>
            </div>
        </div>
    </form>
</div>

@section Scripts{
    <link href="~/css/Home.css" rel="stylesheet" />
}
The Home.css file contains styles that modifies the presentation of the form and validation controls.
.inputValidation{
    color:red;
}

#btnSubmit{
    width:120px !important;
    margin-left: 0px !important;
}

#frmCustomerRegistration{
    margin-top: 50px;
}

#chkDependents{
    margin-left: 0px !important;
}

#spnDependents{
    margin-left: 20px;
}

#headLine{
    text-align:center !important;
    font-weight:bold;
    font-size: 20px;
}
Add external references for the jQuery unobtrusive validation scripts in your _Layout.cshtml page.
    <script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.14.0/jquery.validate.min.js"></script>
    <script src="https://ajax.aspnetcdn.com/ajax/mvc/5.2.3/jquery.validate.unobtrusive.min.js"></script>
In your _ViewImports.cshtml, register the MVC tag helpers to make them available to the project.
@using ASPCoreValidation
@using ASPCoreValidation.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
If everything goes well when running your web application, you should see a form displayed on the browser.
ASP.NET Core MVC Model Validation Using Data Annotation Attributes And Bootstrap 4
If you're going to click the submit button right away, the validation error messages appear on screen.
ASP.NET Core MVC Model Validation Using Data Annotation Attributes And Bootstrap 4
Once you have successfully submitted the form, the save status success message appears.
ASP.NET Core MVC Model Validation Using Data Annotation Attributes And Bootstrap 4

Comments

Donate

Popular Posts From This Blog

WPF CRUD Application Using DataGrid, MVVM Pattern, Entity Framework, And C#.NET

TypeScript Error Or Bug: The term 'tsc' is not recognized as the name of a cmdlet, function, script file, or operable program.

Invalid nested tag div found, expected closing tag input