Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
by
FREELessons:14Length:2.8 hours

Next lesson playing in 5 seconds

Cancel
  • Overview
  • Transcript

4.1 Adding a Service Layer and View Model

It's time to start working with data! In this lesson, we'll write a service layer and a view model to display data.

4.1 Adding a Service Layer and View Model

Every piece of an application is important, but for some applications it's displaying information that is the most important thing to do. For example, with our SoundBoard application, if we aren't going to display the messages, then there's really no reason to have this application to begin with. So starting in this lesson, we are going to focus on displaying information, and for this lesson, we want to display all of the messages within our data store. The first thing we need to do is get our messages and pass that to the view. So we can do this, var messages =, and then we can use our message repository's GetAll method and then we could pass that collection to the view. Now, we could also do that like this so that we don't have to create that messages variable, but I personally like to do this, because if I need to debug this method for some reason, I can send a break point on line 25 and I can inspect the messages collection here. I can see if it has the data that I think it should have, and it just makes things a little bit easier, so I am going to do this, but feel free to simplify this if you want to and, as far as the Index action method, this is really all that we need to do for now. We might come back and adjust it a little bit. But for now let's create the Index view. So we want to go to our Views folder and the Message folder and let's create a new view. So we will add new item, and somewhere here, there it is, MVC View Page, and we want index.cshtml. Now, our view needs to know what type of data it is receiving, so we we will use @model, and this is going to be an IEnumerable of message, and then we need to simply iterate over this collection and generate the HTML. So, we need a foreach loop (var message in model) and then inside of this foreach loop we will have our HTML. Now, our HTML is rather simple. Everything is contained within a div element with a class of message, and you can see where the placeholders are. We have the title here, the message here, the email address here, and the date here. Now, ideally, we would not be showing the email address. But since we can't perform database migrations, we're going with the data that we have, and that is the email address. Ideally, we would have a display name or something like that, but that requires us to add properties to our application user class and then perform a database migration, which we can't do. So email address is the next best thing for this demonstration. So let's go ahead and plug in the information, and we do so using Razor expressions. We don't have any tag helpers for displaying this type of information. So we will start with the @ sign and we want to use our message, and this is the title, so it's going to be MessageTitle. And then we want to do the same thing for the actual message. So @message, but instead of MessageTitle, we want to use the MessageContent. And then let's go ahead and plug in the date. So we will have @message, and then use the Created property, and we can use the ToString method, and for our format, we could have year year year year dash and then a two digit month, then a two digit day. And then there's the email address, but we don't have the email address as part of our message object. We have the user ID, but no address. So that's something that we will need to address in a moment. Let's first of all run the application, and let's make sure that we are actually seeing our messages whenever we go to /message. And we are. We see all three messages and everything but the email address. So we have a nice start, we just need to pull in that email address. So if we were storing everything within a SQL database and using Entity Framework, this would be really easy, because the way Entity Framework works, we could pull in all of the user information, as we are pulling in all of the message information, but we're not. So we have two data stores, and it would be nice if we could just reference one thing within our controller, because we want our controllers to be as clean as possible, so that basically means we need a service layer. So we are going to end up doing that. Let's add a new folder to our projects and let's call it Services. And let's create a class that, for right now, is going to be responsible for just viewing messages, or at least getting the information for viewing messages. So let's call the class ViewMessageService. If we decide to add more responsibilities to this service, then we can of course change the name. And we are working with two stores here, so we need those stores in order to get the messages and get the user information. So, the first thing we need is our message repository. So, let's make private readonly MessageRepository, and, we'll just call it _messages. Of course, we need a using statement for our data namespace, so let's add that. And then, we need the DB context that is used for identity. So, private readonly, it's called ApplicationDbContext, I believe. Let's see, yes, we can pull in the model's namespace, and let's just call that _db. Now these are dependencies that are external to this service. We need them injected, so we will do that with the constructor. So let's have public ViewMessageService, and we want to accept our message repository, let's just call it messages, and then we want our ApplicationDbContext, and let's just call that dbContext. And then inside of the constructor, we will set our private fields. So -messages will be equal to messages. And then _db will be equal to dbContext. And for right now this is a service for displaying messages. So let's do public, we want to return and IEnumerable of something. Now, we can't return a message, because the message doesn't have the user's email address. Now, we could make out message class a partial class and then add in a username property later on. Or we can do something what's called a view model. A view model is a class that contains information for a specific view, and in an MVC application, it is common to see these types of things. So let's create another folder for our project and let's call it ViewModels. Now, some people like to put the ViewModels inside of the Models folder. I don't, I like to separate it from the models, because these are models that are view specific, they're really not used for anything else. So in this ViewModels folder I want to create a new class, and we will just call it MessageViewModel. And we want a lot of the same information within our message class. In fact, in this case it it makes sense to actually inherit from message, because we are going to eventually need everything, the message ID, the user ID and all of the other pieces of information. Now, this isn't always going to be the case. There are times when you want your ViewModel to only have certain pieces of information from your model. So it really depends upon what you need, when you need it. But for right now, and for this case, we want everything from our message class. And then we want another property that we can use to contain the email address. So we could call it email or display name. In this case lets just do Username because that's really what this is. And so we can go back to our ViewMessageService, and we can say that this is going to return an IEnumerable of MessageViewModel. We of course need a using statement for our ViewModels namespace, and we can call this GetAllMessages, and so there are two things that we need to do inside of this method. The first is to retrieve all of our messages, so let's go ahead and do that. var messages =, we will use our messages repository, and we will call the GetAll method. And then we' need our users, so we can say, var users =, and we will use our dbContext, and we want the users table. And we want to select all of them, but really we only need two things. We need the user ID, and we need the email address. So we can create a dictionary where the key is the ID, and the value is the username, or the email address. In identity, the username and the email address are the same, unless if you tell it not to be the same. By default they are the same. So we could use the ToDictionary method, and in fact, we need to do this asynchronously. So, let's just go ahead and await this. We need to add async to our method definition. This needs to return a task of IEnumerable of MessageViewModel, and then we need to change the name to GetAllMessagesAsync, because all asynchronous methods end with Async. So we need to specify the key, so that is the ID. We also need to specify the value, and we could use the username property, or we could use the email address. I guess it would be safer to use the email address, even though they are the same values. And then we want to simply create our MessageViewModels. Now, we're going to do that by taking our current messages and then creating a new MessageViewModel. So that would look something like this. We would return messages, and we could use the Select operator, and then we will simply just new up MessageViewModel, and then we will populate its properties. So we could Id = m.Id, We could say user ID = m.UserId, and then all of the other properties until finally we have the username, and we will say that that is equal to our users, and then for the key we will use m.userId, and that will give us our username. We can go ahead and call the ToArray so that that link query will automatically execute, and that's really all that we need to do here. So we can go back to our MessageController. And we need to make this action method asynchronous because we are going to be using an asynchronous method inside of it. And this needs to return a task of IActionResult. And then we just need to reference our new service. Now, we could do that inside of the Index action method, but really, this is a service that we could end up using for all of our other action methods. So let's put this at the class level so it is a private readonly class variable, and this type is going to be our ViewMessageService. We need a using statement for our services namespace and let's just call it _service. Now, we can't new up this service right here because we have dependencies. We do have our message repository, but we don't have our ApplicationDbContext. So the way that we're going to get that is through our constructor. So, let's create a public MessageController constructor. We want to accept our ApplicationDbContext, and let's just call it dbContext. And then inside of this constructor, we are going to new up the ViewMessageService, and we will pass in our _messages for the repository. And then we will pass in the dbContext. Now, we don't have to worry about passing this dbContext to the controller. That's automatically going to be done for us, because MVC has a dependency injection feature. If we go down and look at the startup file, we want to look at the ConfigureServices method. And you're going to see where there's this services and then configure, but really it's this services and then AddEntityFramework, AddSqlServer, AddDbContext. This is all setting up the dependency injection stuff so that whenever MVC creates our MessageController, it sees that it is expecting this ApplicationDbContext, so it's going to pass it to that. And in fact, we could take this a step further, and we can say that okay, we want to set this up so that our MessageRepository is automatically injected. And we can do that inside of this ConfigureServices method. So down here at the bottom of that method, let's use this services object. This has a method called AddTransient. And there is a non-generic version, but in this case it's easier to use the generic version, and we just want to say that we want to create this MessageRepository object. We don't need to pass anything to this method. And that basically sets us up so we can go back to our controller, and we can accept a MessageRepository, let's call it messages and then we no longer have to new up our repository here in the class. It's going to be automatically passed to our controller's constructor. So inside of the constructor, we can say _messages = whatever we have as our parameter. I'm going to go ahead and change this. This is just my personal preference. Whenever I'm setting up something like this service, I like to pass in using the parameter name and not the class variable name. That's just my personal preference. Doesn't matter, because they are the same object. Now we can go to the Index action method, and instead of using our MessagesRepository, we can await _service, and then GetAllMessagesAsync. And then we can pass those messages on to the view. Now that also means that we need to change our view, because we are no longer expecting an IEnumerable of message. We now want an IEnumerable of MessageViewModel. But we need to add a using statement here, and we do that in Razor using an @ sign and then using. So it's just like in normal C#, we just have this @ sign. And then we want SoundBoard.ViewModels. And we can leave everything alone except for the email address. So here we will say @message, and then email, or no, we had Username, isn't it? And that will display the username. So now the moment of truth. Let's run our application. Let's go to /message, and we will see if this does, indeed, work. Hopefully we will see our three messages, but we should also see the email addresses, and we do. So now we are showing our main list of messages. But we're not done there, because we can also show messages by user, and it would also be nice to display an individual message and we will get started with those in the next lesson

Back to the top