15.1. ViewModels and Passing Data To and From Views¶
Now that we have an understanding for what a model is, we can focus on how to effectively pass information between the three elements of MVC applications. With our current MVC application, we can add new events and remove events. However, our application is also susceptible to run-time errors. Our view can accept any type of input and if we mistype something in our view, we can run into issues later down the line.
A ViewModel is a model class designed specifically to be used in a view.
By utilizing ViewModels in our application, we can make our views strongly-typed and add validation to forms to prevent bad user input.
Also, if we have information we want to collect as part of a form, but not save as part of a model, we can store that data as a property of a ViewModel.
An example of this would be if we have a form for users to create an account on our site.
The form includes two fields: one for the password and one for confirming the new user’s password.
While we only want to save the password and may only have a Password
property in our model, we can add a ConfirmPassword
property to the ViewModel so we can check that the two match before saving the user’s info.
These benefits of ViewModels will help reduce potential errors in our application.
15.1.1. Refactoring the View and Controller to Use a Model in a View - Video¶
Note
If you want to verify what code this video starts with, check out the model-binding branch. If you want to verify what code this video ends with, check out the models-in-views branch.
15.1.2. Refactoring the View and Controller to Use a Model in a View - Text¶
To start with understanding why we may want to use a ViewModel, let’s refactor our code to use a model directly in our view.
First, in EventsController
, we want to convert the collection of Events we have been holding into a list.
19 | List<Event> events = new List<Event>(EventData.GetAll());
|
Now that we are storing our items in a List
, we need to import the model into our Events/Index.cshtml
view so we can use the new events
collection.
We can add a small statement up on line 1 to do so:
@model List<CodingEventsDemo.Models.Event>
Or, as we write in the video:
1 2 3 | @using CodingEventsDemo.Models
@model List<Event>
|
Wherever we used our ViewBag
property, we can now use Model
syntax.
Once the view has been updated, run the application!
This was merely a refactor so the functionality of the app hasn’t changed, but we have eliminated some of the possibility of bugs in our code being discovered at runtime!
Using a model in a view like this makes our view strongly-typed.
Before if we misspelled a property of Event
or ViewBag
, those errors would have been caught at run-time and possibly interfered with users’ experience.
With a strongly-typed view, the same errors would be caught at compile-time before users see the application.
Strongly-typed views also support intellisense, so as we work with properties of a model, we can make sure we have the correct property name.
15.1.3. Adding a ViewModel - Video¶
Note
If you want to verify what code this video starts with, check out the models-in-views branch. If you want to verify what code this video ends with, check out the adding-viewmodels branch.
15.1.4. Adding a ViewModel - Text¶
Now that we have refactored our Events/Index.cshtml
view and EventsController
to use a model, let’s investigate how to create a ViewModel.
We can do so by following these steps:
Add a
ViewModels
directory at the top level of the project.Add a new class to the
ViewModels
directory and name itAddEventViewModel
.Add
Name
andDescription
properties to the new class.Note
For now, your ViewModel does not need a constructor!
In the
Add()
action method responsible for retrieving the form to add events, inEventsController
, create a new instance ofAddEventViewModel
calledaddEventViewModel
and add it to theView()
.Import the ViewModel to the
Add.cshtml
view with the@model
syntax.Add
asp-controller = Events
andasp-action = NewEvent
to the<form>
tag to designate which method the form data should be sent to.Add
asp-for
to<label>
and<input>
tags. This allows us to specify which form field corresponds to which property in our ViewModel.Refactor the
NewEvent()
action method to be namedAdd()
. Have it also now use the ViewModel as its parameter. Set values of a newEvent
object using the values of the properties stored in the instance of theAddEventViewModel
.Add the new
Event
object toEventData
and make sure that the method still returns aRedirect
to/Events
.Run your application.
Following these steps, we effectively refactored our application to use a ViewModel. While the functionality of the application remains the same, we are now in a position to easily add validation to our application.
15.1.5. Check Your Understanding¶
Question
True or False ViewModels are views designed to specifically be used in models.