How to validate models while associating between two objects - asp.net-mvc

I am building a application using Entity Framework 6.1 code first and ASP.NET MVC5.
I got the following model:
class Person {
public Int32 Id {get; set;}
[Required]
public String Name {get; set;}
public List<Book> Books {get; set;}
}
class Book {
public Int32 Id {get; set;}
[Required]
public String Title {get; set;}
public List<Person> Authors {get; set;}
}
The two basic edit-views for changing Person.Name or Book.Title are straight forward.
Now I got one "real world"-view where the user can edit a Book and add existing Authors to them.
The view posts the values like this:
Title = "Nice Book"
Authors[0].Id = 7
Authors[1].Id = 3
The view will only send the Id of the Persons/Authors. After all, the user won't rename an author while editing a Book.
All the model binding works great and the controller can map the posted fields.
Yet the validation of the bound model fails when the author/Person has no (required) Name set.
Is there some kind of workaround? Currently I omit the RequiredAttribute for the affected properties. I would like to not make a view-model for every aspect of my (rather complex) model-graph where some or another item will get associated.

This is why you should use view models. As they allow you to customize what properties should be exposed to the view. However, you're also no handling the posting of selected authors correctly. For a multiselect like this you really need a view model.
public class BookViewModel
{
public BookViewModel()
{
SelectedAuthorIds = new List<int>();
}
[Required]
public string Title { get; set; }
public List<int> SelectedAuthorIds { get; set; }
public IEnumerable<SelectListItem> AuthorChoices { get; set; }
}
Notice, first, that there's no Id property. You may need to add this if you want to use this same view model to edit books, as well, but for the purposes of creation, there's no need to have an Id field in the view, so we leave it off. Next, there's no Authors property. Instead we have SelectedAuthorIds which is a list of integers and AuthorChoices which will hold all the Authors a user can select from. Finally, there's a constructor to initialize SelectedAuthorIds so it's never null. An empty list translates to nothing being selected, but we need an actual list.
Now, use this view model as the model for your view:
#model Namespace.To.BookViewModel
And, change your author select field(s) to:
#Html.ListBoxFor(m => m.SelectedAuthorIds, Model.AuthorChoices)
You'll also need to populate AuthorChoices, which you'll handle in your GET action for this form:
public ActionResult Create()
{
var model = new BookViewModel();
model.AuthorChoices = db.Authors.Select(m => new SelectListItem
{
Value = m.Id.ToString(),
Text = m.Name
});
return View(model);
}
Finally, after the user posts the form, you'll need to use SelectedAuthorIds to fetch those authors from the database and add them to your Book being created. As far as that goes, you'll also need to map the data from BookViewModel to an instance of Book. All this means is copying over the data from one to the other. There's libraries for this type of thing, such as AutoMapper, but this is relatively simple, so I'll handle it manually:
[HttpPost]
public ActionResult Create(BookViewModel model)
{
if (ModelState.IsValid)
{
var book = new Book
{
Title = model.Title
};
book.Authors = db.Authors.Where(m => model.SelectedAuthorIds.Contains(m.Id));
db.Books.add(book);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}
The edit version will be similar, except you'll instead pull an existing Book instead of creating a new one:
[HttpPost]
public ActionResult Edit(int id, BookViewModel model)
{
var book = db.Books.Find(id);
book.Title = model.Title;
...
}

Related

Assign Entity Framework Navigation Property without Query

I am working with an asp MVC5 app with entity framework 6 and want to create an object that has a navigation property like so:
public class widget
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Category Category { get; set; }
}
where the property Category is another entity in the database model. When I implement the CRUD functionality, I create a view model like so:
public class EditWidgetViewModel
{
public List<SelectListItem> Categories { get; set; }
public int CategoryId { get; set; }
}
and the contents of the selectList goes to a dropdown in the html form. Next, the CategoryId gets posted back to the server when the user submits the form. From there, I am currently doing something like the following to save changes:
var dbWidget = new Widget
{
Name = model.Name,
Category = db.Categories.Find(CategoryId)
}
db.Widgets.Add(dbWidget);
db.SaveChanges();
So my question is the following: can I assign the category navigation property without doing another DB lookup with db.Widgets.Find(WidgetId) - I already know the id number that should go in the Category_Category_Id column in the Widgets table of the database without doing a lookup. Also, it seems like if you have something with five or so navigation properties that this would be a significant performance problem with a round trip for each of those.
You can create a new entity with a constructor, assign it a proper id
then use dbContext's Entry().State like this:
Category category = new Category { Id = CategoryId };
db.Entry(category).State = EntityState.Unchanged;
var dbWidget = new Widget
{
Name = model.Name,
Category = category
}
db.Widgets.Add(dbWidget);
db.SaveChanges();

Property null after adding to MVC base model in Visual Studio

