Chapter 5. Models

Data is the heart of every application. A user enters data into the application, edits the entered data, and searches the data. We can even say that an application that we build is just an interface for the operations that we perform on the application data. So, it is absolutely necessary for any framework to provide a mechanism to handle data operations easier and more manageable. Models in ASP.NET MVC are used to represent the business domain data.

In this chapter, you'll be learning about the following topics:

  • Models and their purpose
  • Creating a simple model and using it in the controller and views of the ASP.NET MVC application
  • Creating a model specific to a View model
  • Data flow in an ASP.NET MVC application in the context of models and ViewModels
  • Purpose of the Entity Framework along with its features and benefits
  • Adding, updating, and deleting data using the Entity Framework
  • Using the Entity Framework in ASP.NET MVC applications

Models

Models are simple POCO (Plain Old C# Objects) classes representing your business domain data. For an e-commerce business, model classes would be Product, Order, and Inventory. If you are building an application for a university, model classes would be Student, Teacher, and Subject. Models represent the business domain data in your application and they are not aware of the underlying database that is being used in your application. In fact, you don't even need a database to work with models.

They can represent the data stored in an XML file or CSV file or any other data in your application. Having said that, these models could be used to interact with your database (in most cases) but they don't have any dependency to the database.

The following steps describe how to create an ASP.NET Core application that uses Models:

  1. Make sure to create an ASP.NET 5 application with an empty template. Install the ASP.NET Core NuGet package and configure this, as discussed in an earlier chapter.
  2. Create a Controllers folder and create a HomeController with a single Index action method.
  3. Create the following folder/files for the Views model:
    • Views: This folder is inside your project.
    • Views\_ViewStart.cshtml: This identifies the name of the Layout file.
    • ViewsShared folder: This folder holds all the shared View components for your application.
    • Shared\_Layout.cshtml: This file identifies what your web application structure should look like.
    • ViewsHome folder: This folder contains all of the Views of your HomeController.
    • ViewsHomeIndex.cshtml: This is the view corresponding to the Index action method of HomeController.

Now, we have created an ASP.NET Core application with Controllers and Views.

Let us create a Models folder in our application; this folder will contain all of your model files. In a real world application, this folder and the respective model files would reside in separate projects. For the sake of simplicity, we are keeping the Models folder and its files in the same project.

Models

Let us create a simple model class Product model, in the Models folder:

public class Product { 
  public int ProductId { get; set; } 
  public string Name { get; set; } 
  public decimal Price { get; set; } 
} 

This Product model class is no different from any other C# class and contains a few properties about the product.

Update the Index action method in HomeController to use the Product model, as shown in the following code snippet. We are building the model data and passing the model data to the View so that it can be shown to the users. However, it is NOT recommended to build the Model data in the controller's action methods as it violates the separation of concerns. For the sake of simplicity only, we are building the Model data in an action method.

public IActionResult Index() { 
  /* Build the products model. It is NOT RECOMMENDED to build    models in Controller action methods  like this. In real world appication, these models and the    respective Data Access Layer(DAL) would  be in separate projects. We are creating it here to make things    simpler to explain */ 
  List<Product> Products = new List<Product> { 
    new Product { 
      Name = "Mobile Phone", 
      Price = 300 
    }, 
    new Product { 
      Name = "Laptop", 
      Price = 1000 
    }, 
    new Product { 
      Name = "Tablet", 
      Price = 600 
    } 
  }; 
  return View(Products); 
} 

Update the corresponding Index View method to use the Model data loop through each product and show it as an unordered list item. The @model in the first line represents the Model metadata; the type of data being passed to the View. The Model in the for…each loop represents the actual data itself, a list of products in our case:

@model List<Chapter5.Models.Product> 
 
<ul> 
  @foreach (var Product in Model) { 
    <li>@Product.Name</li> 
  } 
</ul> 

When you run the application, you'll get the following output:

Models

We have successfully created a Model and have used it in our Controller and View.

Let us create a comparatively complex Model class, Order (Order.cs in the Models folder), which contains a list of products and their total amount:

public class Order { 
  public int OrderId { get; set; } 
  public List<Product> Products { get; set; } 
  public decimal Total { get; set; } 
} 

Models

Now, we have to update the Index action method to use the Order model. Once we build the list of products, we are assigning the products list to the Order property and calculating the total cost of the order. These calculations would usually be done as part of the business layer. Again, for the sake of simplicity, we are building the data Model and calculations here in the action; this should never be the case in a real world application.

The code highlighted in bold is the changes that we have made in the action method:

public IActionResult Index() { 
  /* Build the products model. It is NOT RECOMMENDED to build    models in Controller action methods  like this. In real world appication, these models and the    respective Data Access Layer(DAL) would  be in separate projects. We are creating it here to make things    simpler to explain   */ 
  List<Product> Products = new List<Product> { 
    new Product { 
      Name = "Mobile Phone", 
      Price = 300 
    }, 
    new Product { 
      Name = "Laptop", 
      Price = 1000 
    }, 
    new Product { 
      Name = "Tablet", 
      Price = 600 
    } 
  }; 
 
  Order order = new Order(); 
  order.Products = Products; 
  order.Total = Products.Sum(product => product.Price); 
 
  return View(order); 
} 

The View is updated to accommodate the Model changes. Model metadata (@model) is changed to indicate that the Order information is passed to the View instead of the list of products.

Then, we are showing the list of products in table format. Please note that all of the Model data (Order object and its properties, in this case) can be accessed through the Model. For example, the Products class can be accessed through Model.Products and the value of the Total can be obtained through Model.Total:

@model Chapter5.Models.Order 
 
<table border="1"> 
 
  <tr> 
    <th>Product Name</th> 
    <th>Price</th> 
  </tr> 
 
  @foreach (var Product in Model.Products){ 
    <tr> 
      <td>@Product.Name</td> 
      <td>@Product.Price</td> 
    </tr> 
  } 
  <tr> 
    <td><b>Total</b></td> 
    <td><b>@Model.Total</b></td> 
  </tr> 
</table> 

When you run the application, you'll see the following output:

Models

Models specific to a View component

There are scenarios where you might want to update only a few properties in a large Model or you might want to create a new Model based on a few models. In such scenarios, it is better to create a new Model specific to the View.

For example, let us assume that we are building a screen where you update the price of the product. This simple screen may contain only three properties—product ID, product name, and price of the product. But the product's Model may contain more than 30 properties to hold all details of the product such as manufacturer, color, size, and other properties. Instead of sending the complete Model with all the properties, we can create a new Model specific to this view with only a few properties—ID, Name, and Price.

Note on ViewModels

The ViewModels are entities where when you update the Model, your View would get updated automatically and vice versa. In many online articles and even in some books, they are referring to ViewModels when they are actually trying to mean Models specific to the View.

In ViewModels, binding is two ways—when you update either the Model or the View, the other one would get updated automatically. Let us consider a simple example; you have a form with various fields on the left-hand side and print preview on the right side. In this case, whatever you type in real time in the form will be reflected immediately on the right side. In such cases, you can use pure View models when you type, your ViewModel would be updated and that ViewModel would be consumed in the right-hand side print preview. These pure ViewModels are being used in advanced JavaScript frameworks such as Knockout or AngularJS.

In Models specific to the View, we are binding in only one way from the Model to the View. Here, we are sending a Model specific to the View instead of the generic Model (which represents a business domain class).

However, in this book, we will be referring to Models specific to View as ViewModel for brevity. Unless otherwise specified, you should read all ViewModels as Models specific to View. So, I am making the same mistake made by other authors Note on ViewModels.

Data flow with respect to a Model

The following block diagram shows the data flow in an ASP.NET MVC application:

Data flow with respect to a Model

Data Source represents your application data. The application data could reside anywhere—from full-fledged RDBMS such as SQL servers to simple Excel spreadsheets, or anything in between.

Models represent the business domain data for your application and are independent of the data source being used. The same model could be used with different data sources.

We can use the Model as-is in our views to get data or to present it. But in some views, you might not need all the properties of the model. So, instead of sending the entire Model to the View, we create models specific to the View and use them in our View. This makes things simpler.

The following is the high-level sequence of events that happens when you store or retrieve a record in ASP.NET Core using the Model:

  1. Users enter the data in a form (created using Views) in the application. The fields in the form do not need to represent the complete model as we need only a few properties in the Model.
  2. The entered data is passed to the controller where Model binding happens. Model binding is the process where the data entered in the View gets mapped to the Model or ViewModel.
  3. If the data is received in the ViewModel, then we would be converting the ViewModel to the Model.
  4. Finally, the Model data is stored in the data source.

Till now, we have been handling only in-memory data in our application. In almost all real world applications, some form of the database will be used for data storage, access, and retrieval. In the next section, we will discuss the Entity Framework (ORM framework), which makes data access simpler from a .NET application.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset