Form Tag Helpers in ASP.NET Core MVC

Form Tag Helpers in ASP.NET Core MVC

In this article, I will discuss the Form Tag Helpers in an ASP.NET Core MVC Application with Examples. Please read our previous article about Responsive Navigation Menus in ASP.NET Core Applications. 

What are the Tag Helpers used to Create a Form in ASP.NET Core MVC?

Tag Helpers in ASP.NET Core MVC make binding and generating HTML elements in Razor views easier. ASP.NET Core MVC Framework provides several Tag Helpers to simplify form generation, binding, and validation when creating forms. Let us understand this with an example. We will create a form using Tag Helpers, as shown below. The following form is used to create a student.

Form Tag Helpers in ASP.NET Core MVC

Let us proceed and implement this step by step. First, create a new ASP.NET Core MVC Application using the Model View Controller Project template and give the project name FormTagHelperDemo.

Creating Models:

First, we need to create two Enums to hold the Gender and Branch-named constants and the Student model, which will hold the student data.

Creating Gender Enum:

The Gender enum is a strongly typed list of constants representing the gender options available in the student registration form. It helps avoid hard-coding gender strings and ensures that only predefined values (Male, Female, or Other) can be selected. So, create a class file named Gender.cs within the Models folder and copy and paste the following code.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
namespace FormTagHelperDemo.Models
{
public enum Gender
{
Male,
Female,
Other
}
}
namespace FormTagHelperDemo.Models { public enum Gender { Male, Female, Other } }
namespace FormTagHelperDemo.Models
{
    public enum Gender
    {
        Male,
        Female,
        Other
    }
}
Creating Branch Enum

Like the Gender enum, the Branch enum provides a list of fixed values representing different branches of study, such as CSE (Computer Science), ETC (Electronics & Telecommunications), Mechanical, and Electrical. This ensures that users select only valid branch options when filling out the form. So, create a class file named Branch.cs within the Models folder and copy and paste the following code.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
namespace FormTagHelperDemo.Models
{
public enum Branch
{
CSE,
ETC,
Mechanical,
Electrical
}
}
namespace FormTagHelperDemo.Models { public enum Branch { CSE, ETC, Mechanical, Electrical } }
namespace FormTagHelperDemo.Models
{
    public enum Branch
    {
        CSE,
        ETC,
        Mechanical,
        Electrical
    }
}
Creating Student Model

The Student class represents the model for student registration in our application. It defines the data structure and validation rules for the student entity. This class will be used in views and controllers to handle the data inputted by users. It includes properties for storing student information, such as FullName, Password, DateOfBirth, Gender, Address, Branch, etc. The class also uses data annotations to specify validation rules, like requiring certain fields and limiting the length of strings. So, create a class file named Student.cs within the Models folder and then copy and paste the following code.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
using System.ComponentModel.DataAnnotations;
namespace FormTagHelperDemo.Models
{
public class Student
{
public int? StudentId { get; set; }
[Display(Name ="Full Name")]
[Required(ErrorMessage = "Name is required")]
[StringLength(50)]
public string FullName { get; set; }
[Required(ErrorMessage = "Password is required")]
[DataType(DataType.Password)]
public string Password { get; set; }
[Required(ErrorMessage = "Date of Birth is required")]
[DataType(DataType.Date)]
public DateTime DateOfBirth { get; set; }
[Required(ErrorMessage = "Gender is required")]
public Gender Gender { get; set; }
[Required(ErrorMessage = "Address is required")]
[StringLength(500)]
public string Address { get; set; }
[Required(ErrorMessage = "Branch is required")]
public Branch Branch { get; set; }
public bool TermsAndConditions { get; set; }
public List<string> Hobbies { get; set; } = new List<string>();
[Required(ErrorMessage = "At least one skill is required")]
public List<string> Skills { get; set; } = new List<string>();
}
}
using System.ComponentModel.DataAnnotations; namespace FormTagHelperDemo.Models { public class Student { public int? StudentId { get; set; } [Display(Name ="Full Name")] [Required(ErrorMessage = "Name is required")] [StringLength(50)] public string FullName { get; set; } [Required(ErrorMessage = "Password is required")] [DataType(DataType.Password)] public string Password { get; set; } [Required(ErrorMessage = "Date of Birth is required")] [DataType(DataType.Date)] public DateTime DateOfBirth { get; set; } [Required(ErrorMessage = "Gender is required")] public Gender Gender { get; set; } [Required(ErrorMessage = "Address is required")] [StringLength(500)] public string Address { get; set; } [Required(ErrorMessage = "Branch is required")] public Branch Branch { get; set; } public bool TermsAndConditions { get; set; } public List<string> Hobbies { get; set; } = new List<string>(); [Required(ErrorMessage = "At least one skill is required")] public List<string> Skills { get; set; } = new List<string>(); } }
using System.ComponentModel.DataAnnotations;

namespace FormTagHelperDemo.Models
{
    public class Student
    {
        public int? StudentId { get; set; }

        [Display(Name ="Full Name")]
        [Required(ErrorMessage = "Name is required")]
        [StringLength(50)]
        public string FullName { get; set; }

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

        [Required(ErrorMessage = "Date of Birth is required")]
        [DataType(DataType.Date)]
        public DateTime DateOfBirth { get; set; }

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

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

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

        public bool TermsAndConditions { get; set; }

        public List<string> Hobbies { get; set; } = new List<string>();

