ORGANIZE THE LOGIC WITHIN THE MODEL

NET CORE

In this section we will write Model classes that will allow us to obtain data from a data source that is for the moment still fictitious. The controller acting as the coordinator will go to make use of these classes and pass them to the Views.

Pattern MVC

Let’s get into M, that is, the Model in the MVC architecture. Let us first say that there are no patterns that fit every project and every development team, in our project we will use application services that return a ViewModel with the information the View needs no more and no less.

Architettura del Model

Let’s look at the directory breakdown of the model.

Struttura directory

CREATE A VIEWMODEL AND MAKE THE VIEW STRONGLY TYPED

When the View is strongly typed it means that it declares itself what type of data it wants to present.

Catalogo corsi

Let’s look at the Model classes.

CourseViewModel
CourseService

I encourage you to download the section08 code or clone the GITHUB repository so that you have all the sections in your editor.

SECTION SUMMARY

THE MODEL

In the MVC pattern, the “M” is represented by the “Model,” which contains the logic for regulating access to data and, in general, to the world outside the application. The classes contained in the model are used, for example, by controllers that exploit them to obtain the data to be presented by views. There is no single way to organize the logic within the model. The most appropriate approach depends very much on the type of project being undertaken, the skills of the development team on its willingness to espouse that approach.

ORGANIZATION OF LOGIC IN THE MODEL

In this course, the logic within the model is organized on classes that have different purposes:

  • Application services are the classes with which the controllers interact. These classes contain methods such as GetCourses() which is used to retrieve the list of courses, or GetCourseById(string id) to retrieve detailed information. In our project, the application service is aware that in the application such data will be displayed in a view and therefore returns objects called ViewModels that contain all and only the properties needed by the view;
  • Infrastructure services are classes that work at a lower level and deal with talking to the outside world, such as establishing a database connection or sending e-mail, as arranged by the application service that uses them;
  • ViewModels are classes without logic and simply contain properties. They are used to transport data from the application service to the controller, which will then turn these objects over to the view so that they are presented in HTML;
  • A set of various other classes that we will create as we go along, such as value objects and entities.

Regardless of which approach you choose, it is advisable that the logic within the model be organized into small classes with specific responsibility because that way they will be easily reusable. In addition, the application will remain modular and maintainable over time, even as it grows in complexity.

USE AN APPLICATION SERVICE FROM THE CONTROLLER

A controller can simply create an instance of an application service such as CourseService and use its methods that way.

  1. public class CoursesController : Controller
  2. {
  3. public IActionResult Index()
  4. {
  5. var courseService = new CourseService();
  6. List<CourseViewModels> courses = courseService.GetCourses();
  7. return View(courses);
  8. }
  9. }

We note that there is very little logic located within the controller action: the action merely invokes the GetCourses() method of the CourseService application service to obtain a list of CourseViewModels, which it immediately passes to the view so that the list is presented in HTML.

In the next section we will discover a more refined way of obtaining an instance of the CourseService, taking advantage of ASP.NET Core dependency injection.

STRONGLY TYPED VIEWS

Each view can declare what type of data it can present. For this, we add the @model directive (with lowercase m) at the top of the .cshtml file.

  1. @model List<CourseViewModels>

In this way we will have facilities during development:

  • In the view, we use the @Model expression (with a capital M) to access the properties of the object passed by the controller, which, in this case, is an object of type List. For example, we could print the number of items in the list like this: There are @Model.Count courses.
  • When we type @Model. intellisense will appear, that is, the hints that allow us to see what properties exist within the object that was passed by the controller. In this way we drastically reduce the number of typing errors made;
  • If, due to a bug, the controller were to provide an object of a different type than the one declared by the view with the @model directive, we would notice it immediately, already at compile time.

VIEWDATA AND VIEWBAG

The controller can provide additional information to the view using the ViewData and ViewBag objects. However, we prefer not to use them in this way because the task is already performed by the ViewModel, which is a class we created for a specific view and therefore should contain everything that view needs.

Rather, the ViewData and ViewBag objects should be used to exchange information between the content view and the layout view. A typical case is the page title: each content view has its own title that must also be displayed within the title tag found in the layout view.

ViewData and ViewBag objects serve exactly the same purpose, and what changes between the two is only the syntax to be used. We can use one or the other as we please. So let’s go to use the ViewData in a content view to set the title.

  1. @{
  2. ViewData[“Title”] = “Course Catalog”;
  3. }

If we wanted to use ViewBag, the syntax would change slightly but the outcome would be the same.

Now we go to the layout view and show the title in the title tag by getting it from the ViewData. @ViewData[“Title”]

So we can make sure that the content view and the layout view can exchange information, even though they reside on different files.

LINK TO CODE ON GITHUB

GITHUB

Download the code from section08 or clone the GITHUB repository.