Adding Validation, Layouts, and Improved UI Using Bootstrap

In Part 1, you built a complete CRUD module for Products using ASP.NET Core MVC with Controllers, Models, and Views.

In Part 2, you will enhance the project by adding:

  • Form validation (server-side + client-side)

  • A shared layout (_Layout.cshtml)

  • Bootstrap-based clean UI

This is where your app starts looking like a real-world MVC project.

1. Adding Model Validation

ASP.NET Core uses data annotations for validation.

Update your Product.cs model:

using System.ComponentModel.DataAnnotations;

namespace MVCApp.Models
{
    public class Product
    {
        public int Id { get; set; }

        [Required(ErrorMessage = "Product name is required")]
        [StringLength(100)]
        public string Name { get; set; }

        [Range(1, 100000, ErrorMessage = "Price must be greater than 0")]
        public decimal Price { get; set; }
    }
}

✔ What this adds

  • Required validation

  • Custom error messages

  • Client-side validation automatically enabled

2. Update Create View With Validation

Views/Product/Create.cshtml

@model MVCApp.Models.Product

<h2>Add New Product</h2>

<form asp-action="Create" method="post">

    <div class="form-group">
        <label asp-for="Name"></label>
        <input asp-for="Name" class="form-control" />
        <span asp-validation-for="Name" class="text-danger"></span>
    </div>

    <div class="form-group">
        <label asp-for="Price"></label>
        <input asp-for="Price" class="form-control" />
        <span asp-validation-for="Price" class="text-danger"></span>
    </div>

    <br />

    <button type="submit" class="btn btn-success">Save</button>
</form>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

3. Update Edit View With Validation

Views/Product/Edit.cshtml

@model MVCApp.Models.Product

<h2>Edit Product</h2>

<form asp-action="Edit" method="post">
    <input type="hidden" asp-for="Id" />

    <div class="form-group">
        <label asp-for="Name"></label>
        <input asp-for="Name" class="form-control" />
        <span asp-validation-for="Name" class="text-danger"></span>
    </div>

    <div class="form-group">
        <label asp-for="Price"></label>
        <input asp-for="Price" class="form-control" />
        <span asp-validation-for="Price" class="text-danger"></span>
    </div>

    <br />

    <button type="submit" class="btn btn-primary">Update</button>
</form>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

4. Add Bootstrap Layout (Shared UI)

ASP.NET Core MVC already generates a layout file:

Views/Shared/_Layout.cshtml

Replace its content with clean Bootstrap-5 layout:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>@ViewData["Title"] - MVCApp</title>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>

<body>

    <nav class="navbar navbar-expand-lg navbar-dark bg-dark mb-4">
        <div class="container">
            <a class="navbar-brand" href="/">MVCApp</a>

            <div class="navbar-nav">
                <a class="nav-link" href="/Product">Products</a>
            </div>
        </div>
    </nav>

    <div class="container">
        @RenderBody()
    </div>

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>

    @RenderSection("Scripts", required: false)
</body>
</html>

5. Connect Layout With Views

Make sure your views include at the top:

@{
    Layout = "_Layout";
}

Most MVC templates add this automatically.

6. Improve Index View UI

Views/Product/Index.cshtml

@model List<MVCApp.Models.Product>

<h2 class="mb-3">Product List</h2>

<a href="/Product/Create" class="btn btn-primary mb-3">Add Product</a>

<table class="table table-bordered table-striped">
    <thead class="table-dark">
        <tr>
            <th>Id</th>
            <th>Name</th>
            <th>Price (₹)</th>
            <th>Actions</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var p in Model)
        {
            <tr>
                <td>@p.Id</td>
                <td>@p.Name</td>
                <td>@p.Price</td>
                <td>
                    <a href="/Product/Edit/@p.Id" class="btn btn-sm btn-warning">Edit</a>
                    <a href="/Product/Delete/@p.Id" class="btn btn-sm btn-danger">Delete</a>
                </td>
            </tr>
        }
    </tbody>
</table>

7. Update Controller for Validation

ProductController.cs

Add validation check:

[HttpPost]
public IActionResult Create(Product product)
{
    if (!ModelState.IsValid)
        return View(product);

    ProductRepository.Add(product);
    return RedirectToAction("Index");
}

[HttpPost]
public IActionResult Edit(Product product)
{
    if (!ModelState.IsValid)
        return View(product);

    ProductRepository.Update(product);
    return RedirectToAction("Index");
}

✔ Prevents invalid form submission

✔ Supports both client-side & server-side validation

8. What You Achieved in Part 2

Now your application supports:

  • Form validation with error messages

  • Beautiful UI using Bootstrap

  • Clean layout across entire app

  • Stronger, more professional MVC structure

Your app now looks like a real production ASP.NET Core MVC application.