        [Required(ErrorMessage = "At least one skill is required")]
        public List<string> Skills { get; set; } = new List<string>();
    }
}
Creating the Student Controller:

Next, create an Empty MVC controller named StudentController within the Controllers folder and copy and paste the following code. The following StudentController manages operations related to student registration, viewing student lists, and displaying student details. The controller interacts with the Student model and handles incoming HTTP requests for student-related actions.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
using Microsoft.AspNetCore.Mvc;
using FormTagHelperDemo.Models;
namespace FormTagHelperDemo.Controllers
{
public class StudentController : Controller
{
// Simulated in-memory storage with hardcoded data for demonstration purposes
private static List<Student> students = new List<Student>
{
new Student
{
StudentId = 1, FullName = "Pranaya Rout", Password = "Password123!",
DateOfBirth = new DateTime(1990, 1, 1), Gender = Gender.Male, Address = "Test Address 1234",
Branch = Branch.CSE, TermsAndConditions = true,
Hobbies = new List<string> { "Reading", "Traveling" },
Skills = new List<string> { "C#", "SQL" }
},
new Student
{
StudentId = 2, FullName = "Hina Sharma", Password = "Password123!",
DateOfBirth = new DateTime(1992, 2, 15), Gender = Gender.Female, Address = "Test Address 1234",
Branch = Branch.ETC, TermsAndConditions = true,
Hobbies = new List<string> { "Music", "Traveling" },
Skills = new List<string> { "Python", "Machine Learning" }
},
new Student
{
StudentId = 3, FullName = "Anurag Mohanty", Password = "Password123!",
DateOfBirth = new DateTime(1988, 11, 23), Gender = Gender.Male, Address = "Test Address 1234",
Branch = Branch.Mechanical, TermsAndConditions = true,
Hobbies = new List<string> { "Reading", "Music" },
Skills = new List<string> { "ASP.NET Core", "Oracle" }
}
};
// GET: Student/List
[HttpGet]
public IActionResult List()
{
// Return the list of students to the view
return View(students);
}
// GET: Student/Details/{id}
[HttpGet]
public IActionResult Details(int id)
{
// Find the student by Id
var student = listStudents.FirstOrDefault(std => std.StudentId == Id);
if (student == null)
{
return NotFound();
}
// Return the student details view
return View(student);
}
// GET: Student/Register
[HttpGet]
public IActionResult Register()
{
// Ensure the Hobbies list is initialized
var student = new Student
{
Hobbies = new List<string>() // Initialize to prevent null reference issues
};
// Pass the list of available hobbies and skills to the view
ViewBag.Hobbies = new List<string> { "Reading", "Traveling", "Music", "Sports", "Photography" };
ViewBag.Skills = new List<string> { "C#", "Python", "SQL", "Machine Learning", "ASP.NET Core", "Oracle", "Data Analysis" };
return View(student);
}
// POST: Student/Register
[HttpPost]
public IActionResult Register(Student student)
{
if (ModelState.IsValid)
{
//Generated the Student Id
student.StudentId = students.Count() + 1;
// Add the student to the list
students.Add(student);
// Redirect to the List page after successful registration
return RedirectToAction("List");
}
// Pass the list of available hobbies and skills back to the view in case of errors
ViewBag.Hobbies = new List<string> { "Reading", "Traveling", "Music", "Sports", "Photography" };
ViewBag.Skills = new List<string> { "C#", "Python", "SQL", "Machine Learning", "Physics", "Research", "Data Analysis" };
// If invalid, return the same view with validation messages
return View(student);
}
}
}
using Microsoft.AspNetCore.Mvc; using FormTagHelperDemo.Models; namespace FormTagHelperDemo.Controllers { public class StudentController : Controller { // Simulated in-memory storage with hardcoded data for demonstration purposes private static List<Student> students = new List<Student> { new Student { StudentId = 1, FullName = "Pranaya Rout", Password = "Password123!", DateOfBirth = new DateTime(1990, 1, 1), Gender = Gender.Male, Address = "Test Address 1234", Branch = Branch.CSE, TermsAndConditions = true, Hobbies = new List<string> { "Reading", "Traveling" }, Skills = new List<string> { "C#", "SQL" } }, new Student { StudentId = 2, FullName = "Hina Sharma", Password = "Password123!", DateOfBirth = new DateTime(1992, 2, 15), Gender = Gender.Female, Address = "Test Address 1234", Branch = Branch.ETC, TermsAndConditions = true, Hobbies = new List<string> { "Music", "Traveling" }, Skills = new List<string> { "Python", "Machine Learning" } }, new Student { StudentId = 3, FullName = "Anurag Mohanty", Password = "Password123!", DateOfBirth = new DateTime(1988, 11, 23), Gender = Gender.Male, Address = "Test Address 1234", Branch = Branch.Mechanical, TermsAndConditions = true, Hobbies = new List<string> { "Reading", "Music" }, Skills = new List<string> { "ASP.NET Core", "Oracle" } } }; // GET: Student/List [HttpGet] public IActionResult List() { // Return the list of students to the view return View(students); } // GET: Student/Details/{id} [HttpGet] public IActionResult Details(int id) { // Find the student by Id var student = listStudents.FirstOrDefault(std => std.StudentId == Id); if (student == null) { return NotFound(); } // Return the student details view return View(student); } // GET: Student/Register [HttpGet] public IActionResult Register() { // Ensure the Hobbies list is initialized var student = new Student { Hobbies = new List<string>() // Initialize to prevent null reference issues }; // Pass the list of available hobbies and skills to the view ViewBag.Hobbies = new List<string> { "Reading", "Traveling", "Music", "Sports", "Photography" }; ViewBag.Skills = new List<string> { "C#", "Python", "SQL", "Machine Learning", "ASP.NET Core", "Oracle", "Data Analysis" }; return View(student); } // POST: Student/Register [HttpPost] public IActionResult Register(Student student) { if (ModelState.IsValid) { //Generated the Student Id student.StudentId = students.Count() + 1; // Add the student to the list students.Add(student); // Redirect to the List page after successful registration return RedirectToAction("List"); } // Pass the list of available hobbies and skills back to the view in case of errors ViewBag.Hobbies = new List<string> { "Reading", "Traveling", "Music", "Sports", "Photography" }; ViewBag.Skills = new List<string> { "C#", "Python", "SQL", "Machine Learning", "Physics", "Research", "Data Analysis" }; // If invalid, return the same view with validation messages return View(student); } } }
using Microsoft.AspNetCore.Mvc;
using FormTagHelperDemo.Models;
namespace FormTagHelperDemo.Controllers
{
    public class StudentController : Controller
    {
        // Simulated in-memory storage with hardcoded data for demonstration purposes
        private static List<Student> students = new List<Student>
        {
            new Student
            {
                StudentId = 1, FullName = "Pranaya Rout", Password = "Password123!",
                DateOfBirth = new DateTime(1990, 1, 1), Gender = Gender.Male, Address = "Test Address 1234",
                Branch = Branch.CSE, TermsAndConditions = true,
                Hobbies = new List<string> { "Reading", "Traveling" },
                Skills = new List<string> { "C#", "SQL" }
            },
            new Student
            {
                StudentId = 2, FullName = "Hina Sharma", Password = "Password123!",
                DateOfBirth = new DateTime(1992, 2, 15), Gender = Gender.Female, Address = "Test Address 1234",
                Branch = Branch.ETC, TermsAndConditions = true,
                Hobbies = new List<string> { "Music", "Traveling" },
                Skills = new List<string> { "Python", "Machine Learning" }
            },
            new Student
            {
                StudentId = 3, FullName = "Anurag Mohanty", Password = "Password123!",
                DateOfBirth = new DateTime(1988, 11, 23), Gender = Gender.Male, Address = "Test Address 1234",
                Branch = Branch.Mechanical, TermsAndConditions = true,
                Hobbies = new List<string> { "Reading", "Music" },
                Skills = new List<string> { "ASP.NET Core", "Oracle" }
            }
        };

        // GET: Student/List
        [HttpGet]
        public IActionResult List()
        {
            // Return the list of students to the view
            return View(students);
        }

        // GET: Student/Details/{id}
        [HttpGet]
        public IActionResult Details(int id)
        {
            // Find the student by Id
           var student = listStudents.FirstOrDefault(std => std.StudentId == Id);

            if (student == null)
            {
                return NotFound();
            }

            // Return the student details view
            return View(student);
        }

        // GET: Student/Register
        [HttpGet]
        public IActionResult Register()
        {
            // Ensure the Hobbies list is initialized
            var student = new Student
            {
                Hobbies = new List<string>()  // Initialize to prevent null reference issues
            };

            // Pass the list of available hobbies and skills to the view
            ViewBag.Hobbies = new List<string> { "Reading", "Traveling", "Music", "Sports", "Photography" };
            ViewBag.Skills = new List<string> { "C#", "Python", "SQL", "Machine Learning", "ASP.NET Core", "Oracle", "Data Analysis" };
            return View(student);
        }

        // POST: Student/Register
        [HttpPost]
        public IActionResult Register(Student student)
        {
            if (ModelState.IsValid)
            {
                //Generated the Student Id
                student.StudentId = students.Count() + 1;

                // Add the student to the list
                students.Add(student);

                // Redirect to the List page after successful registration
                return RedirectToAction("List");
            }

            // Pass the list of available hobbies and skills back to the view in case of errors
            ViewBag.Hobbies = new List<string> { "Reading", "Traveling", "Music", "Sports", "Photography" };
            ViewBag.Skills = new List<string> { "C#", "Python", "SQL", "Machine Learning", "Physics", "Research", "Data Analysis" };

            // If invalid, return the same view with validation messages
            return View(student);
        }      
    }
}
Creating Student List View:

Next, create a view named List.cshtml within the Views/Student folder and then copy and paste the following code. The following view is to display a list of students in a tabular format and provide actions (such as viewing details) for each student. This view is typically rendered by the StudentController’s List action, which passes a collection of Student objects to the view as the model.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@model IEnumerable<Student>
@{
ViewData["Title"] = "Student List";
}
<h2>Student List</h2>
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Date of Birth</th>
<th>Branch</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
@foreach(var student in Model)
{
<tr>
<td>@student.FullName</td>
<td>@student.DateOfBirth.ToShortDateString()</td>
<td>@student.Branch</td>
<td>
<a asp-action="Details" asp-route-id="@student.StudentId" class="btn btn-info">Details</a>
</td>
</tr>
}
</tbody>
</table>
@model IEnumerable<Student> @{ ViewData["Title"] = "Student List"; } <h2>Student List</h2> <table class="table table-striped"> <thead> <tr> <th>Name</th> <th>Date of Birth</th> <th>Branch</th> <th>Actions</th> </tr> </thead> <tbody> @foreach(var student in Model) { <tr> <td>@student.FullName</td> <td>@student.DateOfBirth.ToShortDateString()</td> <td>@student.Branch</td> <td> <a asp-action="Details" asp-route-id="@student.StudentId" class="btn btn-info">Details</a> </td> </tr> } </tbody> </table>
@model IEnumerable<Student>

@{
    ViewData["Title"] = "Student List";
}

<h2>Student List</h2>

<table class="table table-striped">
    <thead>
        <tr>
            <th>Name</th>
            <th>Date of Birth</th>
            <th>Branch</th>
            <th>Actions</th>
        </tr>
    </thead>
    <tbody>
       @foreach(var student in Model)
        {
            <tr>
                <td>@student.FullName</td>
                <td>@student.DateOfBirth.ToShortDateString()</td>
                <td>@student.Branch</td>
                <td>
                    <a asp-action="Details" asp-route-id="@student.StudentId" class="btn btn-info">Details</a>
                </td>
            </tr>
        }
    </tbody>
</table>
Creating Student Details View:

Next, create a view named Details.cshtml within the Views/Student folder and then copy and paste the following code. The following view is to display detailed information about a specific student. It provides a clear and organized presentation of the student’s data using a card layout with Bootstrap styling. This view is typically rendered by the Details action of the StudentController, where a specific student is passed as the model. The “Back to List” button allows for easy navigation to the List View Page.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@model FormTagHelperDemo.Models.Student
@{
ViewData["Title"] = "Student Details";
}
<h2 class="text-center mb-4">Student Details</h2>
<div class="container">
<div class="card border-primary">
<div class="card-body">
<div class="row mb-3">
<!-- First Name -->
<div class="col-md-4 font-weight-bold">
Full Name:
</div>
<div class="col-md-8">
<p class="mb-0">@Model.FullName</p>
</div>
</div>
<div class="row mb-3">
<!-- Date of Birth -->
<div class="col-md-4 font-weight-bold">
Date of Birth:
</div>
<div class="col-md-8">
<p class="mb-0">@Model.DateOfBirth.ToShortDateString()</p>
</div>
</div>
<div class="row mb-3">
<!-- Gender -->
<div class="col-md-4 font-weight-bold">
Gender:
</div>
<div class="col-md-8">
<p class="mb-0">@Model.Gender</p>
</div>
</div>
<div class="row mb-3">
<!-- Address -->
<div class="col-md-4 font-weight-bold">
Address:
</div>
<div class="col-md-8">
<p class="mb-0">@Model.Address</p>
</div>
</div>
<div class="row mb-3">
<!-- Branch -->
<div class="col-md-4 font-weight-bold">
Branch:
</div>
<div class="col-md-8">
<p class="mb-0">@Model.Branch</p>
</div>
</div>
<div class="row mb-3">
<!-- Hobbies -->
<div class="col-md-4 font-weight-bold">
Hobbies:
</div>
<div class="col-md-8">
<p class="mb-0">@string.Join(", ", @Model.Hobbies)</p>
</div>
</div>
<div class="row mb-3">
<!-- Skills -->
<div class="col-md-4 font-weight-bold">
Skills:
</div>
<div class="col-md-8">
<p class="mb-0">@string.Join(", ", @Model.Skills)</p>
</div>
</div>
</div>
</div>
<div class="text-center mt-4">
<a asp-action="List" class="btn btn-primary">Back to List</a>
</div>
</div>
@model FormTagHelperDemo.Models.Student @{ ViewData["Title"] = "Student Details"; } <h2 class="text-center mb-4">Student Details</h2> <div class="container"> <div class="card border-primary"> <div class="card-body"> <div class="row mb-3"> <!-- First Name --> <div class="col-md-4 font-weight-bold"> Full Name: </div> <div class="col-md-8"> <p class="mb-0">@Model.FullName</p> </div> </div> <div class="row mb-3"> <!-- Date of Birth --> <div class="col-md-4 font-weight-bold"> Date of Birth: </div> <div class="col-md-8"> <p class="mb-0">@Model.DateOfBirth.ToShortDateString()</p> </div> </div> <div class="row mb-3"> <!-- Gender --> <div class="col-md-4 font-weight-bold"> Gender: </div> <div class="col-md-8"> <p class="mb-0">@Model.Gender</p> </div> </div> <div class="row mb-3"> <!-- Address --> <div class="col-md-4 font-weight-bold"> Address: </div> <div class="col-md-8"> <p class="mb-0">@Model.Address</p> </div> </div> <div class="row mb-3"> <!-- Branch --> <div class="col-md-4 font-weight-bold"> Branch: </div> <div class="col-md-8"> <p class="mb-0">@Model.Branch</p> </div> </div> <div class="row mb-3"> <!-- Hobbies --> <div class="col-md-4 font-weight-bold"> Hobbies: </div> <div class="col-md-8"> <p class="mb-0">@string.Join(", ", @Model.Hobbies)</p> </div> </div> <div class="row mb-3"> <!-- Skills --> <div class="col-md-4 font-weight-bold"> Skills: </div> <div class="col-md-8"> <p class="mb-0">@string.Join(", ", @Model.Skills)</p> </div> </div> </div> </div> <div class="text-center mt-4"> <a asp-action="List" class="btn btn-primary">Back to List</a> </div> </div>
@model FormTagHelperDemo.Models.Student

@{
    ViewData["Title"] = "Student Details";
}

<h2 class="text-center mb-4">Student Details</h2>

<div class="container">
    <div class="card border-primary">
        <div class="card-body">
            <div class="row mb-3">
                <!-- First Name -->
                <div class="col-md-4 font-weight-bold">
                    Full Name:
                </div>
                <div class="col-md-8">
                    <p class="mb-0">@Model.FullName</p>
                </div>
            </div>

            <div class="row mb-3">
                <!-- Date of Birth -->
                <div class="col-md-4 font-weight-bold">
                    Date of Birth:
                </div>
                <div class="col-md-8">
                    <p class="mb-0">@Model.DateOfBirth.ToShortDateString()</p>
                </div>
            </div>

            <div class="row mb-3">
                <!-- Gender -->
                <div class="col-md-4 font-weight-bold">
                    Gender:
                </div>
                <div class="col-md-8">
                    <p class="mb-0">@Model.Gender</p>
                </div>
            </div>

            <div class="row mb-3">
                <!-- Address -->
                <div class="col-md-4 font-weight-bold">
                    Address:
                </div>
                <div class="col-md-8">
                    <p class="mb-0">@Model.Address</p>
                </div>
            </div>

            <div class="row mb-3">
                <!-- Branch -->
                <div class="col-md-4 font-weight-bold">
                    Branch:
                </div>
                <div class="col-md-8">
                    <p class="mb-0">@Model.Branch</p>
                </div>
            </div>

            <div class="row mb-3">
                <!-- Hobbies -->
                <div class="col-md-4 font-weight-bold">
                    Hobbies:
                </div>
                <div class="col-md-8">
                    <p class="mb-0">@string.Join(", ", @Model.Hobbies)</p>
                </div>
            </div>

            <div class="row mb-3">
                <!-- Skills -->
                <div class="col-md-4 font-weight-bold">
                    Skills:
                </div>
                <div class="col-md-8">
                    <p class="mb-0">@string.Join(", ", @Model.Skills)</p>
                </div>
            </div>
        </div>
    </div>

    <div class="text-center mt-4">
        <a asp-action="List" class="btn btn-primary">Back to List</a>
    </div>
</div>
Creating Student Register View:

Next, create a view named Register.cshtml within the Views/Student folder and copy and paste the following code. The following view is to provide a registration form for students, allowing users to input various details about a student and submit the form. This view is designed to interact with the Register action of the StudentController, which handles both displaying the form (GET request) and processing the submitted data (POST request).

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@model FormTagHelperDemo.Models.Student
@{
ViewData["Title"] = "Student Registration";
}
<h2 class="mb-4">Student Registration</h2>
<form asp-action="Register" asp-controller="Student" method="post" class="form-horizontal">
<!-- Name Input -->
<div class="form-group row mb-3">
<label asp-for="FullName" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<input asp-for="FullName" class="form-control" />
<span asp-validation-for="FullName" class="text-danger"></span>
</div>
</div>
<!-- Password Input -->
<div class="form-group row mb-3">
<label asp-for="Password" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<input asp-for="Password" type="password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
</div>
<!-- Date of Birth Input -->
<div class="form-group row mb-3">
<label asp-for="DateOfBirth" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<input asp-for="DateOfBirth" type="date" class="form-control" value="@Model.DateOfBirth.ToString("yyyy-MM-dd")" />
<span asp-validation-for="DateOfBirth" class="text-danger"></span>
</div>
</div>
<!-- Gender Radio Buttons (using Enum) -->
<div class="form-group row mb-3">
<label class="col-sm-2 col-form-label">Gender</label>
<div class="col-sm-10">
@foreach (var gender in Enum.GetValues(typeof(FormTagHelperDemo.Models.Gender)))
{
<div class="form-check form-check-inline">
<input type="radio" asp-for="Gender" value="@gender" class="form-check-input" />
<label class="form-check-label">@gender</label>
</div>
}
<span asp-validation-for="Gender" class="text-danger"></span>
</div>
</div>
<!-- Address Text Area -->
<div class="form-group row mb-3">
<label asp-for="Address" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<textarea asp-for="Address" class="form-control"></textarea>
<span asp-validation-for="Address" class="text-danger"></span>
</div>
</div>
<!-- Branch Drop Down List (using Enum) -->
<div class="form-group row mb-3">
<label asp-for="Branch" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<select asp-for="Branch" class="form-control">
<option value="">-- Select Branch --</option>
@foreach (var branch in Enum.GetValues(typeof(FormTagHelperDemo.Models.Branch)))
{
<option value="@branch">@branch</option>
}
</select>
<span asp-validation-for="Branch" class="text-danger"></span>
</div>
</div>
<!-- Hobbies Multi-Select Check Box -->
<div class="form-group row mb-3">
<label class="col-sm-2 col-form-label">Hobbies</label>
<div class="col-sm-10">
@foreach (var hobby in ViewBag.Hobbies as List<string>)
{
<div class="form-check form-check-inline">
<input type="checkbox" class="form-check-input" name="Hobbies" value="@hobby"
@(Model.Hobbies != null && Model.Hobbies.Contains(hobby) ? "checked" : "") />
<label class="form-check-label">@hobby</label>
</div>
}
</div>
</div>
<!-- Skills List Box with multiple selection -->
<div class="form-group row mb-3">
<label asp-for="Skills" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<select asp-for="Skills" class="form-control" multiple>
@foreach (var skill in ViewBag.Skills as List<string>)
{
<option value="@skill">@skill</option>
}
</select>
<span asp-validation-for="Skills" class="text-danger"></span>
</div>
</div>
<!-- Terms and Conditions Single Check Box -->
<div class="form-group row mb-3">
<div class="col-sm-2"></div>
<div class="col-sm-10">
<div class="form-check">
<input asp-for="TermsAndConditions" type="checkbox" class="form-check-input" />
<label class="form-check-label" for="TermsAndConditions">I agree to the terms and conditions</label>
</div>
</div>
</div>
<!-- Submit Button -->
<div class="form-group row mb-4">
<div class="col-sm-2"></div>
<div class="col-sm-10">
<button type="submit" class="btn btn-primary">Register</button>
</div>
</div>
</form>
@model FormTagHelperDemo.Models.Student @{ ViewData["Title"] = "Student Registration"; } <h2 class="mb-4">Student Registration</h2> <form asp-action="Register" asp-controller="Student" method="post" class="form-horizontal"> <!-- Name Input --> <div class="form-group row mb-3"> <label asp-for="FullName" class="col-sm-2 col-form-label"></label> <div class="col-sm-10"> <input asp-for="FullName" class="form-control" /> <span asp-validation-for="FullName" class="text-danger"></span> </div> </div> <!-- Password Input --> <div class="form-group row mb-3"> <label asp-for="Password" class="col-sm-2 col-form-label"></label> <div class="col-sm-10"> <input asp-for="Password" type="password" class="form-control" /> <span asp-validation-for="Password" class="text-danger"></span> </div> </div> <!-- Date of Birth Input --> <div class="form-group row mb-3"> <label asp-for="DateOfBirth" class="col-sm-2 col-form-label"></label> <div class="col-sm-10"> <input asp-for="DateOfBirth" type="date" class="form-control" value="@Model.DateOfBirth.ToString("yyyy-MM-dd")" /> <span asp-validation-for="DateOfBirth" class="text-danger"></span> </div> </div> <!-- Gender Radio Buttons (using Enum) --> <div class="form-group row mb-3"> <label class="col-sm-2 col-form-label">Gender</label> <div class="col-sm-10"> @foreach (var gender in Enum.GetValues(typeof(FormTagHelperDemo.Models.Gender))) { <div class="form-check form-check-inline"> <input type="radio" asp-for="Gender" value="@gender" class="form-check-input" /> <label class="form-check-label">@gender</label> </div> } <span asp-validation-for="Gender" class="text-danger"></span> </div> </div> <!-- Address Text Area --> <div class="form-group row mb-3"> <label asp-for="Address" class="col-sm-2 col-form-label"></label> <div class="col-sm-10"> <textarea asp-for="Address" class="form-control"></textarea> <span asp-validation-for="Address" class="text-danger"></span> </div> </div> <!-- Branch Drop Down List (using Enum) --> <div class="form-group row mb-3"> <label asp-for="Branch" class="col-sm-2 col-form-label"></label> <div class="col-sm-10"> <select asp-for="Branch" class="form-control"> <option value="">-- Select Branch --</option> @foreach (var branch in Enum.GetValues(typeof(FormTagHelperDemo.Models.Branch))) { <option value="@branch">@branch</option> } </select> <span asp-validation-for="Branch" class="text-danger"></span> </div> </div> <!-- Hobbies Multi-Select Check Box --> <div class="form-group row mb-3"> <label class="col-sm-2 col-form-label">Hobbies</label> <div class="col-sm-10"> @foreach (var hobby in ViewBag.Hobbies as List<string>) { <div class="form-check form-check-inline"> <input type="checkbox" class="form-check-input" name="Hobbies" value="@hobby" @(Model.Hobbies != null && Model.Hobbies.Contains(hobby) ? "checked" : "") /> <label class="form-check-label">@hobby</label> </div> } </div> </div> <!-- Skills List Box with multiple selection --> <div class="form-group row mb-3"> <label asp-for="Skills" class="col-sm-2 col-form-label"></label> <div class="col-sm-10"> <select asp-for="Skills" class="form-control" multiple> @foreach (var skill in ViewBag.Skills as List<string>) { <option value="@skill">@skill</option> } </select> <span asp-validation-for="Skills" class="text-danger"></span> </div> </div> <!-- Terms and Conditions Single Check Box --> <div class="form-group row mb-3"> <div class="col-sm-2"></div> <div class="col-sm-10"> <div class="form-check"> <input asp-for="TermsAndConditions" type="checkbox" class="form-check-input" /> <label class="form-check-label" for="TermsAndConditions">I agree to the terms and conditions</label> </div> </div> </div> <!-- Submit Button --> <div class="form-group row mb-4"> <div class="col-sm-2"></div> <div class="col-sm-10"> <button type="submit" class="btn btn-primary">Register</button> </div> </div> </form>
@model FormTagHelperDemo.Models.Student

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

<h2 class="mb-4">Student Registration</h2>

<form asp-action="Register" asp-controller="Student" method="post" class="form-horizontal">

    <!-- Name Input -->
    <div class="form-group row mb-3">
        <label asp-for="FullName" class="col-sm-2 col-form-label"></label>
        <div class="col-sm-10">
            <input asp-for="FullName" class="form-control" />
            <span asp-validation-for="FullName" class="text-danger"></span>
        </div>
    </div>

    <!-- Password Input -->
    <div class="form-group row mb-3">
        <label asp-for="Password" class="col-sm-2 col-form-label"></label>
        <div class="col-sm-10">
            <input asp-for="Password" type="password" class="form-control" />
            <span asp-validation-for="Password" class="text-danger"></span>
        </div>
    </div>

    <!-- Date of Birth Input -->
    <div class="form-group row mb-3">
        <label asp-for="DateOfBirth" class="col-sm-2 col-form-label"></label>
        <div class="col-sm-10">
            <input asp-for="DateOfBirth" type="date" class="form-control" value="@Model.DateOfBirth.ToString("yyyy-MM-dd")" />
            <span asp-validation-for="DateOfBirth" class="text-danger"></span>
        </div>
    </div>

    <!-- Gender Radio Buttons (using Enum) -->
    <div class="form-group row mb-3">
        <label class="col-sm-2 col-form-label">Gender</label>
        <div class="col-sm-10">
            @foreach (var gender in Enum.GetValues(typeof(FormTagHelperDemo.Models.Gender)))
            {
                <div class="form-check form-check-inline">
                    <input type="radio" asp-for="Gender" value="@gender" class="form-check-input" />
                    <label class="form-check-label">@gender</label>
                </div>
            }
            <span asp-validation-for="Gender" class="text-danger"></span>
        </div>
    </div>

    <!-- Address Text Area -->
    <div class="form-group row mb-3">
        <label asp-for="Address" class="col-sm-2 col-form-label"></label>
        <div class="col-sm-10">
            <textarea asp-for="Address" class="form-control"></textarea>
            <span asp-validation-for="Address" class="text-danger"></span>
        </div>
    </div>

    <!-- Branch Drop Down List (using Enum) -->
    <div class="form-group row mb-3">
        <label asp-for="Branch" class="col-sm-2 col-form-label"></label>
        <div class="col-sm-10">
            <select asp-for="Branch" class="form-control">
                <option value="">-- Select Branch --</option>
                @foreach (var branch in Enum.GetValues(typeof(FormTagHelperDemo.Models.Branch)))
                {
                    <option value="@branch">@branch</option>
                }
            </select>
            <span asp-validation-for="Branch" class="text-danger"></span>
        </div>
    </div>

    <!-- Hobbies Multi-Select Check Box -->
    <div class="form-group row mb-3">
        <label class="col-sm-2 col-form-label">Hobbies</label>
        <div class="col-sm-10">
            @foreach (var hobby in ViewBag.Hobbies as List<string>)
            {
                <div class="form-check form-check-inline">
                    <input type="checkbox" class="form-check-input" name="Hobbies" value="@hobby"
                    @(Model.Hobbies != null && Model.Hobbies.Contains(hobby) ? "checked" : "") />
                    <label class="form-check-label">@hobby</label>
                </div>
            }
        </div>
    </div>

    <!-- Skills List Box with multiple selection -->
    <div class="form-group row mb-3">
        <label asp-for="Skills" class="col-sm-2 col-form-label"></label>
        <div class="col-sm-10">
            <select asp-for="Skills" class="form-control" multiple>
                @foreach (var skill in ViewBag.Skills as List<string>)
                {
                    <option value="@skill">@skill</option>
                }
            </select>
            <span asp-validation-for="Skills" class="text-danger"></span>
        </div>
    </div>

    <!-- Terms and Conditions Single Check Box -->
    <div class="form-group row mb-3">
        <div class="col-sm-2"></div>
        <div class="col-sm-10">
            <div class="form-check">
                <input asp-for="TermsAndConditions" type="checkbox" class="form-check-input" />
                <label class="form-check-label" for="TermsAndConditions">I agree to the terms and conditions</label>
            </div>
        </div>
    </div>

    <!-- Submit Button -->
    <div class="form-group row mb-4">
        <div class="col-sm-2"></div>
        <div class="col-sm-10">
            <button type="submit" class="btn btn-primary">Register</button>
        </div>
    </div>
</form>
Understanding the Tag Helper used in the above Code:

We have used the following built-in Tag helpers to generate the Form in ASP.NET Core MVC Application:

asp-action (Used in the <form> Tag):

Example: <form asp-action=”Register” asp-controller=”Student” method=”post” class=”form-horizontal”>

The asp-action Tag Helper specifies the name of the action method to which the form will submit its data. When this form is submitted, the data will be sent to the Register action method of the specified controller (in this case, the StudentController).

asp-controller (Used in the <form> Tag):

Example: <form asp-action=”Register” asp-controller=”Student” method=”post” class=”form-horizontal”>

The asp-controller Tag Helper specifies the controller’s name, which contains the action method to which the form will submit data. This tells the form that the Register action method resides in the StudentController.

asp-for (Used in <label>, <input>, <textarea>, and <select> Tags)

Example: <label asp-for=”FullName”>, <input asp-for=”FullName”>, <textarea asp-for=”Address”>, <select asp-for=”Branch”>

The asp-for Tag Helper automatically binds the form element to a model property. It generates the appropriate id, name, and value attributes for the HTML element based on the bound property in the Student model. For example, asp-for=”FullName” binds the <input> element to the FullName property of the Student model. It also generates the correct label text and sets for attributes in <label> elements.

asp-validation-for (Used in <span> Tags)

Example: <span asp-validation-for=”FullName” class=”text-danger”></span>. The asp-validation-for Tag Helper displays validation error messages associated with the specified model property. If validation errors exist for the FullName property, the error messages will be displayed inside the <span> element. It also allows for custom styling (e.g., text-danger for red text in Bootstrap).

asp-for with <input type=”radio”> (Used in Radio Buttons)

Example: <input type=”radio” asp-for=”Gender” value=”@gender” class=”form-check-input”>. The asp-for Tag Helper, in this case, binds the radio buttons to the Gender property in the model. Each radio button is created dynamically for each enum value (Male, Female, etc.). The value=”@gender” sets the value of each radio button to the corresponding gender enum value.

asp-for with <select> (Used in Dropdowns)

Example: <select asp-for=”Branch” class=”form-control”>. The asp-for Tag Helper binds the <select> dropdown to the Branch property in the Student model. The Tag Helper generates the necessary name, id, and value attributes, and the dropdown options are dynamically populated using a foreach loop that iterates over the Branch enum values.

asp-for with <input type=”checkbox”> (Used in Single Checkboxes)

Example: <input asp-for=”TermsAndConditions” type=”checkbox” class=”form-check-input”>. This binds the checkbox to the TermsAndConditions boolean property in the Student model. If the model property is true, the checkbox will be checked when the form is loaded. The Tag Helper ensures the correct binding and naming of the checkbox input element.

asp-for with <select multiple> (Used in ListBox for Multi-Select)

Example: <select asp-for=”Skills” class=”form-control” multiple>. The asp-for Tag Helper binds the multi-select dropdown to the Skills list in the Student model. When the form is submitted, the selected values from the multi-select dropdown are bound to the Skills list in the model. The multiple attribute allows multiple options to be selected.

asp-for with <textarea> (Used for Multi-line Input)

Example: <textarea asp-for=”Address” class=”form-control”></textarea>

This Tag Helper binds the <textarea> element to the Address property of the Student model. It handles multi-line input and ensures the correct ID, name, and initial value are set from the model data.

asp-for with <input type=”password”> (Used for Password Fields)

Example: <input asp-for=”Password” type=”password” class=”form-control” />. The asp-for Tag Helper binds the <input> element to the Password property of the model, ensuring that the name and id attributes are set correctly. The type=”password” attribute ensures that the input will be treated as a password field, hiding the user’s input.

Modifying the Layout View:

Next, please modify the Layout view as follows. Here, we are adding a few menus that link to the Student List and Register Student Pages.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - FormTagHelperDemo</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/FormTagHelperDemo.styles.css" asp-append-version="true" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container-fluid">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">FormTagHelperDemo</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Student" asp-action="List">Student List</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Student" asp-action="Register">Add New Student</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
&copy; 2024 - FormTagHelperDemo - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>@ViewData["Title"] - FormTagHelperDemo</title> <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" /> <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" /> <link rel="stylesheet" href="~/FormTagHelperDemo.styles.css" asp-append-version="true" /> </head> <body> <header> <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3"> <div class="container-fluid"> <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">FormTagHelperDemo</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between"> <ul class="navbar-nav flex-grow-1"> <li class="nav-item"> <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a> </li> <li class="nav-item"> <a class="nav-link text-dark" asp-area="" asp-controller="Student" asp-action="List">Student List</a> </li> <li class="nav-item"> <a class="nav-link text-dark" asp-area="" asp-controller="Student" asp-action="Register">Add New Student</a> </li> </ul> </div> </div> </nav> </header> <div class="container"> <main role="main" class="pb-3"> @RenderBody() </main> </div> <footer class="border-top footer text-muted"> <div class="container"> &copy; 2024 - FormTagHelperDemo - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a> </div> </footer> <script src="~/lib/jquery/dist/jquery.min.js"></script> <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script> <script src="~/js/site.js" asp-append-version="true"></script> @await RenderSectionAsync("Scripts", required: false) </body> </html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - FormTagHelperDemo</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/FormTagHelperDemo.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container-fluid">
                <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">FormTagHelperDemo</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Student" asp-action="List">Student List</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Student" asp-action="Register">Add New Student</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2024 - FormTagHelperDemo - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
        </div>
    </footer>
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>
    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>
Testing the Application:

We are done with our application implementation. Now, run the application and click on the Student List menu, which should display the following page:

Form Tag Helpers in ASP.NET Core MVC

Next, click on the Details button in the List Page, and you should see the Student Details information as shown in the below image:

Form Tag Helpers in ASP.NET Core MVC Application

Now, click the Add New Student menu to open the Student Registration page. Please fill out the form and click on the Register button as shown in the image below:

Form Tag Helpers in ASP.NET Core MVC Application with Real-time Examples

Once you click on the Register button, it should Register the new Student and navigate to the Student list Page, where you should see the newly created student as shown in the image below:

What are the Tag Helpers used to Create a Form in ASP.NET Core MVC?

In the next article, I will discuss Partial Tag Helper in ASP.NET Core MVC Applications. In this article, I try to explain Form Tag Helpers in ASP.NET Core MVC Application with examples. I hope you enjoy this Form Tag Helpers in ASP.NET Core MVC article.

1 thought on “Form Tag Helpers in ASP.NET Core MVC”

  1. Thank you for your hard work for making a such great tutorial. I learned a lot from your code.

    BTW, if possible, please consider the following suggestions:
    In the [HttpGet] Details(int id) method of the StudentController class, change the
    1. listStudents to students // since there is no listStudents being declared
    2. Id to id // the parameter id is in low-case.

    Again, thank you! It is truly a blessing to read your code.
    Ming

Leave a Reply

Your email address will not be published. Required fields are marked *