views:

281

answers:

7

i see that asp.net mvc 2 has strongly typed helped and looking initially at the way it works i think maybe i am doing something wrong in asp.net mvc 1 in terms of data binding to render the view and post back to the controller.

I often have different objects for rendering the view and posting back to the controller. is this wrong ?? It seems natural as when rendering the view you often have a viewmodel that has lists for dropdowns, etc. but for your posting you only want the properties that are needed to post back.

for example, on the way in for rendering, my viewmodel might look like this

 public class PersonViewModel
 {
      public int Age;
      public string FIrst;
      public JobCategory[] JobCategories;
      public Sport[] Sports;
      public int NumberOfChildren;

 }

in this case, jobCategories and Sports is going to be used to populate a dropdown box. NumberOfchildren is going to just be html put in and i dont want it editable. When i want to post i only want to pass back a slim object with just the posted properties so i have another object

  public class PersonUpdater
 {
      public int Age;
      public string FIrst;
      public int JobCategoryId;
 }

these are the only properties that i need to pass back so my controller will look like this:

 public ActionResult Update(PersonUpdater personUpdater)
 {
      _repository.UpdateModel(personUpdater). 
 }

so, given the above, assuming the strongly typed helper methods (below) seem useful for the way in but then may cause issues on posting back to the server if you are referrring to different properties.

http://weblogs.asp.net/scottgu/archive/2010/01/10/asp-net-mvc-2-strongly-typed-html-helpers.aspx

any thoughts?

A: 

You can specify which property you are refering to in a strongly typed helper, look for overload with 3 parameters.

Nothing wrong with your method. Strongly typed views are there to help you develop better, so no typpo can get in your way.

Alexander Taran
but what is the property that you are using to render is different than the property to pass back on the post
ooo
again, very harsh downvote IMO
AUSteve
i am happy to remove and change the upvote but there wasn't any answer to the question.. them seems down vote worthy
ooo
I'm agreeing that we disagree
AUSteve
name by which this property posts back can be different from models property name
Alexander Taran
A: 

Most of the time the auto-binding stuff doesn't fit what I need so I just resort to posting to a formCollection parameter and go manual. If you can use any part of the model binding magic then all the better for you.

Binding less doesn't mean less data is posted back to the server. All of the input elements in the form will be transmitted, you just wont see them as discrete, strongly typed, "automagic" parameters. If you really want to slim down the post data you have to restrict what input elements are inside the particular form you post. MVC is still HTTP after all...

AUSteve
The downvote seems harsh, the formCollection is actually going back to the pure HTTP request and this method works fine. What do you mean by "all types of bad"?
AUSteve
its not strongly typed . . again what scenario does model binding not support ?
ooo
model binding is fine for small and simple models in simple scenarios, anything more than that and the "automagic" can't cope, nor was it designed to cope with it. Binding just papers over the request's form collection, ie it's casting those string values in into the other types anyway.I'm simply choosing not to use the extra features.
AUSteve
i have used default model binding with nested complicated objects with lists, etc . . it is a bit tricky to get right but it does work.
ooo
@AUSteve Hah - stick to formCollection. Yeah right. At least - move binding form values to custom model binders outside from controllers. Otherwise - you are just doing it wrong. :D
Arnis L.
The 'formCollection' approach is not what the asker is wanting here. I like the default modelbinder and that it binds pretty well for lots of my types. But i have been investigating my own custom model binders lately and the potential is massive. If you want to adhere to KISS and DRY principals then typed params are the way to go. If you need to bind something that dosent't work with the default binder then write your own - once.
cottsak
IMHO declaring a controller action to take "FormCollection" is an anti-pattern in most cases (don't know if AUSteve's situation is a valid exception or not). When the default model binder doesn't work, I prefer to write a custom model binder that encapsulates the "bind an object to form data" logic. That way my controllers focus on the "orchestration" of responding to a web request, not the minutiae of dealing with low-level form data.
Seth Petry-Johnson
+5  A: 

