If you have scenario of a User that has many Roles and Roles that have many users. Using MVC is there an easy way to bind to the model directly? If your user class has a list of roles and the roles class has a list of users.
Thank you.
Model binding in MVC is fairly strong. You have to remember that naming conventions are important, especially when you start attempting to bind collections. To bind to a collection, you have to name your form field something to the effect of name="Model.Roles[]" (where Model is User; that would be dependent on your view being strongly typed to your User object; change accordingly). The brackets denote a collection of information being sent back up to the server. If you want to target a specific point in the collection, perhaps targeting a specific property on that point, you might have something like name="Model.Roles[x].Id where x is a valid index in the collection. It takes some effort to ensure you have these correct, and my approach almost always degrades into sending a custom collection of information back to the server and manually creating the relationships in the action method prior to saving the entity in question.
Phil Haack has a post about binding to a collection, albeit from 2008. It's still relevant, however, and might give you more insight into the model binding behavior.
Related
With MVC3, should I design my view models such that there is one that is bound to the view (DisplayModel), and one that is posted back to the controller (EditModel)?
To clarify, I am not asking about data models vs. view models -- I know it's not good to bind my views/controllers to data/domain models.
Nor am I asking about sharing one model across two separate views, one view that is used for displaying the data, and another view that is used for editing the data.
Rather, I am asking about one view that is used for editing data, and the model that is bound to the view vs. the model that is bound to the controller action.
In other words, if this is my view:
#model MyApp.Models.CustomerModel
Should my controller action look like:
public ActionResult Index(CustomerModel model)
Or:
public ActionResult Index(CustomerEditModel model)
At one point, we were doing the latter (separate). But lately, we've started doing the former (shared).
The reason for this change was because:
With MVC3 unobtrusive validation, if I'm using DataAnnotations on my model for validation, this is needed in both models if they are separated (on the display model to map client-side validation, and on the edit model for server-side validation).
As our application matured, we realized that our display and edit models were 95% identical, with the exception of the select lists that were in our view models. We've now moved these to a shared class and are passing these in via the view now.
But I've seen some other discussions that point to having shared models for view/controller to be a bad idea, and that it violates separation of concerns.
Can someone help me understand the tradeoffs for these two approaches?
I've seen perfectly good arguments for and against, it just depends what works best for your application. There's no one size fits all approach that can be applied!
If you haven't read it Jimmy Bogard has written a very good post about how his team does MVC here, which covers this topic.
I agree with rich.okelly's answer that there's no right approach.
There are a couple of concerns I have with using one model, though.
It's going to be very to always use one model without having unneeded properties when the view needs to display a selectable list of objects. The model will need to have the list of objects as well as a property to accept the POSTed value the user chooses. These unneeded properties add a small amount of code clutter and overhead.
(One way around this is to have the model contain only selected ID and have HTML helpers to build the lists.)
Another concern is more related to security.
A common scenario is displaying information in a form that should be considered read-only.
In the case of a ViewModel and an EditModel, the EditModel will only contain properties that are expected to be POSTed, whereas the ViewModel will contain all of the properties.
For example, if a form displays a user's salary, a user will be able to POST a 'salary' and have it bound to the ViewModel's Salary property automatically by MVC.
At this point, something has to be done to ensure it doesn't end up in the database. It could be if/else logic, a Bind attribute, Automapper logic or something else, but the point is that it's a step that could be overlooked.
When considering the lifespan of an application, I like the explicitness of the EditModel over time.
These concerns don't mean that two models are good and one model is bad, but they should be considered when choosing a design.
If the properties are the same for display and edit view models I see no reason to have separate classes.
I think you'll find that it's hit or miss no matter what way you go but if you can take the path of easiest maintainability then you should do that. In my experience, having a single model is much easier to maintain, obviously, but it seems that there is always some business decision that is made that forces me to split the models. If you're in that 95% then I think you are in really good shape. Your application, from a maintainability perspective related to your models, will be easy to maintain. When a change comes along, you have one place to make that change, for the most part. The issue I always seem to run into is scaling business changes across multiple models. Copy/paste issues, or simply forgetting about some property somewhere, always seems to hurt me because of the multi-model issue.
we realized that our display and edit models were 95% identical, with the
exception of the select lists that were in our view models. We've now
moved these to a shared class and are passing these in via the view now.
Are they 95% identical in data and operations or only in data? Remember that classes encapsulate data and behavior.
If they are 95% similar in properties but have totally different operations you might benefit from splitting them in two classes. Or you might not :)
As others pointed out there is no one-size-fit-all answer and in your case it seems that one class is OK...but if you start noticing that the behavior on each of them is unrelated don't be afraid to rethink you approach.
No - one view model for both directions. Mixing it up is not only harder to follow, but one could easily inject invalid values into the page that then get automatically bound. I could overwrite your customerid (or create one) for example.
Inherit from a base view model if you must or don't rely on data annotations at all and use the fluent api on your model save.
A great link (somewhat unrelated but the auto map is nice)
edit
(sorry someone else previously posted this below I just realized)
http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/
Also
ASP.net MVC - One ViewModel per View or per Action?
You (IMHO) should be generally binding to your method specific VieWModel rather than a shared view model. You could get caught in a trap of missing properties, etc. but it may also work just fine for you.
Use auto mapper to go between both. Jimmy also has a nice AutoMap attribute when returning to the View. Going back the other way I would not use a CustomerModel in general as there may be fields required in there that are not coming from my say, create view. For example a customer id may be a required field and for a "create" action it won't be present. But - if you find in the most of your cases this to actually work for you, then there is no reason at all not to use it.
I'm coming to the end of my first MVC project, and I'm not overly happy with how I constructed my Model objects and I'm looking for some ideas on how to improve them.
I use repositories for each DB table with Get, Save, Delete etc methods.
The repositories use Linq2Sql for the DB access.
I do mapping from the Linq2Sql objects to MVC Model objects, in the main, these are very much 1 to 1 mappings.
My problem is, I don't think my MVC model objects were granular enough, and I am probably passing more data back and forth than needed.
For example, I have a User table. An admin can edit a users details as can the user themselves, so I reckon I should really have a "AdminUserModel" and "UserModel" objects, where "AdminUserModel" has a greater set of values (IsEnabled for example).
So my bigger question is really, what kind of architectures are people using out there in the wild, in order to map many similar, related Model objects down through the layers to the DB?
Any sample architecture solutions anyone can suggest beyond NerdDinner?
thanks in advance!
In the case of your user model, you should use inheritence in stead of 2 seperated models. In this way you can use the code that was created for user in the ones that inherite from it.
the type of model you use depends completely on what you want to do with it. A good thing might be to take a look at patterns and try to get the patterns working that are needed for your situation...
I usually take implement inheritance in my models.
I usually have a base class of entity, which will have id, datecreated, valid and any other fields that are shared between entities (publishStatus, locked etc).
If needs be you can create other base classes inheriting from entity: person entity, product entity etc.
this way you can have a generic repository base, constrained to Entity or IEntity, i find that most entities CRUD functions dont need much more behaviour than that provided by the generic base (perhaps you will need to add a few additional get methods for some types)
In your case, AdminUser could inherit from User
Background
I have a payment page where the user can select from a list of existing payment methods, or specify a new one. The dropdown presents options such as:
Visa - ******1234 (Saved)
Mastercard - ******9876 (Saved)
[New Credit Card ...]
[New Electronic Check ...]
Using jQuery, I toggle hidden DIVs that contain either an informational table (in the case of options 1 or 2 for saved payment methods) or a form (in the case of the [new] options).
I am using a strongly typed class as my view model which contains (among simple types) a CreditCard class and a Check class. Each of these classes uses data annotation validators, as they are used in other parts of the site.
Problem
The problem comes in when the user submits the form. I would like to use model binding to handle the mapping of POST values, but I need the binding and/or validation to fire depending on which option the user selected. For example, if the user selects option 1 or 2 from the list above, I don't want the model validation (or maybe even the binding itself) to fire for the CreditCard or Check objects.
I have researched the possibilities of creating a custom model binder using IModelBinder as well as extending the DefaultModelBinder and just overriding some of the methods. However, I am unsure as to which method is better, and, if extending DefaultModelBinder, which would be the appropriate method to override.
The logic would be fairly simple:
If the user selected one of the existing payment methods, no validation on the CreditCard or Check are required.
If the user selected one of the options to create a new payment method, then only the selected method (CreditCard or Check) needs to be bound and validated
It feels as if extending the DefaultModelBinder is the way to go, as I would like most of the heavy lifting to be done by the framework without the need to create a custom binder from scratch. However, when looking at the available methods to override, it's not clear which is the best one(s):
BindProperty - The problem here is that I basically need to look at one of the properties to determine what other properties should be bound. I don't think I can control the order in which the incoming properties are bound, and I wouldn't want to rely on the order they are set in the HTML form.
OnModelUpdated - By this point, it's too late. The binding validation from the data annotations has been triggered and the ModelState has been updated. I would have to loop through the ModelState and remove the errors that are not relevant.
OnPropertyValidating - At first I thought this is where I should look, but even returning TRUE for all properties (as a test) causes the ModelState to contain binding errors.
I have come across this scenario in other aspects of the application and decided to split up functionality into separate controller/actions to simplify the process. However, I would like to have a better understanding of how to approach more complex UI problems, particularly related to the MVC model binding features.
Any help on this subject would be greatly appreciated.
All the possible values are stored in a dropdown list. Using jQuery, I toggle the form (for a new payment method) and the display (for an existing method)
I have decided to try to circumvent model binding altogether and use FormCollection, IValueProvider, and TryUpdateModel inside my controller action.
Your issue sounds way to specialized to be placed in the default ModelBinder.
The ModelBinder is this seductress that lures you in on the pretense that she can solve all of your problems. But then you start merging ModelState's together and going off to do crazy things with nested objects lists and before you know it she slaps you with divorce papers and takes everything but your bones.
MVC 3 holds some promise to provide a more extensible ModelBinder but from my own personal experience unless its super simple what you need to change, such as empty texboxes becoming "" instead of null, than stay clear away from your own implementation.
The alternative approach is to use the existing ModelBinder functionality piecemeal and using things like Ignore method parameters to clean things up:
if( myModel.IsNewPayment )
UpdateModel( myModel.Payment, "exclude everything else" );
A lot of what your proposing to stuff into the model binder is really business logic too that should be in another layer. I've done some crazy things with my own ModelBinder and now regret every line of code I've written in there. Maybe its just me but your really bending the rules and completely trashing the "single responsibility principal" by putting business and payment logic in there.
I have such scenario when i have to load controls dynamically.
I have untyped view and a set of strong typed controls.
All strong typed controls has completely different models.
The questions is, how to create kind of generic post action method wich allows to get all this models on post?
May be some one may suggest the more efficient way of doing this?
Load controls dynamically (kind of wizard, prev/next) and then catch data on post action.
I just was thinking that i may have post action for each step for each model. I will try it now.
Any more ideas are welcome :)
Assuming you can determine from the request what models you created for edit, you could just recreate those objects and call UpdateModel() on each one.
Of course, you'll need to make sure the fields names don't overlap between the object types.
Also, you'll need to look at the implications of using dynamic objects in UpdateModel(). To get around the limitations look at the code I posted here:
MVC 2 UpdateModel on Interface, Should ModelBinderAttribute be ignored?
When I started using xVal for client-side validation, I was only implementing action methods which used domain model objects as a viewmodel or embedded instances of those objects in the viewmodel.
This approach works fine most of the time, but there are cases when the view needs to display and post back only a subset of the model's properties (for example when the user wants to update his password, but not the rest of his profile data).
One (ugly) workaround is to have a hidden input field on the form for each property that is not otherwise present on the form.
Apparently the best practice here is to create a custom viewmodel which only contains properties relevant to the view and populate the viewmodel via Automapper. It's much cleaner since I am only transferring the data relevant to the view, but it's far from perfect since I have to repeat the same validation attributes that are already present on the domain model object.
Ideally I'd like to specify the Domain Model object as a meta class via a MetaData attribute (this is also often referred to as "buddy class"), but that doesn't work since xVal throws when the metadata class has properties that are not present on the viewmodel.
Is there any elegant workaround to this? I've been considering hacking the xVal sourcecode, but perhaps there is some other way I have overlooked so far.
Thanks,
Adrian
Edit: With the arrival of ASP.NET MVC 2, this is not only a problem related to validation attributes anymore, but it also applies to editor and display attributes.
This is the quintessential reason why your input screens should not be tightly coupled to your model. This question actually pops up here on the MVC tag about 3-4 times a month. I'd dupe if I could find the previous question and some of the comment discussion here is interesting. ;)
The issue your having is you're trying to force two different validation contexts of a model into a single model which fails under a large amount of scenarios. The best example is signing up a new user and then having an admin edit a user field later. You need to validate a password on a user object during registration but you won't show the password field to the admin editing the user details.
The choices for getting around these are all sub-optimal. I've worked on this problem for 3 projects now and implementing the following solutions has never been clean and usually frustrating. I'm going to try and be practical and forget all the DDD/db/model/hotnessofthemonth discussions everybody else is having.
1) Multiple View Models
Having viewmodels that are almost the same violates the DRY principal but I feel the costs of this approach are really low. Usually violating DRY amps up maintenance costs but IMHO the costs for this are the lowest and don't amount to much. Hypothetically speaking you don't change how max number characters the LastName field can have very often.
2) Dynamic Metadata
There are hooks in MVC 2 for providing your own metadata for a model. With this approach you could have whatever your using to provide metadata exclude certain fields based on the current HTTPRequest and therefore Action and Controller. I've used this technique to build a database driven permissions system which goes to the DB and tells the a subclass of the DataAnnotationsMetadataProvider to exclude properties based values stored in the database.
This technique is working great atm but the only problem is validating with UpdateModel(). To solve this problem we created a SmartUpdateModel() method which also goes to the database and automatically generates the exclude string[] array so that any non-permissisable fields aren't validated. We of course cached this for performance reasons so its not bad.
Just want to reiterate that we used [ValidationAttributes] on our models and then superceeded them with new rules on runtime. The end result was that the [Required] User.LastName field wasn't validated if the user didn't have permission to access it.
3) Crazy Interface Dynamic Proxy Thing
The last technique I tried to was to use interfaces for ViewModels. The end result was I had a User object that inherited from interfaces like IAdminEdit and IUserRegistration. IAdminEdit and IUserRegistration would both contain DataAnnotation attributes that performed all the context specific validation like a Password property with the interfaces.
This required some hackery and was more an academic exercise than anything else. The problem with 2 and 3 is that UpdateModel and the DataAnnotationsAttribute provider needed to be customized to be made aware of this technique.
My biggest stumbling block was I didn't ever want to send the whole user object to the view so I ended up using dynamic proxies to create runtime instances of IAdminEdit
Now I understand this is a very xVal specific question but all of the roads to dynamic validation like this lead to customization of the internal MVC Metadata providers. Since all the metadata stuff is new nothing is that clean or simple to do at this point. The work you'd have to do to customize MVC's validation behavior isn't hard but requires some in depth knowledge of how all of the internals work.
We moved our validation attributes to the ViewModel layer. In our case, this provided a cleaner separation of concerns anyway, as we were then able to design our domain model such that it couldn't get into an invalid state in the first place. For example, Date might be required on a BillingTransaction object. So we don't want to make it Nullable. But on our ViewModel, we might need to expose Nullable such that we can catch the situation where the user didn't enter a value.
In other cases, you might have validation that is specific per page/form, and you'll want to validate based on the command the user is trying to perform, rather than set a bunch of stuff and ask the domain model, "are you valid for trying to do XYZ", where in doing "ABC" those values are valid.
If ViewModels are hypothetically being forced upon you, then I recommend that they only enforce domain-agnostic requirements. This includes things like "username is required" and "email is formatted properly".
If you duplicate validation from the domain models in the view models, then you have tightly coupled the domain to the UI. When the domain validation changes ("can only apply 2 coupon per week" becomes "can only apply 1 coupon per week"), the UI must be updated. Generally speaking, this would be awful, and detrimental to agility.
If you move the validation from the domain models to the UI, you've essentially gutted your domain and placed the responsibility of validation on the UI. A second UI would have to duplicate all the validation, and you have coupled two separate UI's together. Now if the customer wants a special interface to administrate the inventory from their iPhone, the iPhone project needs to replicate all the validation that is also found in the website UI.
This would be even more awful than validation duplication described above.
Unless you can predict the future and can rule out these possibilities, only validate domain-agnostic requirements.
I don't know how this will play for client-side validation, but if partial validation is your issue you can modify the DataAnnotationsValidationRunner discussed here to take in an IEnumerable<string> list of property names, as follows:
public static class DataAnnotationsValidationRunner
{
public static IEnumerable<ErrorInfo> GetErrors(object instance, IEnumerable<string> fieldsToValidate)
{
return from prop in TypeDescriptor.GetProperties(instance).Cast<PropertyDescriptor>().Where(p => fieldsToValidate.Contains(p.Name))
from attribute in prop.Attributes.OfType<ValidationAttribute>()
where !attribute.IsValid(prop.GetValue(instance))
select new ErrorInfo(prop.Name, attribute.FormatErrorMessage(string.Empty), instance);
}
}
I'm gonna risk the downvotes and state that there is no benefit to ViewModels (in ASP.NET MVC), especially considering the overhead of creating and maintaining them. If the idea is to decouple from the domain, that is indefensible. A UI decoupled from a domain is not a UI for that domain. The UI must depend on the domain, so you're either going to have your Views/Actions coupled to the domain model, or your ViewModel management logic coupled to the domain model. The architecture argument is thus moot.
If the idea is to prevent users from hacking malicious HTTP POSTs that take advantage of ASP.NET MVC's model binding to mutate fields they shouldn't be allowed to change, then A) the domain should enforce this requirement, and B) the actions should provide whitelists of updateable properties to the model binder.
Unless you're domain is exposing something crazy like a live, in-memory object graph instead of entity copies, ViewModels are wasted effort. So to answer your question, keep domain validation in the domain model.