Problem
How to use Tag Helpers in ASP.NET Core MVC to simplify the creation of data entry forms.
Solution
In an empty project, update the Startup class to add the services and middleware for MVC.
- public void ConfigureServices(
- IServiceCollection services)
- {
- services.AddMvc();
- }
-
- public void Configure(
- IApplicationBuilder app,
- IHostingEnvironment env)
- {
- app.UseDeveloperExceptionPage();
- app.UseMvc(routes =>
- {
- routes.MapRoute(
- name: "namedRoute",
- template: "call-named-route/{id?}",
- defaults: new { controller="Home", action="NamedRoute" });
-
- routes.MapRoute(
- name: "default",
- template: "{controller=Home}/{action=Index}/{id?}");
- });
- }
Add a Controller with these action methods.
- public IActionResult Index()
- {
- var model = new EmployeeViewModel();
- return View(model);
- }
-
- [HttpPost]
- public IActionResult Index(EmployeeViewModel model)
- {
- if (!ModelState.IsValid)
- {
- return View(model);
- }
- var json = JsonConvert.SerializeObject(model);
- return Content(json);
- }
-
- public IActionResult Echo(int id)
- {
- return Content(id.ToString());
- }
-
- public IActionResult NamedRoute(int id)
- {
- return Content(id.ToString());
- }
Add a _ViewImports.cshtml page in Views folder. Add a directive to import the tag helpers.
- @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
Add a model to use on the data entry screen.
- public enum Gender { Male = 1, Female = 2}
-
- public class EmployeeViewModel
- {
- [HiddenInput]
- public int Id { get; set; }
-
- [Required]
- public string Firstname { get; set; }
-
- [EmailAddress]
- public string Email { get; set; }
-
- [Url]
- public string BlogUrl { get; set; }
-
- [Phone]
- public string MobileNo { get; set; }
-
- [DataType(DataType.Password)]
- public string Password { get; set; }
-
- [DataType(DataType.Date)]
- public DateTime BirthDate { get; set; }
-
- public double Salary { get; set; }
-
- [Display(Name = "Part Time?")]
- public bool IsPartTime { get; set; }
-
- public string Notes { get; set; }
-
- public string Title { get; set; }
- public IEnumerable<string> Interests { get; set; }
- public Gender Gender { get; set; }
-
- public List<SelectListItem> GetTitles()
- { ... }
-
- public List<SelectListItem> GetInterests()
- { ... }
- }
Add a Razor page (Index.cshtml).
- @using Fiver.Mvc.TagHelpers.Models.Home
- @model EmployeeViewModel
-
- @* Form *@
- <form asp-controller="Home" asp-action="Index" method="post">
- @* Validation Summary *@
- <div asp-validation-summary="All"></div>
-
- @* Label, Input, Validation(span) *@
- <input asp-for="Id" />
-
- <label asp-for="Firstname"></label>
- <input asp-for="Firstname" />
- <span asp-validation-for="Firstname"></span> <br />
-
- <label asp-for="BirthDate"></label>
- <input asp-for="BirthDate" asp-format="{0:dd/MM/yyyy}"/>
- <span asp-validation-for="BirthDate"></span> <br />
-
- @* Textarea *@
- <label asp-for="Notes"></label>
- <textarea asp-for="Notes"></textarea>
- <span asp-validation-for="Notes"></span> <br />
-
- @* Select (single) *@
- <label asp-for="Title"></label>
- <select asp-for="Title" asp-items="Model.GetTitles()">
- <option value="">--select--</option>
- </select><br />
-
- @* Select (multiple) *@
- <label asp-for="Interests"></label>
- <select asp-for="Interests" asp-items="Model.GetInterests()"></select><br />
-
- @* Select (enum) *@
- <label asp-for="Gender"></label>
- <select asp-for="Gender" asp-items="Html.GetEnumSelectList<Gender>()">
- <option value="" selected>--select--</option>
- </select><br />
-
- <br />
- <button type="submit">Save</button><br />
- </form>
Discussion
Tag Helpers help generate HTML by attaching attributes to the existing HTML elements or by creating new elements. Although they look like HTML elements and attributes, Tag Helpers are processed by Razor (server-side).
I like to think of Tag Helpers as C# extensions methods, i.e., they allow us to attach some extra behavior to the existing classes.
The sample project shows the usage of various tag helpers that can help in creating data entry forms. I have outlined the key information about these below:
Form
- Generates HTML form’s action attribute.
- Generate a hidden verification token field used with [ValidateAntiForgeryToken] attribute on [HttpPost] action method.
- Can specify asp-route-[param], however, it will be ignored if the route parameter exists in the form as well.
- Can use asp-route for named routes.
Input & Text Area
- Generates id and <strong>name.
- Generate validation attributes.
- Generate type attribute based on model’s property type and data annotations.
Label
- Generate for
- Picks the [Display] attribute on the Model property as label text.
Validation
- <strong>asp-validation-for: generates validation message for single property on model.
- asp-validation-summary: generates validation messages for a model and it’s properties. You could choose the option to suppress individual property messages.
Select
- Generates select and option
- Can be populated by List<SelectListItem>, received from the model or injected service.
- Can be populated by specifying enum type, using GetEnumSelectList().
- Multi-selection enabled if asp-for is IEnumerable.
- Can add default option too, these will be combined with the ones from a data source.
Anchor
- Can generate href based on controller, action and route parameters.
- Can generate href based route name.
- Can generate href based host and protocol.
- asp-route-[param] transmitted as query string if [param] not part of the route.
- <a asp-controller="Home" asp-action="Echo" [email protected]>Echo!</a><br />
- <a asp-route="namedRoute" [email protected]>Call Named Route</a><br />
- <a asp-host="tahir-naushad.com" asp-protocol="http">Blog</a>
Source Code
GitHub