Learn ASP.NET Core MVC (.NET 5) by Building an App with CRUD Operations

ASP.NET Core MVC is a powerful and popular web development framework for building dynamic, data-driven web applications. It is open-source, cross-platform, and highly performant. With ASP.NET Core MVC, you can rapidly develop sophisticated web apps following the Model-View-Controller (MVC) architectural pattern.

In this tutorial, we‘ll learn ASP.NET Core MVC by building a simple web application that performs Create, Read, Update, and Delete (CRUD) operations against a database. By the end, you‘ll have a solid foundation in ASP.NET Core MVC and be ready to develop your own real-world applications. Let‘s get started!

Overview of Project

We will be building a basic Book Catalog application that allows users to:

  • View a list of all books in the catalog
  • Add a new book
  • Edit an existing book
  • Delete a book

The app will consist of a single Book model class with properties for the book‘s ISBN, title, author, publication year, and price. We‘ll use Entity Framework Core to map the Book model to a database table and handle data access. The user interface will be server-rendered HTML views styled with Bootstrap.

Setting Up the Development Environment

Before we start coding, let‘s get our development environment set up. You‘ll need:

  1. The .NET 5 SDK – Download and install it from https://dotnet.microsoft.com/download
  2. An integrated development environment (IDE), preferably Visual Studio 2019 or Visual Studio Code
  3. SQL Server Express LocalDB or another database provider

Once you have the .NET 5 SDK and an IDE installed, create a new ASP.NET Core MVC project:

  1. Open a command prompt and navigate to the directory where you want to create your project
  2. Run the command dotnet new mvc -o BookCatalog to create a new MVC project in a directory named "BookCatalog"
  3. Run cd BookCatalog to switch to the project directory
  4. Open the project in your IDE

MVC Architecture Pattern

ASP.NET Core MVC implements the Model-View-Controller (MVC) architectural pattern, which separates an application into three main groups of components:

  • Models: Classes that represent the data of the app and that use validation logic to enforce business rules for that data.
  • Views: Template files that the app uses to dynamically generate HTML responses.
  • Controllers: Classes that handle incoming browser requests, retrieve model data, and then specify view templates that return a response to the browser.

This separation of concerns provides numerous benefits, such as improved maintainability, testability, and code reuse. In our Book Catalog app, we‘ll create a Book model class, a handful of views for the CRUD pages, and a BooksController to process requests.

Creating the Model

Let‘s define our Book model class with the necessary properties:

public class Book
{
    public int Id { get; set; }

    [Required]
    public string ISBN { get; set; }

    [Required]
    [MaxLength(255)]
    public string Title { get; set; }

    [Required] 
    [MaxLength(255)]
    public string Author { get; set; }

    public int? PublicationYear { get; set; }

    [Range(0, 9999.99)]
    public decimal Price { get; set; }
}

We‘ve decorated some of the properties with data annotation attributes like [Required] and [MaxLength] to specify validation rules. The Id property will be the primary key in the database.

Generating the Database with EF Core Migrations

To store our book catalog data, we‘ll use Entity Framework Core to generate the database from our model class. First, add the EF Core NuGet packages to the project:

dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools

Next, create a BookCatalogContext class that derives from DbContext and exposes a Books property:

public class BookCatalogContext : DbContext
{
    public BookCatalogContext(DbContextOptions<BookCatalogContext> options)
        : base(options)
    {
    }

    public DbSet<Book> Books { get; set; }
}

Register the DbContext in the ConfigureServices method of Startup.cs:

