4

I'm new to MVC.

I have read this short bit detailing three ways of dealing with the view model in MVC:

http://geekswithblogs.net/michelotti/archive/2009/10/25/asp.net-mvc-view-model-patterns.aspx

The gist of it seems to me that:

Method 1, pull an object out the database and use it as your view model. Quick and simple, but if you want data from multiple tables you're totally screwed (I can't think of a way around it without Method 2).

Method 2, create a class that has references to multiple objects, and use this as your view model. This way you can access everything you need. The article says that when views become complicated it breaks down due to impedance mismatch between domain/view model objects... I don't understand what this means. Googling impedance mismatch returned a lot of stuff, the gist of it being that you're representing database stuff using objects and stuff doesn't map across cleanly, but you'd presumably have this problem even with Method 1. Not sure what I am missing. Also seems to me that creating a class for each View to get the data you want isn't ideal from a maintenance point of view, not sure if you have a choice.

Method 3, I am still getting my head around it, but I don't quite understand why their checkbox example wouldn't work in method 2, if you added a bool addAdditional to your class that wasn't connected to the domain model. Method 3 seems to say rather than return the domain stuff directly, just pull out the properties you specifically need, which I think is nicer but is gonna be harder to maintain since you'll need some big constructors that do this.x = domain.x, this.y = domain.y etc.

I don't understand the builder, specifically why the interface is used, but will keep working on it.

Edit: I just realised this isn't really a question, my question is, is my thinking correct?

NibblyPig
  • 51,118
  • 72
  • 200
  • 356
  • Sorry Jeremy, I edited to add the question, more specifically, is method 1 useless for querying multiple tables, what is impedance mismatch re. method 2, and method 3 why can't you see if a checkbox is checked using method 2 just as easily? – NibblyPig Sep 21 '11 at 14:56

2 Answers2

1

The problem I've run into with #2 is that I have to do one of these two things:

  • Include every single field on every single object on the form -- those that aren't going to be displayed need to be included but hidden.

  • Only include the specific fields I need but use AutoMapper or something similar to map these fields back onto the actual objects.

So with #2 I see a mismatch between what I want to do and what I'm required to do. If we move on to #3, this mismatch is removed (from what I understand, briefly glanced at it). It also fixes the problem that a determined hacker could submit values like id fields or similar when using method #2 that unless I was very careful could be written to my data store. In other words, it is possible to update anything on any of the objects unless one is very careful.

With method #3 you can use AutoMapper or similar to do the dirty work of mapping the custom object to the data store objects without worrying about the security issues/impedance exposed by method #2 (see comment for more details on security issues with #2).

Cymen
  • 14,079
  • 4
  • 52
  • 72
  • Is that because MVC automatically generates a form? I'm a bit new to MVC sorry! – NibblyPig Sep 21 '11 at 14:56
  • It is because of how MVC model binding works. If I have an action that is posted to like this: `ActionResult Edit(MyModel myModel)` and say my model has an `int secretId` but I don't expose this (but somehow the attack knows this exists) they can simply put in the http post a `secretId=1234` which will set the value on `myModel.secretId` to 1234 and if I insert that... The default model binding is very lax intentionally however it is a big security hole if one is unaware. If one uses method #3 with a model that only has fields one wants to expose the issue is resolved. – Cymen Sep 21 '11 at 14:59
  • I see, I saw that you can avoid that by using Bind and setting it to ignore the ID. Why do fields on your view model that aren't going to be displayed still need to be included? If I had a Person table in my DB with properties like Name, Age, etc. but wanted a form that only updates Name, would the other fields have to be hidden so that the controller knows how to update the model? If so, how do you update the model with method 3, as you are only going to get the Name property and nothing else, not even the ID. – NibblyPig Sep 21 '11 at 15:03
  • I recommend ASP.NET MVC in Action. Manning just published ASP.NET MVC in Action 3 which is supposed to be going to the presses right now. You can get the ebook + book on their site. It goes into all of this a bit more and is a good overall introduction to ASP.NET MVC. (this is out of order, I missed your reply so this is just a general comment) – Cymen Sep 21 '11 at 15:03
  • 1
    @SLC I am assuming with method #2 you're planning on reading and writing those objects to/from the data store. If so, if any of the fields are missing may get the default values and overwrite what is in the data store (at least they would with our data access methods). For #3, I could write the code by hand or use AutoMapper or similar to map that Name field. – Cymen Sep 21 '11 at 15:06
  • Thanks, that clears up my confusion:) – NibblyPig Sep 21 '11 at 15:08
0

You're probably right about impedance mismatch being present in both Methods 1 and 2 - it shows up anywhere you're going between objects in code and DB objects with relational mapping. Jeff Atwood writes about it, and cites this article, which is a fantastic discussion of everything dealing with Object-Relational mapping, or "The Vietnam of Computer Science". What you'll pretty much end up doing is weighing the pros and cons of all these approaches and choose the one that sounds like it fits your needs the best, then later realizing you chose the wrong one. Or perhaps you're luckier than I am and can get it right the first go 'round. Either way, it's a hairy problem.

Zann Anderson
  • 4,767
  • 9
  • 35
  • 56