ASP.NET MVC - Model-binding for different views at runtime - asp.net-mvc

My latest project involves actions returning different views at runtime (simply put, the application has a number of different customers as users, and they want their own custom data entry form designs - these forms all share the same model object-graph, but their display of the model's data is radically different to each other)...
For example, a "Case" entity has multiple People associated with it. Some forms only display a single Person's fields, other forms support multiple Persons, and another doesn't contain Person information at all. Furthermore, the forms have differing levels of fields - many forms lack many fields that others have.
Because of this radically different behaviour, I believe I'll need a different model binder for each view design.
Can StackOverflow recommend a course of action to take in this case, or an alternative solution that keeps the code simple.

If all your view models derive from a common abstract base view model you could have your POST action take this common view model as parameter and then write a custom model binder which will instantiate and bind the correct instance assuming each view sends an additional parameter containing the concrete type.
Here's an example of how this could be done.

Related

Is creating ViewModel for Model validation odd and unnecessary?

Is there any good reasons to create ViewModel that copy`s Model with addition of validation logic?
Why not simply extend current model with validation logic?
If you will create ViewModel copy, you need to
Create class with corresponding fields (which is not big problem if you have few models to validate, but what if you have many..)
Set automapper, wich can be slow, and adds additional logic to your solution (or do it by hand, which is probably, bad idea)
Support Model changes for ViewModel
These problems dissapear if you simply extend your basic Model. So why it is so popular to create ViewModel layer?
You can have two views with different validation logic for the same model.
the classic example is a sign up form, with a single page form vs a multi page wizard.
In both cases the model is the same, but in the wizard view its legitimate to submit the model half filled in, while the single page version should have all the fields validated.
Taking this possibility further leads to the one viewmodel per view methodology. Where you always make a viewmodel for a view as a matter of course because you expect to need the flexibility that it offers as a general thing.
Additionally, its pretty rare that view exactly matches a model. You usually require more than one model plus some odd extra bits. eg user model for the 'logged in as' header, list of models to display plus pagination info.
You can avoid some of the issues you mention by using ViewModels which simply wrap models and expose their properties where extra logic isn't required

Scope of viewmodels in asp.net MVC 3

I have read online that it is bad practice to use a "kitchen sink" model:
Rule #3 – The View dictates the design of the ViewModel. Only what is
required to render a View is passed in with the ViewModel.
If a Customer object has fifty properties, but one component only
shows their name, then we create a custom ViewModel type with only
those two properties.
Jimmy Bogard's subsequent explanation of how this is good, however, left me a little questioning. It'd be so easy to have my Model just contain a list of Customers, I could even use my POCO's.
So now I get to create custom little view model fragments for every page on the site? Every page that uses a Customer property would get one, but of course could not be shared since some of the information is extraneous, if one page used Age but not Name, for example. Two new mini view model classes right?
This is very time consuming, and seems like it'll lead to a million little custom view models - can someone elaborate as to the utility of this approach and why the easier approach is bad?
View model class can be used not only to transfer values, but it also defines data types (data annotations), validation rules and relations different then ones used in model. Some advantages that come to my mind right now:
There are different validation rules when you change user's password,
change his basic data or his subscription setting. It can be
complicated to define all these rules in one model class. It looks
much better and cleaner when different view models are used.
Using view model can also give you performance advantages. If you
want to display user list, you can define view model with id and name
only and use index to retrieve it from database. If you retrieved
whole objects and pass it to view, you transfer more data from
database than you need to.
You can define display, and editor templates for view models and reuse them on different pages using html helpers. It looks much worse, when you define templates for model POCOs.
If you would use your POCO objects as view models, you would essentially be showing your private objects and break the encapsulation. This in turn would make your model hard to change without altering the corresponding views.
Your data objects may contain details that are appropriate only to the data access layer. If you expose those things to the view, someone might alter those values that you did not expect to be altered and cause bugs.
Many of the same reasons as for having private members in OO languages apply to this reasoning. That being said, it's still very often broken because it's a lot of extra work to create all these "throw-away" models that only gets used once. There exists frameworks for creating these sorts of models, though the name eludes me, that can tie objects together and pick out the interesting properties only which takes away some of the drudgery from creating specific view models.
Your View Model tells the View how data should be shown. It expresses the model. I don't think its necessary to have two view models unless you have two ways to express your model. Just because you have two pages, doesn't mean you will be showing the data any different way, so I wouldn't waste time making two mini View Models when it can be in one reusable view model, Imagine if later you have a page that needs Name and Age, you would create another view model? It's absolutely silly. However, if you had two pages both showing 'Age' and it needed to be shown in a different way, then I would create another one.

Different model validation scenarios

I have a user entity in my application where users input some basic information when they register to the application. If they want to use some advanced features they have to give full information.
So I have two validation scenarios.
My first approach was to exchange the Required attribute with MyRequired attribute to avoid columns being created as NOT NULL in the database via Entity Framework.
But the model is validated if I add it to my DB context. So I can't add the entity if it's just filled with basic information.
Is there a way to have one entity with several different validation scenarios?
Is there any way to validate a model with different scenarious?
That's what view models are supposed to do. I would recommend you to avoid passing your EF models to the views. Also avoid passing EF domain models to your actions => always use view models. Those classes are specifically designed to meet the requirements of a given view, including validation attributes. Then map your model entities to your view models.
This way your domain models are completely decoupled from the way the information is being presented on a given view. Also (as it is your case) the same domain model could have two different representations on different views as well as different validation requirements of course => view models fill this gap.

Should I render optional sections of a form via partials?

As an exercise in learning .NET, I'm moving some simple forms over into MVC, and have run into an issue. The form in question is a multi-part form that has option sections. For example, Section 0 is static and contains information like username, real name, email address. After that is a radio button with several options. If you click the first radio, it displays Section 1. If you choose the second, it displays Section 2, and so on.
In WebForms this was no biggy, as I just validated on postback and said if Radio1.Selected validate this, if Radio2.Selected validate that, etc. So now I've got a strongly-typed view with [Required] members, which obviously isn't going to work - I can't require members that aren't always going to be required.
With that said, is this the correct approach to the problem:
Create the members that belong in Section 0 in my strongly-typed view model class.
Create references to each partial's strongly-typed class in my view model class.
Create the partial views and then render them in the main view.
Depending on which radio button is selected, render the appropriate partial view.
Validate the model like usual...which hopefully will cascade to the partial models.
Does this make sense, or is the approach wrong?
That's a typical scenario where you need conditional validation, i.e. if some value is set then validate that some other value is required. Achieving this with static data annotations which are simple attributes baked at compile time can quickly turn into a nightmare due to their declarative nature. Well, you could always roll your own custom validation attributes but the problem with attributes is that you will have to specify property names as strings as they need to be known at compile time.
That's one of the reasons why I use FluentValidation.NET. Not only that validation rules are separate from the view models and that it integrates really nicely with ASP.NET MVC but handling scenarios like this would be very easy. You could have a sub-view model containing all the properties of the sub-section and then conditionally include it based on the value of a given property on the main view model inside its validator.

best practice for what is in a ViewModel

I am wondering if it is a good idea or bad, placing things like a List of countries in ViewModel, for binding to a drop down list? For example on a site's Registration page.
I was under the impression that a ViewModel is supposed to represent an instance of the filled out form, but I think I may be wrong as I have seen other people put things like lists in their ViewModel.
Would it not be better to put it in a static class somewhere and called directly from the View?
Like CommonData.ListCountries(); and then using Lambda to convert to SelectList item list in the view Directly?
As you've realized there are a variety of ways to accomplish your goal. While the MVC design pattern encourages certain application organizations how you organize your models, views and controllers is ultimately a matter of preference.
Scott Allen discusses his preference for dealing with ASP.NET MVC drop down lists in a blog post. Scott uses an extension method to convert an enumerable of a complex type into an IEnumerable<SelectListItem> on his model. He then describes that upon post back ASP.NET MVC will not be returning the IEnumerable<SelectListItem> he sent to the view, but only the value the user selected. He then suggests that utilizing two models can simplify things.
This is a reasonable description of what I refer to as ViewModels and FormModels. A ViewModel carries the display data to the view and a FormModel is used for carrying collected data back to a controller action. To explain further:
ViewModels contain data that help render views. By organizing my ViewModels this way I can place all necessary information to render a particular view into an associated model. This prevents me from having to use ViewData for anything that's not truly temporary.
FormModels are used to gather user input. FormModels (almost) never contain references to other complex types and are made up of primitives, DateTimes, and strings.
In either case I have a hard rule to never reuse a model for a different view. Having your models closely aligned with the views used to render them makes your views easier to write. You don't have to worry about things like static methods because your models should be carrying data to their associated views in a form that is easy for them to render. Tools like AutoMapper can help "flatten" domain objects into models for display purposes.
For additional reading checkout: ASP.NET MVC terminology is tripping me up - why 'ViewModel'?
Whatever data your View needs, put it in the ViewModel.
The way i see it, once your view is going through the rendering process, it should have all the info it needs from the Model it is bound to.
If you start to use helper methods, then the View is "going back to the controller" in a sense. Extension/helper methods are fine for formatting, etc, but they should not call through the model.
Don't forget, you also have ViewData (basically HttpContext.Current.Items, lives for single request), which is a lightweight storage mechanism that can be used to share data across partial views (for example).

Resources