services.AddDbContext<BookCatalogContext>(options =>
    options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

Add a connection string named "DefaultConnection" to appsettings.json:

"ConnectionStrings": {
  "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=BookCatalog;Trusted_Connection=True;MultipleActiveResultSets=true"
}

Finally, generate the database by creating and running a migration:

dotnet ef migrations add InitialCreate
dotnet ef database update

Implementing CRUD Operations

Now we‘re ready to implement the CRUD operations for books. In the BooksController, add action methods for each operation:

public async Task<IActionResult> Index()
{
    return View(await _context.Books.ToListAsync());
}

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

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,ISBN,Title,Author,PublicationYear,Price")] Book book)
{
    if (ModelState.IsValid)
    {
        _context.Add(book);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    return View(book);
}

public async Task<IActionResult> Edit(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var book = await _context.Books.FindAsync(id);
    if (book == null)
    {
        return NotFound();
    }
    return View(book);
}

[HttpPost]
[ValidateAntiForgeryToken]  
public async Task<IActionResult> Edit(int id, [Bind("Id,ISBN,Title,Author,PublicationYear,Price")] Book book)
{
    if (id != book.Id)
    {
        return NotFound();
    }

    if (ModelState.IsValid)
    {
        _context.Update(book);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    return View(book);
}

public async Task<IActionResult> Delete(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var book = await _context.Books
        .FirstOrDefaultAsync(m => m.Id == id);
    if (book == null)
    {
        return NotFound();
    }

    return View(book);
}

[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
    var book = await _context.Books.FindAsync(id);
    _context.Books.Remove(book);
    await _context.SaveChangesAsync();
    return RedirectToAction(nameof(Index));
}

For each action, create a corresponding Razor view template under the Views/Books directory. Use scaffolding to generate the Create, Edit, Delete, and Details views.

The Index action retrieves all books from the database and passes them to the Index view. The Create action displays a form for adding a new book and handles the form submission. The Edit and Delete actions work similarly for updating and removing books.

Adding Data Validation

Our Book model has some validation rules specified by data annotations, such as required fields and maximum string lengths. To enforce these validations:

  1. In the Create and Edit views, add asp-validation-summary tags to display validation messages.
  2. In the Create and Edit action methods, check the ModelState.IsValid property before saving changes.
  3. In the view templates, use asp-validation-for attributes on form fields to display field-level validation messages.

Here‘s an example for the Create view:

<form asp-action="Create">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    <div class="form-group">
        <label asp-for="ISBN" class="control-label"></label>
        <input asp-for="ISBN" class="form-control" />
        <span asp-validation-for="ISBN" class="text-danger"></span>
    </div>
    <!-- Other form fields -->
    <div class="form-group">
        <input type="submit" value="Create" class="btn btn-primary" />
    </div>
</form>

Running and Testing the App

To run the application:

  1. Open a command prompt in the project directory
  2. Run dotnet run to start the application
  3. Open a web browser and navigate to https://localhost:5001/
  4. Click on the "Books" link in the navbar to go to the book list page
  5. Test out the CRUD functionality by adding, editing, and deleting books

If you followed along, you should have a working CRUD application for managing a book catalog! The app demonstrates the core features of ASP.NET Core MVC and Entity Framework Core.

Deploying to Azure

To share your app with the world, you can easily deploy it to Microsoft Azure:

  1. Create a new Web App in the Azure Portal
  2. Configure the app to use the .NET 5 runtime stack
  3. Enable a Deployment Center in the app‘s settings
  4. Choose your preferred deployment source (e.g. GitHub, Azure DevOps, FTP) and follow the steps to set up continuous deployment
  5. Update the connection string in appsettings.json to point to an Azure SQL Database
  6. Commit your code changes and push to the main branch of your repo to trigger the deployment

Your ASP.NET Core app will now be live on Azure, backed by a managed SQL database! For more on deployment, check out the official documentation.

Conclusion

Congratulations, you now have a solid foundation in building data-driven web apps with ASP.NET Core MVC! In this tutorial, we covered:

  • Setting up an ASP.NET Core MVC project
  • Using the Entity Framework to define a data model and generate a database
  • Implementing CRUD operations in a controller
  • Validating user input with data annotations
  • Deploying the app to Azure

There‘s so much more to learn, such as authentication/authorization, web APIs, single page applications (SPAs), caching, logging, and more. Keep practicing and building new projects to deepen your understanding of ASP.NET Core. The official documentation is a great resource for further learning.

I hope this tutorial was helpful for getting started with ASP.NET Core MVC. Feel free to reach out with any questions or feedback. Happy coding!

Similar Posts