I am currently working on an ASP.NET MVC project.
Some developers on the team want to bind the auto-generated database entities directly to the Views.
Other developers want to create tailor-made ViewModel's and bind those to the Views.
Objectively, what are the pros and cons of both approaches?
(By "database entities" I am referring to the auto generated classes that an ORM framework generates, such as LINQ to SQL, Entity Framework or LLBLGen).
Definitely use view models in your views, and use something like AutoMapper to create view models from entities easily.
Cons:
Sometimes it feels like you are duplicating code, specifically, when the view model and the entity have the exact same properties
Pros:
You often need to represent an object in a simpler format (often called flattening), but you need full fidelity on the server side. This allows you to transition between the two without mucking up your domain model with presentation cruft.
Aggregate roots often have a lots of value objects and additional entities that are irrelevant to a specific view, and omitting them in a view model makes it easier to work with.
Your entities will have lots of two way references that are sensible in terms of an API, but create pure hell when serializing them for JSON, XML, etc. View models will eliminate these circular references.
You may often use the same entity but in different ways for different views. Trying to balance both needs on one type can create a huge mess.
The orthodoxy is that you should never use your raw database entities in your views. Like any rule, it is there to be broken if you know your entities well and you understand the consequences, but there are very good reasons not to break that rule, particularly when working in teams and with code that will be maintained in future by people who might not understand the rule or the entities as well as you do. The main reasons are:
ORM lazy loading. Imagine your Customer has a lazy loaded collection Orders. You pass Customer off to the View and it iterates over Orders. You get an N*1 select on the Orders table. But it also means that your database connection still needs to be open in the View. There is a pattern that people use 'Transaction per Action' which disposes of the database context in the Action_Executed event, which happens before your View is rendered. So you could be trying to access the database after it has been disposed. Even if you are not doing that now, someone in future might decide to implement that pattern because it is fashionable.
The concerns of the ViewModel are different to the db Model. For example, you typically decorate your ViewModel properties with validation attributes. These typically are different or only concern the UI not the db. If you bind to your database entities you will find all these UI concerns polluting you DB entities.
Related to 2 - the requirements of the ViewModel may demand computed or derived properties. For example, a Fullname constructed from First and Last names. These kind of things are best kept in the ViewModel.
You can unit-test your ViewModels in isolation from the database. ViewModels can end up containing quite a lot of logic which needs to be unit-tested. This is easier to test if it is not tied to your database (as with EF entities).
In general, creating and maintaining ViewModels (even without AutoMapper) is not an overhead and you will find it is a much better pattern of development overall. I would recommend it for everything but the simplest cases (lookup lists of static data, for example).
I believe using view models is the only way to go, so no pros for ORM entities:) View models not only provide data for view, but they also define how view should look (by defining templates) or how it should validate (by adding data annotations or implementing IDataErrorInfo).
Using view models:
Pros:
View models contain only properties required by view, nothing else.
View models may contain specific validation rules using data annotations or IDataErrorInfo.
View models can combine values from different database entities.
View models document themselves and are not tied to any framework.
View models protect you from forged POSTs, containing values, that were not provided in form, but were contained in ORM entities.
You can specify easily display templates for view models and reuse them in many places using DisplayFor or EditorFor helpers.
Using ORM entities:
Cons:
ORM entities already contain data annotations, that can mess up your validation. Example: Password field in user may be markes as Required, but it is not required when you change only basic user info.
ORM entities are strongly tied to Framework (Entity Framework) and may be not easy to implement rules in.
ORM entities can contain properties for more than one view, but it is hard to separate validation rules for different views.
Using ORM entities with lazy loading can lead you to executing SQL queries when views are rendered. It shouldn't happen.
Using ORM entities can lead to using huge SQL queries instead on small ones. When you want to display dropdown with first name and last name, you should only retrieve first name and last name from database, not whole entities.
Thanks for the answers so far - they have been a big help in understanding the pros/cons of both approaches. I have one thing to add that no one else has mentioned.
Over-posting attack
A worrying disadvantage with binding directly against DB entities is an "over-posting attack". This is where the attacker, using a tool no more advanced than FireBug, can insert form fields that are not intended to be editable by the user, but which do exist on the DB entity.
Consider an "Edit my profile" page. Your view might look like this:
#using(Html.BeginForm() {
<div>
#Html.LabelFor(x=> x.FirstName)
#Html.TextBoxFor(x=> x.FirstName)
</div>
<div>
#Html.LabelFor(x=> x.LastName)
#Html.TextBoxFor(x=> x.LastName)
</div>
<input type="Submit" value="Save" />
}
It would render the following HTML:
<form action="/profile/edit" method="post">
<div>
<label for="FirstName">FirstName</label>
<input type="text" name="FirstName" value="" />
</div>
<div>
<label for="LastName">LastName</label>
<input type="text" name="LastName" value="" />
</div>
<input type="Submit" value="Save" />
</form>
Using FireBug, an attacker merely needs to insert a chunk of HTML inside the form:
<input type="hidden" name="IsAdmin" value="true" />
...and suddenly users are able change data in very unexpected and harmful ways.
Here are some even scarier hidden form fields:
<input type="hidden" name="ShoppingCart.Items[0].Price" value="0.01" />
<input type="hidden" name="BankAccount.Balance" value="1000000" />
<input type="hidden" name="User.Administrator.Password" value="hackedPassword" />
Ouch!
Info taken from:
http://hendryluk.wordpress.com/tag/asp-net-mvc/
I once tried to develop an app which used NHibernate entities directly in ASP.NET views. I ran into many problems with Lazy loading and deferred SQL execution running directly from the views rather than in the business logic layer or even controllers. Moving to a viewmodels and using automapper seemed to solve all these problems and make the app easier to test, debug and maintain.
I also found that view models were helpful in holding all the associated data I needed on a page. Some developers like to use the dynamic ViewBag for this, but this is bad for testing and debugging.
In particular, view models made it easy when you wanted to pick associated entities from dropdown lists.
AutoMapper was a lifesaver on this project, as it saved having to write a ton of mapping code, all I had to do was create the view models and then the controllers automapped from entities to view models.
Do not expose backend-entities to the client.
Real world application have behaviour -not CRUD. It you databind your entities to the view it will just be a matter of time before you dig into muddy hack when behaviour is required on the clientside.
I was just about to add exactly the same sentiment as hackedbychinese. also i'd add, with fk's to lookup lists, you just HAVE to use viewmodels as the entity model merely will hold a pointer to a single id within that table. A viewmodel allows you to pass the required populated list into the view - voila.
Also, a viewmodel can contain discreet logic where required, this would definately NOT be the case with the entity model. Also, your validations may vary depending on the use of your view, therefore different validations can be applied per 'view' requirement.
The purpose of a ViewModel is mainly separation of concerns - decoupling the View from the implementation details of the Model.
Using DB entities in your views, especially your forms is a massive security issue. Take the following POCO object
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Email { get; set; }
public bool IsAdmin { get; set; }
}
Now say you are presenting a view that allows a user to change their email. The MVC method for processing the form result when using Db Entities instead of view models would look like: (unless you don't use model binding, in which case you are making more work for yourself)
public class HomeController : Controller
{
[HttpPost]
public ActionResult ChangeEmail(User user)
{
//....
}
}
Model binding in Asp.net works by looking for GET or POST parameters matching the names of the properties in the model. Therefore, all the user has to do is add IsAdmin=true to the POSt parameters and viola, the model passed into the ChangeEmail function will have the IsAdmin property set to true, which could very easily be accidentally added into the database, giving users free access to change data they didn't have access to change.
This goes for user permissions, changing who owns an entity (make your question be associated with me instead of you), change original creation dates, etc...
Related
I have an asp.net-mvc site that pretty much is a CRUD app but I also do some adds & updates outside the webview (upload from spreadsheets, etc). Based on this article, I am trying to get as much of the logic outside the MVC project into a seperate shared project so i can reuse the same code in all scenarios and I am trying to isolate and seperate my "read" viewModels that are binding to UIs for display from the "edit" viewModels that represent what is being posted to the server on a form post.
I have a number of projects in the solution (domainobjects, importexport,etc) that are shared with other solution plus the MVC project has the following directories in the MVC project
Controllers
Views
ViewModels
Scripts
EditViewModels
My ViewModels folder represents the objects that I am binding to my views (a container object that usually includes:
A domain object and
A bunch of IEnumerable of SelectListItem to populate UI dropdowns, etc
something like this:
public class OrderViewModel
{
public Order MyOrder {get;set;}
public IEnumerable<SelectListItem> OrderTypes {get;set;}
public IEnumerable<SelectListItem> Sizes {get;set;}
}
My EditViewModels folder represents the objects that i am posting from forms to the server so they are usually simpler flat objects with just primatives that i then populate a domain object with before adding or updating my database like this:
public class OrderEditViewModel
{
public int Id {get;set;}
public int OrderTypeId {get;set;}
public int SizeId {get;set;}
}
My main question is when i have a method in my Controller class that usually looks like this (simplified):
public ActionResult Update(OrderEditViewModel order)
{
var existingOrder = _repository.GetOrder(order.Id);
existingOrder.Name = order.Name;
existingOrder.Size = _repository.GetSize(order.SizeId);
existingOrder.Price = order.Price;
_repository.Save(existingOrder);
return Json( Result = "Success");
}
I am trying to figure out how to get as much code as possible outside the MVC project but that forces me to move all of my classes in the EditViewModel outside of the MVC project so those objects can be reused.
Does anyone see anything wrong with having these "Post" data structure classed outside the MVC projecdt. Given its a "viewmodel" class it feels wrong to move it away from the view but I don't see any other way to share this code outside of the MVC project. Maybe the "viewModel" name here is just wrong possibly?
Your View Models are specific to your views, and should not be relevant to anything else. They contain things which nothing else should care about, such as your select lists. As such, they should stay in your UI.
The article appears to me to be creating a situation in which the business logic depends on the UI (or at least the UI Model.. ie View Model), and I think that is the wrong approach. The UI should be able to consume the business logic without the business logic being aware what the UI is. It could be a web site, a fat client, a mobile client, a web service, etc... By making this logic depend on your view models, you now are making any future services that are not web based depend on those.
This is, however, a simple CRUD app, and in simple CRUD apps you can often take a lot of shortcuts because it's just not worth the extra engineering effort. I wouldn't normally pass a domain object to the view directly in the View Model. But in this case it's probably the best choice.
If you want to do it "right", however, then you need to create more separation of concerns. Your domain and ui layers need more separation. You create separate view and domain models, and then map between them. This prevents the business layer from knowing anything about the UI.
I would probably create a service layer that handles your logic. For instance:
_orderService.UpdateOrder(order.Id, order.Name, order.Price);
In my case, i make a difference between read(view-)models and write-models.
Read models are very specific to the view, they can contain select lists and formatted and localized content. You should not move this models outside of your ui-project. Of course you can make a separate assembly with your models, or you can make one assembly per module, but you should never consume these models from your domain layer.
Write models - in my opinion - are not that specific to your UI. Instead they represent the data that is required by the command (e.g. SaveUserCommand). They can contain validation attributes, so your domain layer can validate them easily and they can be shared by domain layer and UI. In my project I have one class per command (e.g. SaveUserCommand, EditUserCommand, DeleteUserCommand) and related models (SaveUserModel, EditUserModel). Somebody will comment, that the they also contain some UI-specific code (e.g. the IClientValidateable itnerface for attributes or the attributes itself) and at least the IClientValidateable interface is a problem that I am willing to ignore to reduce the number of models. My experience with this approach (I also tried others) shows, that these models are very easy and it very easy to bind to these models.
Sometimes you will also have the problem, that you want to show some additional information in the edit-view. Instead of adding all this information to the viewbag, I will have another model, for example:
class UserEditModel
{
string Password;
}
UserEditViewModel
{
DateTime Modified;
UserEditModel Edit;
}
So my advice:
Create write-models that have all the data and validation logic that is specific to your use cases.
Create view models that contain all data you want to display and try not to use the ViewBag.
If you have a form, add the write-model to your view model. The write-model has all the data that will be sent back to your server via POST and then directly to your domain layer.
I use four "layers" in two assemblies
{application}.app assembly with three namespaces, just a regular class library project.
1) {application}.model for domain model
2) {application}.data for data using repository pattern
3) {application}.services for all business logic
{application}.WebUI assembly for the UI, this is the MVC project
Controllers only call services and services get and update data through the repositories.
There is an services API for every operation your app has to do, i.e.
OrderServices.Update (existingOrder)
OrderServices.Approve (existingOrder)
Services layer only know domain models, and controllers just assemble the viewmodels, using the domain models gotten from services, to send them to the views and prepare the domain models using the viewmodels gotten from the views to send them to the appropiate service.
This way you can eventually create an {application}.WebAPI or whatever that uses the same {application}.app assembly reusing all of the buissiness logic and keeping viwemodels where they belong (the WebUI project)
Hope this helps.
Best regards.
You could use a service architecture of your project , where all function and db queries are in this files and which you could using just by adding this code
IOrderService<Order> service = new OrderEntityService();
and use it like
service.Create(Order) or service.Update();
Whats strange to me is you're taking care and effort to layer out your app as much as possible, but you're still letting your MVC controller contain a lot of your logic. You're trying to share the objects and models, but the logic to add a new OrderEditViewModel is not shared, its stuck within that controller.
What I try and do is create a "helper" or "logic" class for each of my controllers. That logic or helper class is then injected into my controllers and wrapped in an interface. My controller can save, edit and remove items through my helper class, but has no knowledge of how its actually doing that.
I have then shared these logic classes along with the models to other projects, allowing a lot of code re-use. The problem is just ensuring that none of the "HTTP'ness" of the controllers sneaks into your logic classes, as these must be usable in a console or winforms application. So you have to be pretty strict and wrap a lot of things like HTTPSession or HTTPContext into interfaces that can then have non HTTP implementations..
Well, I understand your situation and also tends to a DDD (Domain Driven Design) solution as #MystereMan suggests.
I have an approach that sepparates the "Models" in 3 categories:
ViewModels: Have all the information necessary to display content data in the UI
RequestModels: Have all the information necesssary to send data, post/get/etc.)
AutoBindModels: Have all the information that is injected my MVC binding model (cookies, sessions, etc..)
And the most important, for all that classes I use as DTO/POCO's, actually they have no UI dependent code just properties/calculated properties and could be easily in any other project to be referenced by an UI project.
You could also create a Controller class that act as a Service outside ASP.MVC project and extend or inject it in your MVC controller.
Hope it helps...
I never reuse (Edit)ViewModels objects (this is not entirely true, I often share one EditViewModel between Create and Update but not always).
I design my ViewModels for specific Views. Therefore, I don't have to compromise my ViewModels when the UI changes (it changes all the time).
I take this as far as creating two distinct ViewModels even if they are identical. I'm done refactoring shared ViewModels..
I would answer yes to your question.
Hope it helps.
OrderEditViewModel and OrderViewModel are both 'ViewModels' end of the day. IMO, they may stay together in the same project even in your same 'ViewModels' folder. You may though create a sub folder under ViewModels for your 'EditViewModels'.
Now as you want to clean/tidy up the controller actions, you may want to use AutoMapper or ValueInjecter. You are mapping domain entity and view models manually. That is a tiresome job. With AutoMapper you can do something like:
var customerInfo = Mapper.Map<CustomerViewModel, CustomerInfo>(customerViewModel);
I am relatively new to MVC. I am trying to just display the contents of a remote SQL Server table on a page. It is READ ONLY, and nearly everything I find online is utilizing the Entity Framework or something similar which is overkill for what I am after. I just need to print all the rows from a table out to a view.
So my questions are:
should I just hack the sqlconn and everything into the view that I want the data printing out to?
Or should I add the sql in that view's controller?
Create a model and somehow get that data back into the view?
I know step #3 is the 'correct' way to do it, however I am looking for something simple and quick. :)
Thanks everyone!
You say EF is overkill, but that's the easiest way to do this. Maybe use Linq to SQL, since that's more lightweight. This is all there is to it:
Generate the EF / L2S entity classes
Instantiate the database context in the controller, and get all records
Return the IEnumerable records to the view
In the view, use #Html.DisplayForModel()
Here's a simple example. Note that returning the database entity classes is considered bad practice, you should map / automap them to a View Model type class first.
Home Controller
public ActionResult Index()
{
MyEntityModel[] items = MyDatabaseContext.GetAllRows();
return View(items);
}
Home/Index View
#model IEnumerable<MyEntityModel>
#foreach (MyEntityModel item in Model)
{
#Html.DisplayFor(m => item)
}
Without EF / L2S it's almost as easy, but you'd have to create your own entity / wrapper class for the database records and populate them manually.
There are also scaffolding projects for MVC that will generate repository and controller classes, as well as Razor views. See for example MVC Scaffolding on NuGet.
Once you get used to forcing yourself to use Entity Framework for even your "small" applications then and only then will you truly understand that is it the simplest way.
Sure, if you come from a background of memorized ADO.NET dataset/datatable/datareaders etc.. then sure you have projects with "canned" operations that you port over and modify but it is truly just old and cost you more time in the long run.
Use EF
Use multiple projects in a solution
Use a repository pattern if you can, it pays off in dividends for reasons you will discover
Keep your controllers "skinny"
Dont' use a "ViewModel" just to use / do it.
The SOC of having View and Controller are critical, but the Models folders does not need to be used, you can wire things up without it if you want, just pay attention to where your "model" is and abiding by SOLID principle etc..
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
Improve this question
For the ViewBag, I heard it was a no-no to use.
I would assume have the content from the ViewBag should be incorporated into a view model?
Question:
Is my assumption above the best practice. (Not to use a ViewBag and second to have it in the view model)
Are there situations where a ViewBag is absolutely necessary?
ViewBag is a dynamic dictionary. So when using ViewBag to transfer data between action methods and views, your compiler won't be able to catch if you make a typo in your code when trying to access the ViewBag item in your view. Your view will crash at run time :(
Generally it is a good idea to use a view model to transfer data between your action methods and views. view model is a simple POCO class which has properties specific to the view. So if you want to pass some additional data to view, Add a new property to your view model and use that.Strongly typed Views make the code cleaner and more easy to maintain. With this approach, you don't need to do explicit casting of your viewbag dictionary item to some types back and forth which you have to do with view bag.
public class ProductsForCategoryVm
{
public string CategoryName { set;get; }
public List<ProductVm> Products { set;get;}
}
public class ProductVm
{
public int Id {set;get;}
public string Name { set;get;}
}
And in your action method, create an object of this view model, load the properties and send that to the view.
public ActionResult Category(int id)
{
var vm= new ProductsForCategoryVm();
vm.CategoryName = "Books";
vm.Products= new List<ProductVm> {
new ProductVm { Id=1, Name="The Pragmatic Programmer" },
new ProductVm { Id=2, Name="Clean Code" }
}
return View(vm);
}
And your view, which is strongly typed to the view model,
#model ProductsForCategoryVm
<h2>#Model.CategoryName</h2>
#foreach(var item in Model.Products)
{
<p>#item.Name</p>
}
Dropdown data ?
A lot of tutorials/books has code samples which uses ViewBag for dropdown data. I personally still feel that ViewBag's should not be used for this. It should be a property of type List<SelectListItem> in your view model to pass the dropdown data. Here is a post with example code on how to do that.
Are there situations where a ViewBag is absolutely necessary?
There are some valid use cases where you can(not necessary) use ViewBag to send data. For example, you want to display something on your Layout page, you can use ViewBag for that. Another example is ViewBag.Title (for the page title) present in the default MVC template.
public ActionResult Create()
{
ViewBag.AnnouncementForEditors="Be careful";
return View();
}
And in the layout, you can read the ViewBag.AnnouncementForEditors
<body>
<h1>#ViewBag.AnnouncementForEditors</h1>
<div class="container body-content">
#RenderBody()
</div>
</body>
1) Is my assumption above the best practice. (Not to use a ViewBag and
second to have it in the view model)
You should use viewmodels instead of passing data via ViewBag as much as possible.
2) Are there situations where a ViewBag is absolutely necessary?
There is no situation where a ViewBag is absolutely necessary. However, there are some data I personally prefer using ViewBag instead of View Model. For example, when I need to populate a dropdown box for predefined values (i.e Cities), I use ViewBag for carrying SelectListItem array to view. I prefer not to pollute my ViewModels with this data.
1) Is my assumption above the best practice. (Not to use a ViewBag and
second to have it in the view model)
Yes.
2) Are there situations where a ViewBag is absolutely necessary?
No. Everything that you have stored in a ViewBag could go into the view model passed to the view.
The issue with ViewBags and the recommended best practice boils down to compile time checking. ViewBags are just dictionaries and with that you get 'magic' strings, so if you end up changing the object type of one of the viewbag items or the key name you won't know until runtime, even if you precompile the views using <MvcBuildViews>true</MvcBuildViews>.
Sticking to view models is best, even if you have to alter them to fit a specific view now and again.
I have found some use for ViewBag where there is common functionality across all pages, and the functionality does not depend on the page being shown. For example, say you are building StackOverflow. The job board appears on each page, but the jobs shown have nothing to do with the page (my usage was similar in concept). Adding a property to each ViewModel would be difficult and time consuming, and a lot of fluff to your tests. I don't think it is worth it in this situation.
I have used a base ViewModel class with the cross cutting data, but if you more than one (e.g., jobs & list of stack exchange sites), you either have to start stuffing extra data in, or some other abuse of a ViewModel, plus you need a ViewModel builder to populate the base data.
As for the magic strings problem, there are a lot of solutions. Constants, extension methods, etc.
With all that said, if you have something that is displayed on your page that depends on the context of the page, a ViewModel is your friend.
Erick
No. Use ViewModels.
No. If you design a perfect ViewModel, you never need a ViewBag.
If you cannot re-design EXISTING ViewModel use ViewBag.
If there were no use cases for it, it wouldn't be implemented in the first place. Yes you can do everything with ViewModels, but what if you don't really need one? One such scenario is editing entities. You can pass DTO directly as a model.
#model CategoryDto
<div class="md-form form-sm">
<input asp-for="Name" class="form-control">
<label asp-for="Name">("Category Name")</label>
</div>
But what if you want to select Category parent? Entity DTO ideally holds only it's own values, so to populate select list you use ViewBag
<select asp-for="ParentId" asp-items="ViewBag.ParentList">
<option value="">None</option>
</select>
Why do this? Well if you have 50 types of entities each with some sort of select from different values, you just avoided creating 50 extra ViewModels.
I thought I'd give my opinion on this, as I've used the ViewBag extensively.
The only real benefits you'll get from using it are for a small project, or in cases where you have a new project and just want to get the ball rolling and not have to worry about creating loads of model classes.
When your project is more mature, you may find issues with unexpected behaviour caused by using weak typing all over your application. The logic can be confusing, difficult to test and difficult to troubleshoot when things go wrong.
I actually went down the route of completely removing the ViewBag from my applications, and preventing other developers from using it within the same codebase by throwing compilation errors when they try to, even within Razor views.
Here's a sample ASP.NET 5 project on GitHub where I've removed it: https://github.com/davidomid/Mvc5NoViewBag
And here's a blog post where I explain the motivations for removing it and an explanation on how the solution works:
https://www.davidomid.com/hate-the-aspnet-mvc-viewbag-as-much-as-i-do-heres-how-to-remove-it
2.Are there situations where a ViewBag is absolutely necessary?
In some case you'll need to share your data from the Controller across the layouts, views and partial views. In this case, ViewBag is very helpful and I doubt there's any better way.
At the risk of opening up an old can of worms here, let me offer a tiny bit of insight. Regardless of what might be the "best practice," let me offer the real-world experience that the extensive use of ViewBag can be a nightmare source of niggling, hard to find bugs and issues that are an utter nuisance to track down and resolve. Even if an agreeable notion or rule for the use of ViewBag can be established, they too easily become a crutch for junior developers to rely on to distraction AND discourage the development of proper, strongly typed ViewModels.
Unfortunately, too many "tutorial" YouTube videos show the use of ViewBags for a demonstration purposes and offer little to no insight on when such a practice isn't appropriate for production code. Yes, there may be times when use of the ViewBag may be a suitable solution to a given problem, but can lead to a long and winding road of frustration and poor maintainability. At the risk of overcorrecting in the cautious direction, I would encourage younger developers not to rely on the ViewBag until they get more experience with MVC, develop a natural sense of when and how ViewModels are useful, and then after that time develop a more seasoned sense of when the use of the ViewBag is appropriate.
OK, I have been hearing discussion about "ViewModels" in regards to MS's ASP.NET MVC.
Now, that is intended to be a specific kind of Model, correct? Not a specific kind of View.
To my understanding, it's a kind of Model that has a specific purpose of interacting with the View? Or something like that?
Some clarification would be appreciated.
Essentially Model and View Model are both simple classes with attributes.
The main objective of these classes are to describe (to "Model") an object for their respective audiences that are respectively the controller and the view.
So you are completely right when you say
To my understanding, it's a kind of
Model that has a specific purpose of
interacting with the View
So, while Model classes are effectively Domain Entities that your application interact with, View Models are simple classes that your views interact with.
Hope it helps :)
Update:
Microsoft has developed a specialized version of the Presentation Pattern by Martin fowler largely based on the Model-View-Controller and called it Model-View-ViewModel (MVVM) for PF application. This pattern is targeted at modern UI development platforms where UI developers have different requirements based more on business logic than traditional developers. Have a look here for a bit of theory
In the simplest of terms, I like to think of the following:
Model: Strictly looks and feels like your data model. For all intents and purposes it is only a class representation of your data model. It has no knowledge of your View or any elements within your View. That said, it should not contain any attribute decorators (ie; Required, Length, etc.) that you would use for your View.
View Model: Serves as a data-binder between your View and your Model and in many cases, is also a wrapper for your Model. It would be rendered useless without the View, so it typically isn't reusable across multiple Views and Controllers like a standard Model is.
As an example, your Model may have the following properties, which are direct representations of your data source:
public string FirstName { get; set; }
public string LastName { get; set; }
Now, since your View Model is tied to your View, it may have the following property - which concatenates the Model's FirstName field and LastName field together as one string:
[Display(Name = "Customer Name")]
public string CustomerFullName { get { return String.Format("{0} {1}", myModel.FirstName, myModel.LastName) }}
I found this article a very useful resource for understanding how the "Domain Model" and "View Model" interact within an MVC application, particularly in regards to binding. Best of all includes examples instead of abstract descriptions.
"Since MVC has been released I have observed much confusion about how best to construct view models. Sometimes this confusion is not without good reason since there does not seem to be a ton of information out there on best practice recommendations. Additionally, there is not a “one size fits all” solution that acts as the silver bullet. In this post, I’ll describe a few of the main patterns that have emerged and the pros/cons of each. It is important to note that many of these patterns have emerged from people solving real-world issues."
http://geekswithblogs.net/michelotti/archive/2009/10/25/asp.net-mvc-view-model-patterns.aspx
WikiPedia has a more complete description of Model vs. ModelView than you'll get in an SO answer: http://en.wikipedia.org/wiki/Model_View_ViewModel
I quote:
Model: as in the classic MVC pattern, the model refers to either (a) an object model that represents the real state content (an object-oriented approach), or (b) the data access layer that represents that content (a data-centric approach).
View: as in the classic MVC pattern, the view refers to all elements displayed by the GUI such as buttons, windows, graphics, and other controls.
ViewModel: the ViewModel is a “Model of the View” meaning it is an abstraction of the View that also serves in data binding between the View and the Model. It could be seen as a specialized aspect of what would be a Controller (in the MVC pattern) that acts as a data binder/converter that changes Model information into View information and passes commands from the View into the Model. The ViewModel exposes public properties, commands, and abstractions. The ViewModel has been likened to a conceptual state of the data as opposed to the real state of the data in the Model.
There is a notion of a ViewModel, but it is not generally associated with Asp.net MVC. MVC uses the Model View Controller patter, where the controller handles interactions, builds up data from the Model, and then passes that data to the View for display.
ViewModels (and the Model View ViewModel pattern) is more generally associated with Silverlight and WPF. Xaml is a bit different in that the views can do two-way binding to the ViewModels, so the technology is a little different. For example, if you bind a textbox to a field, as you type into that textbox, the value of the field is updated dynamically. This sort of interaction isn't really possible in web pages since web pages are stateless.
The similarity in the two patterns is that they are both trying to separate the logic from the display. The most common use/reason for this is testing: you want to be able to perform from code (via a testing framework) all the interactions that a user will invoke via the User Interface.
I've got a View where I use a naming-convention on my text-fields, to indicate what should be done with the content once it is posted back to my controller.
The format is similar to:
<input type="text" name="RegistrationLine#ID" />
for updates
<input type="text" name="CreateRegistrationLine#LineNumber" /> for create
Now since I'm using this Naming-convention, regular model-binding isn't possible. But I've been reading up a bit on the subject and did find a bit of an indication that it would be possible to write a custom model binder, that should be able to help parse and bind these form elements and instantiate the objects correctly.
Please read: Bind formValue to property of different name, ASP.NET MVC
This is a bit similar to what I am doing except, I have the additional complexity of having appended information in the formelement-name that I am trying to bind to.
Am I way off base here? and if not, can any of you drop a few lines of code to show how you would start this model-binder off..
If this is a very bad approach to what I am really trying to achieve, I would love to hear suggestions for better approaches. Just note that what I want to be able to do is post back both updates and creates in one go.
I kinda have to agree with #jfar and #omar. I don't think a custom model binder is where you want to be in this instance.
You can pass a complex type to your view and simply use the full stop like #jfar mentioned.
id="Model.Person.Name.FirstName" will happily bind to an object named Person that has a class in it called Name that has a property called FirstName.
Now if you want to do some special checks on the data you could implement a partial class which would do the validations etc and populate the ModelState errors.
public partial class Name
{
public void Validate(){ }
public int CreateRegistrationLine(){ }
public bool DoSpecialActions(){ }
}
It's a little unclear what your special actions are doing so my example above may not be what you want.