ASP.NET Core MVC: Models

Understanding Models in ASP.NET Core MVC

In the Model-View-Controller (MVC) architectural pattern, the Model represents the data and the business logic of your application. It is responsible for managing the application's state and responding to requests for information about that state.

Models are typically plain old C# objects (POCOs) that encapsulate the data and the rules that govern it. They do not directly interact with the user interface (View) or handle incoming requests (Controller).

Core Responsibilities of a Model:

Creating a Simple Model

Let's create a simple Product model to represent an item in an online store.


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

        public string Name { get; set; }

        public string Description { get; set; }

        public decimal Price { get; set; }
    }
}
            

In this example:

Data Validation with Data Annotations

ASP.NET Core provides a powerful mechanism for data validation using Data Annotations. These attributes can be applied to model properties to define validation rules.

Let's enhance our Product model with some validation:


using System.ComponentModel.DataAnnotations;

namespace MvcModels.Models
{
    public class Product
    {
        [Key] // Indicates this is the primary key for data binding/persistence
        [Display(Name = "Product ID")]
        public int Id { get; set; }

        [Required(ErrorMessage = "Product name is required.")]
        [StringLength(100, ErrorMessage = "Product name cannot be longer than 100 characters.")]
        [Display(Name = "Product Name")]
        public string Name { get; set; }

        [StringLength(500, ErrorMessage = "Description cannot be longer than 500 characters.")]
        [Display(Name = "Description")]
        public string Description { get; set; }

        [Required(ErrorMessage = "Price is required.")]
        [Range(0.01, 10000.00, ErrorMessage = "Price must be between $0.01 and $10,000.00.")]
        [Display(Name = "Price")]
        public decimal Price { get; set; }
    }
}
            

Here's what the new attributes do:

How Validation Works:

When a form bound to this model is submitted, ASP.NET Core's model binder attempts to validate the incoming data against these attributes. If validation fails, the errors are collected and can be displayed to the user in the View.

Models and Controllers

Controllers are responsible for retrieving data from models (or a data access layer) and passing it to views. They also receive data from the user's input (often bound to a model) and can instruct the model to update its state.

For example, a controller might:

Models and Views

Views consume data provided by models to render the user interface. Views are typically strongly-typed to a specific model, meaning they expect and can directly access the properties of that model.

A typical view for our Product model might iterate through a list of products and display their name, description, and price.

Best Practices:

  • Keep Models Simple: Models should primarily focus on data and validation. Avoid putting UI logic or complex controller actions into them.
  • Use Data Transfer Objects (DTOs): For complex scenarios or when communicating between layers, consider using DTOs to shape the data specifically for the needs of the caller.
  • Separate Concerns: While models can contain data access logic, it's often better to abstract this into dedicated repositories or services for cleaner code.

By understanding and effectively utilizing models, you build robust, maintainable, and data-centric ASP.NET Core applications.