this is an issue that has been happening for a couple of weeks now, was wondering if anyone has encountered this , and if there is a fix :
Say I have a View Model called 'ListFruitsViewModel' , which for the sake of argument contains a base model of 'Fruit' that has the properties
public Guid fruitID {get; set;}
public String fruitName {get; set;}
ok so I go ahead and create the ListFruits view , perform some action and all works ok.
but then I realise I need to change the 'Fruit' model to include a 'fruitColor' property. So I change the properties of 'Fruit' to look like :
public Guid fruitID {get; set;}
public String fruitName {get; set;}
public String fruitColor {get; set;}
now I can see the fruitColor property in the Razor intellisense etc, I ve changed the method that populates the fruits in the list to include the new property etc, and no matter what I try, the fruitColor property is always null in the View Model.
Its almost like although VS knows there is a new property, the underlying assembly files have not picked up that there is a new property in the 'Fruit' model, and is not populating it.
Various combinations of cleans / builds / rebuilds have not fixed the issue, and a VS restart holds no joy.
I am certain this is a quirk of VS and the way it updates complied code.
Any ideas?
EDIT: one real-world example then :
I have a class of type report with Properties:
public Guid reportID { get; set; }
public String reportName { get; set; }
public DateTime reportCreated { get; set; }
public String reportCreatedBy { get; set; }
and I have just added:
public String reportCode { get; set; }
Im bringing in a list of these back from a database so Ive changed the method that populates the list to :
public List<Report> ListReports() {
List<Report> list = new List<Report>();
DAL.DAL dal = new DAL.DAL();
DataTable dt = new DataTable();
Report item;
dt = dal.ListAllReports();
foreach (DataRow row in dt.Rows) {
item = new Report() {
reportID = new Guid(row["ReportID"].ToString()),
reportName = row["ReportName"].ToString(),
reportCreated = Convert.ToDateTime(row["ReportCreatedDateTime"].ToString()),
reportCreatedBy = row["ReportCreatedBy"].ToString(),
reportCode = row["ReportCode"].ToString()
};
list.Add(item);
}
return list;
}
I can step through the ListReports() method , and can see the values are being passed in to the object at this point, but the property is always null in the View Model, while the other properties are populated as expected.

MVC - Multiple models in a view

