2

I like the way model binding in django works: you send stuff that you need in a Json-like way:

'param1': val,
'param2': val

In ASP.NET MVC you can't do it primarily because C# is a static language. You can use ViewData but it's ugly and not recommended.

So I had to create dozens of ViewModels for every view: IndexViewModel, AboutViewModel, etc. And today I got an idea: why not just create one Model class and have Visual Studio generate all necessary fields? It's almost like in django.

return View(new Model
            {
                Param1 = "asd",
                Param2 = "sdf"
            });

Param1 & Param2 are not members of the Model class, but Visual Studio will automatically generate them.

Now my question is, is it gonna work? The thing is that there will be a lot of fields in this Model class. And when we pass it to a view, only a small percentage of fields made for that view in particular will be used. Is it gonna be bad performance wise?

Thanks

Alex
  • 34,581
  • 26
  • 91
  • 135

4 Answers4

4

If you have all these properties on your ViewModel which aren't used (i.e null or whatever) it isn't really going to impact performance. What it will impact however, is your design.

Generally speaking, one model to rule them all as you are proposing is a bit evil and goes against separation of concerns. ViewModel's should be very simple and should be tailored to the view. ViewModel's shouldn't really provide the view with more or less data than what the view needs in order to render.

Consider this....

You have a generic model with 15 properties on it and you only set a handful of them. Somebody else designs a new view and looks at the model, they may not know which of those properties are sent and under what conditions they are set. Consequently they may be attempting to display data that does not exist. This isn't a very clean approach.

I would stick to individual view models and where there is common functionality between views, create an abstraction or base ViewModel from which other view models can extend.

Edit: One other thing you could do is use the new MVC 3 (still in preview) syntax (dynamic) for setting ViewData properties directly as if they were properties.

So rather than doing

ViewData["FirstName"] = "Bob";

You can do

ViewModel.FirstName = "Bob";

This gives you dynamic variables automatically in MVC 3.

Joshua Hayes
  • 1,938
  • 2
  • 21
  • 39
  • Good point. What I want to do, is to imitate django's behavior. The Model.cs class shouldn't even be looked at, because it's completely auto-generated. But I'll think about what you wrote. – Alex Sep 21 '10 at 07:42
  • I totally agree with the viewmodel being as simple as possible – samy Sep 21 '10 at 07:44
  • 3
    Completely auto generated is recipe for disaster. Whilst more convenient initially (because you don't have to code up front) it will be very brittle, harder to debug when issues occur and harder to test. The problem with dynamic is that you don't get compiler time checking and the type of a dynamic variable can change and you might not notice. – Joshua Hayes Sep 21 '10 at 07:45
  • 1
    Alex, even if you don't look at the model, it's an abstraction that may leak. If each person adds to it without supervision, you may (that's a big may, but it exists) run into performance problems, or worse discrespancies between expected and observed behaviors. Just imagine somebody adding a property to automatically fill two fields (splitting a string to name and nickname, for example). This change could bleed into other parts you're not aware of. – samy Sep 21 '10 at 07:46
  • Yeah, I don't want to use dynamics because of loosing type checking. – Alex Sep 21 '10 at 07:47
  • 2
    If you provide a little more information about your actual domain I may be able to suggest some ideas for structuring your models. In general though, think if maybe there are commonalities amongst your models that you would like to create base models from and have your other models extend these. If this isn't the case, then your data IS different and SHOULD belong in different views. Its best practice to only give a View the data it needs. No more and no less. – Joshua Hayes Sep 21 '10 at 07:47
2

Have a look a Clay the 'malleable' object model being used by the Orchard Project.

http://weblogs.asp.net/bleroy/archive/2010/08/16/clay-malleable-c-dynamic-objects-part-1-why-we-need-it.aspx

http://weblogs.asp.net/bleroy/archive/2010/08/18/clay-malleable-c-dynamic-objects-part-2.aspx

Clicktricity
  • 4,171
  • 1
  • 23
  • 15
1

There's no reason it shouldn't work.

You can even skip the Model class and create an anonymous type with just the members you need.

return View(new { Amount = 108, Message = "Hello" });

The problem using anonymous types is that you're giving up on auto-completion in the view since you won't be able to type the view according to the model.

samy
  • 14,832
  • 2
  • 54
  • 82
  • When using anonymous types, we have to cast objects using the 'as' keyword. Also I'm not giving up on auto completion, why would it not work? – Alex Sep 21 '10 at 07:40
  • 1
    indeed, if you have one Model class with all possible members, it would work. I was thinking about using the anonymous type :p – samy Sep 21 '10 at 07:42
  • I don't understand the necessity for the cast, though – samy Sep 21 '10 at 07:42
  • @samy, here's why: http://stackoverflow.com/questions/223713/can-i-pass-an-anonymous-type-to-my-asp-net-mvc-view/224005#224005 – Alex Sep 21 '10 at 07:45
  • In fact, there is no need to cast :) If you create a view with the anonymous object above, you can type <%= Model.Amount %> and it will output 108. You won't have auto-completion. But you'll have a lean ViewModel – samy Sep 21 '10 at 07:54
  • Yes but basic operations like Model.Amount + 2 and foreach loop will need it :) – Alex Sep 21 '10 at 07:55
0

Just use dynamic

gandjustas
  • 1,925
  • 14
  • 12