Real problem is - current accepted approach ignores SRP for view models a bit - edit form acts as input and output simultaneously.

People haven't accepted yet dividing view model into, as i call them, input view model and output view model (for many - even creating view model layer is too much). Therefore - Mvc2 currently lacks support for this (you aren't supposed to have strongly typed view that's not input and output at the same time) mainly because of vagueness and lack of broadly accepted approaches.

But i do think that there's a gain (ok... it's actually a trade off) in going deeper and separating view model into 2 of them. And i won't be surprised if this idea will evolve and eventually become widely accepted.

Actually - current approach even has a name - Thunderdome principle. And if guys like Jeremy D. Miller says this is correct, community won't bother and won't search for anything else.


From practical point of view - some of the issues you can mitigate through providing correct metadata (you might want to check out fluent model metadata provider).

Arnis L.
A: 

I would suggest to keep it simple by just using one object for GET and POST. Code maintainability is far more important/valuable here than saving a few bytes for an update action.

Arnis makes good arguments regarding SRP and other design patterns but petterns are supposed to be adapted. If i were you i'd use the help the mvc framework has created for you: use the typed helpers; use typed model/viewmodel objects for GET/POST and if you need more complex binding create a custom binder.

Keep your code light and ur app will stay awesome.

cottsak
You say that code maintainability is important. Depending on your school of thought, creating separate view models for the GET and POST flavors of a view IS the more maintainable approach. It results in more class files, and maybe a little extra code as you duplicate properties in each, but you end up with objects that are perfectly tuned to do one thing well. IMHO that's cleaner, and therefore more maintainable, than creating a single view model for both GET and POST. (Unless of course the two models are exactly equal, in which case pragmatism dictates we have only one class)
Seth Petry-Johnson
i guess i hav to agree with that Seth
cottsak
A: 

I use a model for input (displayed by the form) and a separate model for output (posted by the form). Validation is placed on the output model. The specific reason why I do this is for drop down lists. You want a list of possible values to present to the user and these are in the input model. In the output or post from the form I don't want the list of possible value, I want to know what values the user selected, if any.

37Stars
If validation fails, and you have to redisplay the edit form, how do you re-create the input model while preserving the changes captured in the output model? Do you do this by hand in the controller?
Seth Petry-Johnson
The output model (which I name Post) has two methods. One method returns the data object, which is used when the data validation passes. The second method returns a object of the input model (which I name Form). The second method is used when when validation fails.I'm in the middle of writing a couple of T4 templates that generate these input and output models for me. They require some manual tweeking but I don't have to write the whole class from scratch.
37Stars
A: 

I use separate view models for input [GET] and output [POST] as well, unless the two models are identical. IMHO this approach is cleaner, easier to maintain, and more clearly expresses which data will be updated by a given controller action.

There's a cost in terms of LOC, but the extra code is usually not logic. In most cases, I don't feel that duplicating some automatic properties on two objects violates the DRY principle, and I think the cost is justified to follow SRP.

The other cost, as you've noted, is that the built-in strongly typed helpers don't work so well. Have you thought about writing your own helpers that support your pattern? For instance, you might overload one of the existing helpers so that you can specify both the source (e.g. the property of the input model) and the destination (e.g. the name of the form field that is posted to the output model).

Seth Petry-Johnson
A: 

Just looking at your specific situation, the following points occur to me.

1) The two models are very similar indeed 2) If you add "MiddleName", you have to add it in two places 3) When you say "I only want to pass back a slim object" - the actual POST will contain the same amount of data, whether you bind to the original model or a new one (it will contain a key, value pair for each user-input within the form) 4) You preclude the option of displaying the data on your "saved ok" or "something isn't valid" page as it isn't part of the model

For these reasons, I would recommend using the same model for the GET and POST of the action.

Sohnee
i dont think i agree with you here. the downside of having to replicate properties doesn't seem to justify forcing what is two different data models into one (even if there is some overlap). I think it seems much clearer to identify what is being bound on the input and what is being bound on the output post.
ooo