I'm using MVC (for the first time) with Entity framework, Database first
What I want to do is display data from a database in a single view. I created the database first, then I made a ADO.NET Entity Data Model based from the database that contains all the tables. I then created a Index view that was strongly typed with my Entity Data Model as model.
In my Index I have at the top
#model IEnumerable<Forum6.Models.Forum>
This allows me to get the rows from the table "Forum" from my database. If I try to add an extra model I get I get this error message when I run:
Line 1: #model IEnumerable<Forum6.Models.Forum>
Line 2: #model2 IEnumerable<Forum6.Models.Post>
Parser Error Message: Only one 'model' statement is allowed in a file.
After searching for an answer I found this: Two models in one view in ASP MVC 3
The answer was to create a ViewModel (ParentModel) that contained all the Models (Tables).
This is the ViewModel I created:
public class ViewModel
{
public IEnumerable<Forum6.Models.Forum> Forum { get; set; }
public IEnumerable<Forum6.Models.Post> Post { get; set; }
public IEnumerable<Forum6.Models.Topics> Topics { get; set; }
public IEnumerable<Forum6.Models.Users> Users { get; set; }
public IEnumerable<Forum6.Models.PrivMsg> PrivMsg { get; set; }
public IEnumerable<Forum6.Models.Permission> Permission { get; set; }
}
I edited my controller to look like this:
public class HomeController : Controller
{
// ForumDBEntities old_db = new ForumDBEntities();
ViewModel db = new ViewModel();
public ActionResult Index()
{
return View(db);
}
}
Then replaced the old Index view with a new strongly typed view that used the ViewModel as model. Which contains:
#model IEnumerable<Forum6.Models.ViewModel>
Trying to run this gives me this error:
The model item passed into the dictionary is of type 'Forum6.Models.ViewModel', but this dictionary requires a model item
of type
'System.Collections.Generic.IEnumerable`1[Forum6.Models.ViewModel]
How do I make the "ViewModel" enumarable? Or is my error elsewhere?
You'll need to change #model IEnumerable<Forum6.Models.ViewModel> to #model Forum6.Models.ViewModel as you're wrapping your IEnumerables inside a single ViewModel.
A good rule of thumb is to have a 1:1 relationship between your ViewModel and View.
This might be a good read for you: http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/ (just ignore the automapper part if you don't want to go that route)
You'll also need to put in actual data in your ViewModel since
ViewModel db = new ViewModel();
public ActionResult Index()
{
return View(db);
}
will just give your view an empty ViewModel.
One way to do it would be.
public ActionResult Index()
{
var model = new ViewModel
{
Forum = db.GetForum(),
Post = db.GetPost(),
Topic = you get the idea
};
return View(model);
}
One last thing when naming properties or variables in general you should use the plural verb when it contains a list. So your ViewModel would be.
public class ViewModel
{
public IEnumerable<Forum6.Models.Forum> Forums { get; set; }
public IEnumerable<Forum6.Models.Post> Posts { get; set; }
public IEnumerable<Forum6.Models.Topics> Topics { get; set; }
public IEnumerable<Forum6.Models.Users> Users { get; set; }
public IEnumerable<Forum6.Models.PrivMsg> PrivMsgs { get; set; }
public IEnumerable<Forum6.Models.Permission> Permissions { get; set; }
}
Change #model IEnumerable<Forum6.Models.ViewModel> to #model Forum6.Models.ViewModel as you are passing a single instance of a ViewModel class and not a collection of them.
All your collections are passed in a single instance of a view model.

Is there a design pattern to standardise the display of multiple models into a single view?

I've tinkered with derived classes, interfaces and viewmodels, but I haven't been able to create quite what I need.
Say we're building a CMS with the following models:
ArticleItem
Title
Summary
Content
NewsItem
Headline
PublishDate
Summary
Content
EventItem
EventTitle
StartDate
EndDate
Content
I'm looking for a way to standardise the display of these into one format / view (e.g. so we can display them all in the same RSS feed). The standardized view might be called HTMLItem and have 3 fields:
Title
Summary
Content
The ArticleItem would translate directly to the HTMLItem, that's straightforward.
For the NewsItem I would like to join the PublishDate and the first 100 characters of the content to create Summary field of HTMLItem.
For the EventItem I would like to combine the StartDate and EndDate to create the Summary field of HTMLItem.
Ultimately I'm looking for the easiest, most efficient way to be able to pass the 3 models into a single view that has been designed to display HTMLItem. My best shot so far has been to create a 'convertor' class for each model, but I can't help feeling that there is a better way to do this.
Any experience, expertise and advice would be much appreciated!
Make a ViewModel with the standarized properties and a constructor for each specialized class:
public class HtmlItemViewModel {
//Properties
public string Title {get; set;}
public string Summary {get; set;}
public string Content {get; set;}
//Constructor inside HtmlItemViewModel for each one of the specialized classes:
public HtmlItemViewModel(ArticleItem item)
{
this.Title = item.Title;
this.Summary = item.Summary;
this.Content = item.Content;
}
public HtmlItemViewModel(NewsItem item)
{
this.Title = item.Headline;
this.Summary = String.Format("{0} - {1}", item.PublishDate, item.Summary.Substring(0,1000));
this.Content = item.Content;
}
public HtmlItemViewModel(EventItem item)
{
this.Title = item.EventTitle;
this.Summary = String.Format("{0} - {1}", item.StartDate, item.EndDate);
this.Content = item.Content;
}
}
Then, on the method you use for your RSS Feed simply pass each entity to the constructor on each individual query. Like this:
//Example controller
public class RssController : Controller {
public ActionResult GetRssFeed(){
//Assuming you have a service for each item type
var articleList = ArticleService.GetArticles().Select(s => new HtmlItemViewModel(s));
var newsItemList = NewsItemService.GetNewsItems().Select(s => new HtmlItemViewModel(s));
var eventItemList = EventItemService.GetEvents().Select(s => new HtmlItemViewModel(s));
articleList.AddRange(newsItemList);
articleList.AddRange(eventItemList);
return articleList;
}
}
You can use Viewmodel Pattern in your project
Models and ViewModels are different. Don't confuse the ViewModel with
the MVVM pattern.
The use of a view model can make the interaction between model and
view more simple. A model can sometimes be over complicated having
other model objects as members, which could have model objects as
member etc..
By using a view model you have a good way to simplify what the view
deals with. This will also filter down what can be seen in
intellisense, so if you have different people developing the models
than those working on the views, creating a simple view model can make
it much easier for those just dealing with the UI.
The simple and most common solution to this is to create a composite view model class. This can be a composed class (containing references to your domain models), or a flattened class, referencing properties from each class individually.
So you could do this:
public class HtmlItemViewModel
{
public ArticleItem ArticleItem {get; set;}
public NewsItem NewsItem {get; set;}
public EventItem EventItem {get; set;}
}
Or this:
public class HtmlItemViewModel
{
//Article Item Properties
public string ArticleTitle {get; set;}
public string ArticleContent {get; set;}
public string ArticleSummary {get; set;}
//News Item Properties
public string Headline {get; set;}
public DateTime PublishDate {get; set;}
public string NewsItemSummary {get; set;}
public string NewsItemContent {get; set;}
//Event Item Properties
public string EventTitle {get; set;}
public DateTime StartDate {get; set;}
public DateTime EndDate {get; set;}
public string EventContent {get; set;}
}
Then, whichever way you choose to construct the view model, you will map the view model properties to the domain model(s) in the controller. You can do this mapping manually
HtmlItemViewModel.ArticleTitle = ArticleItem.ArticleTitle;
//and so on...
Or you can use a third party tool like AutoMapper
I tend to favor the flattened view model in most scenarios as it allows me to only send the data I need, no more, no less. And it also allows me to put my data annotations for input validation on the view model instead of the domain model.

What is ViewModel in MVC?

I am new to ASP.NET MVC. I have a problem with understanding the purpose of a ViewModel.
What is a ViewModel and why do we need a ViewModel for an ASP.NET MVC Application?
If I get a good example about its working and explanation that would be better.
A view model represents the data that you want to display on your view/page, whether it be used for static text or for input values (like textboxes and dropdown lists) that can be added to the database (or edited). It is something different than your domain model. It is a model for the view.
Let us say that you have an Employee class that represents your employee domain model and it contains the following properties (unique identifier, first name, last name and date created):
public class Employee : IEntity
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateCreated { get; set; }
}
View models differ from domain models in that view models only contain the data (represented by properties) that you want to use on your view. For example, lets say that you want to add a new employee record, your view model might look like this:
public class CreateEmployeeViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
As you can see it only contains two of the properties. These two properties are also in the employee domain model. Why is this you may ask? Id might not be set from the view, it might be auto generated by the Employee table. And DateCreated might also be set in the stored procedure or in the service layer of your application. So Id and DateCreated are not needed in the view model. You might want to display these two properties when you view an employee’s details (an employee that has already been captured) as static text.
When loading the view/page, the create action method in your employee controller will create an instance of this view model, populate any fields if required, and then pass this view model to the view/page:
public class EmployeeController : Controller
{
private readonly IEmployeeService employeeService;
public EmployeeController(IEmployeeService employeeService)
{
this.employeeService = employeeService;
}
public ActionResult Create()
{
CreateEmployeeViewModel model = new CreateEmployeeViewModel();
return View(model);
}
public ActionResult Create(CreateEmployeeViewModel model)
{
// Do what ever needs to be done before adding the employee to the database
}
}
Your view/page might look like this (assuming you are using ASP.NET MVC and the Razor view engine):
#model MyProject.Web.ViewModels.CreateEmployeeViewModel
<table>
<tr>
<td><b>First Name:</b></td>
<td>#Html.TextBoxFor(m => m.FirstName, new { maxlength = "50", size = "50" })
#Html.ValidationMessageFor(m => m.FirstName)
</td>
</tr>
<tr>
<td><b>Last Name:</b></td>
<td>#Html.TextBoxFor(m => m.LastName, new { maxlength = "50", size = "50" })
#Html.ValidationMessageFor(m => m.LastName)
</td>
</tr>
</table>
Validation would thus be done only on FirstName and LastName. Using FluentValidation you might have validation like this:
public class CreateEmployeeViewModelValidator : AbstractValidator<CreateEmployeeViewModel>
{
public CreateEmployeeViewModelValidator()
{
RuleFor(m => m.FirstName)
.NotEmpty()
.WithMessage("First name required")
.Length(1, 50)
.WithMessage("First name must not be greater than 50 characters");
RuleFor(m => m.LastName)
.NotEmpty()
.WithMessage("Last name required")
.Length(1, 50)
.WithMessage("Last name must not be greater than 50 characters");
}
}
And with Data Annotations it might look this:
public class CreateEmployeeViewModel : ViewModelBase
{
[Display(Name = "First Name")]
[Required(ErrorMessage = "First name required")]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
[Required(ErrorMessage = "Last name required")]
public string LastName { get; set; }
}
The key thing to remember is that the view model only represents the data that you want to use, nothing else. You can imagine all the unnecessary code and validation if you have a domain model with 30 properties and you only want to update a single value. Given this scenario you would only have this one value/property in the view model and not all the properties that are in the domain object.
A view model might not only have data from one database table. It can combine data from another table. Take my example above about adding a new employee record. Besides adding just the first and last names you might also want to add the department of the employee. This list of departments will come from your Departments table. So now you have data from the Employees and Departments tables in one view model. You will just then need to add the following two properties to your view model and populate it with data:
public int DepartmentId { get; set; }
public IEnumerable<Department> Departments { get; set; }
When editing employee data (an employee that has already been added to the database) it wouldn’t differ much from my example above. Create a view model, call it for example EditEmployeeViewModel. Only have the data that you want to edit in this view model, like first name and last name. Edit the data and click the submit button. I wouldn’t worry too much about the Id field because the Id value will probably been in the URL, for example:
http://www.yourwebsite.com/Employee/Edit/3
Take this Id and pass it through to your repository layer, together with your first name and last name values.
When deleting a record, I normally follow the same path as with the edit view model. I would also have a URL, for example:
http://www.yourwebsite.com/Employee/Delete/3
When the view loads up for the first time I would get the employee’s data from the database using the Id of 3. I would then just display static text on my view/page so that the user can see what employee is being deleted. When the user clicks the Delete button, I would just use the Id value of 3 and pass it to my repository layer. You only need the Id to delete a record from the table.
Another point, you don’t really need a view model for every action. If it is simple data then it would be fine to only use EmployeeViewModel. If it is complex views/pages and they differ from each other then I would suggest you use separate view models for each.
I hope this clears up any confusion that you had about view models and domain models.
View model is a class that represents the data model used in a specific view. We could use this class as a model for a login page:
public class LoginPageVM
{
[Required(ErrorMessage = "Are you really trying to login without entering username?")]
[DisplayName("Username/e-mail")]
public string UserName { get; set; }
[Required(ErrorMessage = "Please enter password:)")]
[DisplayName("Password")]
public string Password { get; set; }
[DisplayName("Stay logged in when browser is closed")]
public bool RememberMe { get; set; }
}
Using this view model you can define the view (Razor view engine):
#model CamelTrap.Models.ViewModels.LoginPageVM
#using (Html.BeginForm()) {
#Html.EditorFor(m => m);
<input type="submit" value="Save" class="submit" />
}
And actions:
[HttpGet]
public ActionResult LoginPage()
{
return View();
}
[HttpPost]
public ActionResult LoginPage(LoginPageVM model)
{
...code to login user to application...
return View(model);
}
Which produces this result (screen is taken after submitting form, with validation messages):
As you can see, a view model has many roles:
View models documents a view by consisting only fields, that are represented in view.
View models may contain specific validation rules using data annotations or IDataErrorInfo.
View model defines how a view should look (for LabelFor,EditorFor,DisplayFor helpers).
View models can combine values from different database entities.
You can specify easily display templates for view models and reuse them in many places using DisplayFor or EditorFor helpers.
Another example of a view model and its retrieval: We want to display basic user data, his privileges and users name. We create a special view model, which contains only the required fields. We retrieve data from different entities from database, but the view is only aware of the view model class:
public class UserVM {
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool IsAdministrator { get; set; }
public string MothersName { get; set; }
}
Retrieval:
var user = db.userRepository.GetUser(id);
var model = new UserVM() {
ID = user.ID,
FirstName = user.FirstName,
LastName = user.LastName,
IsAdministrator = user.Proviledges.IsAdministrator,
MothersName = user.Mother.FirstName + " " + user.Mother.LastName
}
Edit: I updated this answer on my Blog:
http://www.samwheat.com/post/The-function-of-ViewModels-in-MVC-web-development
My answer is a bit lengthy but I think it is important to compare view models to other types of commonly used models to understand why they are different and why they are necessary.
To summarize, and to directly answer the question that is asked:
Generally speaking, a view model is an object that contains all the properties and methods necessary to render a view. View model properties are often related to data objects such as customers and orders and in addition, they also contain properties related to the page or application itself such as user name, application name, etc. View models provide a convenient object to pass to a rendering engine to create an HTML page. One of many reasons to use a view model is that view models provide a way to unit test certain presentation tasks such as handling user input, validating data, retrieving data for display, etc.
Here is a comparison of Entity models (a.ka. DTOs a.ka. models), Presentation Models, and View Models.
Data Transfer Objects a.k.a “Model”
A Data Transfer Object (DTO) is a class with properties that match a table schema in a database. DTOs are named for their common usage for shuttling data to and from a data store.
Characteristics of DTOs:
Are business objects – their definition is dependent on application data.
Usually contain properties only – no code.
Primarily used for transporting data to and from a database.
Properties exactly or closely match fields on a specific table in a data store.
Database tables are usually normalized therefore DTOs are usually normalized also. This makes them of limited use for presenting data. However, for certain simple data structures, they often do quite well.
Here are two examples of what DTOs might look like:
public class Customer
{
public int ID { get; set; }
public string CustomerName { get; set; }
}
public class Order
{
public int ID { get; set; }
public int CustomerID { get; set; }
public DateTime OrderDate { get; set; }
public Decimal OrderAmount { get; set; }
}
 
