Understanding the Model in MVC
This is part eighteen of ASP.NET Core tutorial. In this video, we'll discuss model in ASP.NET MVC with an example.
Ultimately, we want to retrieve a specific employee details from this employee database table and display those details on a web page as you can see right here. Model in MVC contains a set of classes that represent data and the logic to manage the data. In our case, we want to work with employee data. So to represent employee data, I'm going to create an employee class and this employee class is going to contain these properties: name, email, Department. To be able to uniquely identify each employee, I am also going to have ID property. So let's create an employee class with these four properties: ID, name, email and Department.
Organizing Model Classes
This is the same project that we've been working with so far in this video series. Now let's place all our model classes in a folder called models within our project. In ASP.NET Core MVC, model and controller classes does not have to necessarily be in the folders named models and controllers. They can literally live anywhere within the project, but it's a good practice to place them in their respective folders because it's easier to find them later.
Creating the Employee Model Class
To represent the employee data that we want to work with, I'm going to add an employee class to the models folder. The first property that we want here is ID. This property allows us to uniquely identify each employee. The quickest and easiest way to create a property in visual studio is by typing prop and then press the Tab key twice. And here, the first thing we can do is change the data type of the property. In our case the data type for the ID property is going to be integer, so I'm not going to change that. Now when I press Tab we'll have the opportunity to change the name of the property. In our case the name of the property is ID. At this point when I press the Enter key we will get out of the editing mode.
In addition to ID, we want name. The data type for the name property is string. Next, we want email. Again the data type of email is string. Finally, we want Department.
Defining the Repository Pattern Interface
Remember, a model in MVC contains a set of classes that represent data and the logic to manage the data. In our case, this employee class represents the employee data that we want to work with. In addition to this employee class, we want another class that's going to manage these employee details, that is, saving and retrieving these employee details from an underlying data source, such as a database table.
So to the models folder, in addition to the employee class, I'm going to add another class. I'm actually going to add an interface instead of a class. We'll understand the reason for using this interface abstraction in just a bit. I'm going to name this interface IEmployeeRepository. For now, this interface is going to contain just one method that's going to retrieve a specific employee by ID. Let's name the method getEmployee. This is going to have a parameter of type integer, and let's name the parameter ID. As we progress through this course, we'll add more methods to this interface to be able to create, update, and delete employees.
Implementing the Mock Employee Repository
Right now, we need to provide implementation for this interface, IEmployeeRepository. So to this models folder, I'm going to add another class. Let's name this class MockEmployeeRepository. This class is going to provide the implementation for IEmployeeRepository. Notice we have a red squiggly under IEmployeeRepository. When I press Control-Period, we have the option to implement the interface.
We will provide the implementation for getEmployee method in just a bit. Before that, let me create a private field. This is going to be of type List<Employee>. In addition to this private field, I'm also going to include a constructor for this class. Inside the constructor, we're going to initialize this private field _employeeList with some employee mock data. At the moment, as you can see, we are working with this hardcoded data. In our upcoming videos in this series, we're going to provide another implementation for this IEmployeeRepository and that implementation is going to retrieve employee details from a SQL Server database. For now, from this getEmployee method, let's return an employee whose ID matches with this incoming ID. So from the method, let's return the first or default employee whose ID matches with this incoming ID.
The Importance of Using an Interface
Now let's quickly understand the reason for using this interface IEmployeeRepository. Now if we take a look at this interface, it doesn't have much code in it. All it has is the declaration of this method, getEmployee. All the work is done by our MockEmployeeRepository class, which is providing the implementation for the getEmployee method. So the obvious question that comes to our mind is why are we using this interface IEmployeeRepository in between? Why don't we directly program against this MockEmployeeRepository class?
Well, we can use this MockEmployeeRepository class without the interface if we want, but if we do that, we cannot use dependency injection, and as a result, our application will be extremely difficult to change and maintain. Unit testing also becomes very difficult. So throughout our application, we will be programming against this interface IEmployeeRepository and not against any concrete implementation such as this MockEmployeeRepository. This allows us to use dependency injection, which in turn allows our application to be more flexible and easily unit testable. If this doesn't make much sense at the moment, don't worry, we'll discuss dependency injection in detail in our next video.
Injecting the Repository into the Controller
For now, let's use this IEmployeeRepository within our home controller. The first thing that I'm going to do here is create a constructor. Using this constructor we are going to inject this interface IEmployeeRepository. We don't have the required namespace, EmployeeManagement.Models, so let's bring that in. And let's name this injected dependency employeeRepository and let's store it in a private field. I'm going to name it _employeeRepository. We don't have the private field yet. Let's generate it by pressing Control-Period.
In most real-world ASP.NET Core MVC applications, we'll see this programming pattern very often. Here we're using the constructor to inject the service, IEmployeeRepository. This is called constructor injection. If this code doesn't make much sense at the moment, don't worry, we'll discuss dependency injection in detail in our next video and it'll be much clearer at that point. For now, from this index action method let's use this private field _employeeRepository and then call getEmployee method. I'm going to hard-code the employee ID for now to one, and we know this is going to return the employee object which has got the name property. So let's return the name property from this index action method. Let's also change the return type of the method from JsonResult to string. With all these changes in place, let's run our application.
The Dependency Injection Error and Recap
Notice we have an error: "Unable to resolve service for type IEmployeeRepository while attempting to activate HomeController". So basically, ASP.NET Core MVC is complaining that HomeController requires an instance of IEmployeeRepository, but I don't know which implementation instance to provide. We'll discuss what causes this error and how to fix it in our next video.
So a model in MVC contains a set of classes that represent the data and the logic to manage the data. In our case, we want to work with employee data, so model contains two: the Employee class, which represents the employee data, and the EmployeeRepository class, which knows how to retrieve and save employee data. At the moment our EmployeeRepository class has only one method, getEmployee, which only knows how to retrieve data. In our upcoming videos in this series, we'll add methods to create, update, and delete as well. That's it in this video. Thank you for watching.