tags:

views:

358

answers:

6

I'm kind of new to ASP.NET MVC and to the MVC pattern in general but I'm really digging the concept and the rapidity with which I can compose an app. One thing that I'm struggling with is how to expose more than one object to a view. I use a lot of strongly typed views, which works well but what if my view relies on more than one object? Right now I'm doing something pretty hacky and passing a Dictionary to the view and then just keying the different objects. Is there a better pattern for this?

+2  A: 

You can simply store each object in the ViewData then cast the appropriate object type in your View.

Controller:

 ViewData["ObjectA"] = objectA;
 ViewData["ObjectB"] = objectB;

View:

 <%= ((ObjectA)ViewData["ObjectA"]).PropertyA %>
 <%= ((ObjectB)ViewData["ObjectB")).PropertyB %>

or better yet,

 <% 
    var objectA = (ObjectA)ViewData["ObjectA"];
    var objectB = (ObjectB)ViewData["ObjectB"];
 %>

 <%= objectA.PropertyA %>
 <%= objectB.PropertyB %>
tvanfosson
How is this any different than using a dictionary?
Peter Meyer
It's not, but this "dictionary" already exists and you're not creating any new objects/classes just to send the data to the view.
tvanfosson
+5  A: 

You have two primary options and either could work well depending on your application.

1) Just put objects into the ViewData collecion. This works well if you have lots of different controllers that pass different data to different views. It also depends on how much boxing/unboxing you want from object as you cast objects to their correct types. This option is more flexible, but less type-safe and possibly more fragile.

2) Create strongly-typed objects that contain other strongly-typed objects useful to a set of views. This works well if you tend to pass the same data to most of your views and you have fewer controllers.

You could also consider passing an object that exposes an interface that can acquire different model objects (kind of a locator class), but that probably causes more problems than it does fix them.

Geoff Cox
ViewData is already a container. Other than only having to do one cast on the View side, I don't see the advantage. On the other hand, you might start multiplying containers or have to remember which properties in the container are really operative for a particular view. IMHO, 1 is better than 2.
tvanfosson
2 is the way to go unless your application is extremely simple. Why use dictionaries and not create a legitimate "Model" -- you're circumventing the design pattern and specifically the "M" in MVC?
Peter Meyer
A: 

Use the ViewData collection to pass object to the view. You might want to pass a Controller instead of 1 by 1 object of your model.

Daok
Controller or container???
tvanfosson
+3  A: 

make a nested class in your controller.

public class WhateverControllerViewData
{
   public ObjectA ObjectA {get;set;}
   public ObjectB ObjectB {get;set;}
}

Assign to them in your ActionMethods

{
   var wcvd = new WahteverControllerViewData;
   wcvd.ObjectA = whatever;
   ..

   Return View(wcvd);
}

Then use it in your View

<%= ViewData.Model.ObjectA.Whatever %>

Make sure you create a strongly typed view with your nested class as the type.

Kyle West
Why nest the class in the controller? Why not create a legitimate "Model"?
Peter Meyer
A: 

How about using anonymous types in ViewData.Model?

Ian P
This won't work easily since you don't have access in the View to the anonymous type definition -- i.e., the compiler doesn't know about it's properties, so you can't reference them. You'd have to use reflection to get at the properties from the view.
tvanfosson
+1  A: 

I would architect your model to contain your various object types:

public class TheModel {

  public DataClassA DataTypeA { get; set; }

  public DataClassB DataTypeB { get; set; }

}

This eliminates casting and dictionary objects, etc.

Peter Meyer