Presentation Models
A presentation model is a utility class that is used to render data on a screen or report. Presentation models are typically used to model complex data structures that are composed of data from multiple DTOs. Presentation models often represent a denormalized view of data.
Characteristics of Presentation Models:
Are business objects – their definition is dependent on application data.
Contain mostly properties. Code is typically limited to formatting data or converting it to or from a DTO. Presentation Models should not contain business logic.
Often present a denormalized view of data. That is, they often combine properties from multiple DTOs.
Often contain properties of a different base type than a DTO. For example, dollar amounts may be represented as strings so they can contain commas and a currency symbol.
Often defined by how they are used as well as their object characteristics. In other words, a simple DTO that is used as the backing model for rendering a grid is in fact also a presentation model in the context of that grid.
Presentation models are used “as needed” and “where needed” (whereas DTOs are usually tied to the database schema). A presentation model may be used to model data for an entire page, a grid on a page, or a dropdown on a grid on a page. Presentation models often contain properties that are other presentation models. Presentation models are often constructed for a single-use purpose such as to render a specific grid on a single page.
An example presentation model:
public class PresentationOrder
{
public int OrderID { get; set; }
public DateTime OrderDate { get; set; }
public string PrettyDate { get { return OrderDate.ToShortDateString(); } }
public string CustomerName { get; set; }
public Decimal OrderAmount { get; set; }
public string PrettyAmount { get { return string.Format("{0:C}", OrderAmount); } }
}
View Models
A view model is similar to a presentation model in that is a backing class for rendering a view. However, it is very different from a Presentation Model or a DTO in how it is constructed. View models often contain the same properties as presentation models and DTOs and for this reason, they are often confused one for the other.
Characteristics of View Models:
Are the single source of data used to render a page or screen. Usually, this means that a view model will expose every property that any control on the page will need to render itself correctly. Making the view model the single source of data for the view greatly improves its capability and value for unit testing.
Are composite objects that contain properties that consist of application data as well as properties that are used by application code. This characteristic is crucial when designing the view model for reusability and is discussed in the examples below.
Contain application code. View Models usually contain methods that are called during rendering and when the user is interacting with the page. This code typically relates to event handling, animation, visibility of controls, styling, etc.
Contain code that calls business services for the purpose of retrieving data or sending it to a database server. This code is often mistakenly placed in a controller. Calling business services from a controller usually limits the usefulness of the view model for unit testing. To be clear, view models themselves should not contain business logic but should make calls to services which do contain business logic.
Often contain properties that are other view models for other pages or screens.
Are written “per page” or “per screen”. A unique View Model is typically written for every page or screen in an application.
Usually derive from a base class since most pages and screens share common properties.
View Model Composition
As stated earlier, view models are composite objects in that they combine application properties and business data properties on a single object. Examples of commonly used application properties that are used on view models are:
Properties that are used to display application state such as error messages, user name, status, etc.
Properties used to format, display, stylize, or animate controls.
Properties used for data binding such as list objects and properties that hold intermediate data that is input by the user.
The following examples show why the composite nature of view models is important and how we can best construct a View Model that efficient and reusable.
Assume we are writing a web application. One of the requirements of the application design is that the page title, user name, and application name must be displayed on every page. If we want to create a page to display a presentation order object, we may modify the presentation model as follows:
public class PresentationOrder
{
public string PageTitle { get; set; }
public string UserName { get; set; }
public string ApplicationName { get; set; }
public int OrderID { get; set; }
public DateTime OrderDate { get; set; }
public string PrettyDate { get { return OrderDate.ToShortDateString(); } }
public string CustomerName { get; set; }
public Decimal OrderAmount { get; set; }
public string PrettyAmount { get { return string.Format("{0:C}", OrderAmount); } }
}
This design might work… but what if we want to create a page that will display a list of orders? The PageTitle, UserName, and ApplicationName properties will be repeated and become unwieldy to work with. Also, what if we want to define some page-level logic in the constructor of the class? We can no longer do that if we create an instance for every order that will be displayed.
Composition over inheritance
Here is a way we might re-factor the order presentation model such that it becomes a true view model and will be useful for displaying a single PresentationOrder object or a collection of PresentationOrder objects:
public class PresentationOrderVM
{
// Application properties
public string PageTitle { get; set; }
public string UserName { get; set; }
public string ApplicationName { get; set; }
// Business properties
public PresentationOrder Order { get; set; }
}
public class PresentationOrderVM
{
// Application properties
public string PageTitle { get; set; }
public string UserName { get; set; }
public string ApplicationName { get; set; }
// Business properties
public List<PresentationOrder> Orders { get; set; }
}
Looking at the above two classes we can see that one way to think about a view model is that it is a presentation model that contains another presentation model as a property. The top-level presentation model (i.e. view model) contains properties that are relevant to the page or application while the presentation model (property) contains properties that are relevant to application data.
We can take our design a step further and create a base view model class that can be used not only for PresentationOrders but for any other class as well:
public class BaseViewModel
{
// Application properties
public string PageTitle { get; set; }
public string UserName { get; set; }
public string ApplicationName { get; set; }
}
Now we can simplify our PresentationOrderVM like this:
public class PresentationOrderVM : BaseViewModel
{
// Business properties
public PresentationOrder Order { get; set; }
}
public class PresentationOrderVM : BaseViewModel
{
// Business properties
public List<PresentationOrder> Orders { get; set; }
}
We can make our BaseViewModel even more re-usable by making it generic:
public class BaseViewModel<T>
{
// Application properties
public string PageTitle { get; set; }
public string UserName { get; set; }
public string ApplicationName { get; set; }
// Business property
public T BusinessObject { get; set; }
}
Now our implementations are effortless:
public class PresentationOrderVM : BaseViewModel<PresentationOrder>
{
// done!
}
public class PresentationOrderVM : BaseViewModel<List<PresentationOrder>>
{
// done!
}
I didn't read all the posts but every answer seems to be missing one concept that really helped me "get it"...
If a Model is akin to a database Table, then a ViewModel is akin to a database View - A view typically either returns small amounts of data from one table or, complex sets of data from multiple tables (joins).
I find myself using ViewModels to pass the info into a view/form, and then transferring that data into a valid Model when the form posts back to the controller - also very handy for storing Lists(IEnumerable).
If you have properties specific to the view, and not related to the DB/Service/Data store, it is a good practice to use ViewModels. Say, you want to leave a checkbox selected based on a DB field (or two) but the DB field itself isn't a boolean. While it is possible to create these properties in the Model itself and keep it hidden from the binding to data, you may not want to clutter the Model depending on the amount of such fields and transactions.
If there are too few view-specific data and/or transformations, you can use the Model itself
A lot of big examples, let me explain in a clear and crispy way.
ViewModel = Model that is created to serve the view.
ASP.NET MVC view can't have more than one model so if we need to display properties from more than one model in the view, it is not possible. ViewModel serves this purpose.
View Model is a model class that can hold only those properties that are required for a view. It can also contain properties from more than one entity (tables) of the database. As the name suggests, this model is created specifically for the View requirements.
A few examples of View Models are below
To list data from more than entities in a view page – we can create a
View model and have properties of all the entities for which we want
to list data. Join those database entities and set the View model
properties and return to the View to show data of different
entities in one tabular form
The view model may define only specific fields of a single entity that is
required for the View.
ViewModel can also be used to insert, and update records into more than one entity however the main use of ViewModel is to display columns from multiple entities (model) into a single view.
The way of creating a ViewModel is the same as creating a Model, the way of creating a view for the ViewModel is the same as creating a view for a Model.
Here is a small example of List data using ViewModel.
Hope this will be useful.
View model a is simple class which can contain more than one class property. We use it to inherit all the required properties, e.g. I have two classes Student and Subject
Public class Student
{
public int Id {get; set;}
public string Name {get; set;}
}
Public class Subject
{
public int SubjectID {get; set;}
public string SubjectName {get; set;}
}
Now we want to display records student's Name and Subject's Name in View (In MVC), but it's not possible to add more than one classes like:
#model ProjectName.Model.Student
#model ProjectName.Model.Subject
the code above will throw an error...
Now we create one class and can give it any name, but this format "XyzViewModel" will make it easier to understand. It is inheritance concept.
Now we create a third class with the following name:
public class StudentViewModel:Subject
{
public int ID {get; set;}
public string Name {get; set;}
}
Now we use this ViewModel in View
#model ProjectName.Model.StudentViewModel
Now we are able to access all the properties of StudentViewModel and inherited class in View.
MVC doesn't have a view model: it has a model, view, and controller. A ViewModel is part of MVVM (Model-View-ViewModel). MVVM is derived from the Presentation Model and is popularized in WPF. There should also be a model in MVVM, but most people miss the point of that pattern completely and they will only have a view and a view model. The model in MVC is similar to the model in MVVM.
In MVC the process is split into 3 different responsibilities:
View is responsible for presenting the data to the user
A controller is responsible for the page flow
A model is responsible for the business logic
MVC is not very suitable for web applications. It is a pattern introduced by Smalltalk for creating desktop applications. A web environment behaves completely differently. It doesn't make much sense to copy a 40-year-old concept from desktop development and paste it into a web environment. However, a lot of people think this is ok because their application compiles and returns the correct values. That is, in my opinion, not enough to declare a certain design choice as ok.
An example of a model in a web application could be:
public class LoginModel
{
private readonly AuthenticationService authentication;
public LoginModel(AuthenticationService authentication)
{
this.authentication = authentication;
}
public bool Login()
{
return authentication.Login(Username, Password);
}
public string Username { get; set; }
public string Password { get; set; }
}
The controller can use it like this:
public class LoginController
{
[HttpPost]
public ActionResult Login(LoginModel model)
{
bool success = model.Login();
if (success)
{
return new RedirectResult("/dashboard");
}
else
{
TempData["message"] = "Invalid username and/or password";
return new RedirectResult("/login");
}
}
}
Your controller methods and your models will be small, easily testable, and to the point.
ViewModel is workaround that patches the conceptual clumsiness of the MVC framework. It represents the 4th layer in the 3-layer Model-View-Controller architecture. when Model (domain model) is not appropriate, too big (bigger than 2-3 fields) for the View, we create smaller ViewModel to pass it to the View.
View Model is a class that we can use for rendering data on View. Suppose you have two entities Place and PlaceCategory and you want to access data from both entities using a single model then we use ViewModel.
public class Place
{
public int PlaceId { get; set; }
public string PlaceName { get; set; }
public string Latitude { get; set; }
public string Longitude { get; set; }
public string BestTime { get; set; }
}
public class Category
{
public int ID { get; set; }
public int? PlaceId { get; set; }
public string PlaceCategoryName { get; set; }
public string PlaceCategoryType { get; set; }
}
public class PlaceCategoryviewModel
{
public string PlaceName { get; set; }
public string BestTime { get; set; }
public string PlaceCategoryName { get; set; }
public string PlaceCategoryType { get; set; }
}
So in the above Example, Place and Category are the two different entities and PlaceCategory ViewModel is ViewModel which we can use on View.
ViewModel is the model containing fields to use in MVC View. Using ViewModel for the view has the following benefits:
As the database model (Entity class) contains a single table's data. If required data from multiple tables, a single ViewModel can have multiple tables' fields.
User can not interact directly with the database model, so the Database layer or model is secured.
It is used to get data from the database model through the repository and pass it to view. Similarly, it utilizes for posting data to the database model to update database records.
If you want to study code on how to set up a "Baseline" web application with ViewModels I can advise you to download this code on GitHub: https://github.com/ajsaulsberry/BlipAjax. I developed large enterprise applications. When you do this it's problematic to set up a good architecture that handles all this "ViewModel" functionality. I think with BlipAjax you will have a very good "baseline" to start with. It's just a simple website, but great in its simplicity. I like the way they used the English language to point out what's really needed in the application.
A view model is a conceptual model of data. Its use is to for example either get a subset or combine data from different tables.
You might only want specific properties, so this allows you to only load those and not add unnecessary properties.
ViewModel contain fields that are represented in the view (for
LabelFor,EditorFor,DisplayFor helpers)
ViewModel can have specific validation rules using data annotations
or IDataErrorInfo.
ViewModel can have multiple entities or objects from different data
models or data source.
Designing ViewModel
public class UserLoginViewModel
{
[Required(ErrorMessage = "Please enter your username")]
[Display(Name = "User Name")]
[MaxLength(50)]
public string UserName { get; set; }
[Required(ErrorMessage = "Please enter your password")]
[Display(Name = "Password")]
[MaxLength(50)]
public string Password { get; set; }
}
Presenting the viewmodel in the view
#model MyModels.UserLoginViewModel
#{
ViewBag.Title = "User Login";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm())
{
<div class="editor-label">
#Html.LabelFor(m => m.UserName)
</div>
<div class="editor-field">
#Html.TextBoxFor(m => m.UserName)
#Html.ValidationMessageFor(m => m.UserName)
</div>
<div class="editor-label">
#Html.LabelFor(m => m.Password)
</div>
<div class="editor-field">
#Html.PasswordFor(m => m.Password)
#Html.ValidationMessageFor(m => m.Password)
</div>
<p>
<input type="submit" value="Log In" />
</p>
}
Working with Action
public ActionResult Login()
{
return View();
}
[HttpPost]
public ActionResult Login(UserLoginViewModel user)
{
// To access data using LINQ
DataClassesDataContext mobjentity = new DataClassesDataContext();
if (ModelState.IsValid)
{
try
{
var q = mobjentity.tblUsers.Where(m => m.UserName == user.UserName && m.Password == user.Password).ToList();
if (q.Count > 0)
{
return RedirectToAction("MyAccount");
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
catch (Exception ex)
{
}
}
return View(user);
}
In ViewModel put only those fields/data that you want to display on
the view/page.
Since view reperesents the properties of the ViewModel, hence it is
easy for rendering and maintenance.
Use a mapper when ViewModel become more complex.
View model is same as your datamodel but you can add 2 or more data model classes in it. According to that you have to change your controller to take 2 models at once
A viewmodel is a usually an aggregation/combination of two or more models.
Let's say we have a DB with two tables called Student and Course with two models each. On the client side we have two views to render each table.
Imagine you need another view that renders both students and courses? Then you can create a a so called viewmodel. Which is basically a class that takes both Models i.e Students and Courses.
Class CombinedStudentsCourses will be the view model and can be returned by the view.
public class Student
{
public string? Name{ get; set; }
public string? Email{ get; set; }
}
THIS is our view model with two models combined inside.
public class Course
{
public string? CourseName { get; set; }
public string? CourseCode { get; set; }
}
ViewModel i.e combining two or more models to satisfy the specific needs of our view.
public class SchoolSystem
{
public Students Student { get; set; }
public Courses Course { get; set; }
}
public ActionResult<SchoolSystem> Index()
{
var SchoolSystemViewModel = new SchoolSystem();
// now we have access two to tables i.e two models in our
//view.
return this.View("SchoolSystemView", SchoolSystemViewModel,);
}

Resources