Multiple models sent to a single view instance

2019-02-02 20:26发布

My terminology is probably way off here but basically I'm trying to pass multiple data models to a view. To help put the question in context, take this example:

Say I was making a blog. When I log in I want the home screen to display a list of all new unapproved comments, as well as a list of recently registered users, and a list of the most recently submitted blog posts.

Most discussions I've seen suggest strongly-typing the view page so it can be called with something like "return View(RecentComments)" and iterate through the comments in the view, or to cast the data model like "var NewUsers = (MembershipUserCollection) ViewData.Model". What I'm ideally after is the 'right', or at least a 'right-enough', way of passing multiple models while still maintaining appropriate logic separation.

8条回答
仙女界的扛把子
2楼-- · 2019-02-02 20:36

One thing no one seems to have mentioned is that in the original questioners example, it might make sense to create the view out of a series of child actions that handle their own area of functionality rather than making a mega view model. That way the components such as unnapproved messages etc can be reused.

This also gives better encapsulation.

查看更多
仙女界的扛把子
3楼-- · 2019-02-02 20:37

Creating an object that can encapsulate your other objects is the best way to go. Otherwise you're stuck with a bunch of ugly ViewData tags in the controller and the view.

查看更多
萌系小妹纸
4楼-- · 2019-02-02 20:41

The way to pass multiple models to a view is to create what we call a Form View Model which has your other models within it.

Then in your view you can pass the individual models contained in your Form View Model to the Partial Views responsible for rendering the data in said models.

Makes sense?

edit

btw: a form view model is simply a class. it's not a special type as may have been suggested by my answer.

查看更多
Animai°情兽
5楼-- · 2019-02-02 20:45

What I've done in the past is written a class that contained instances of both the classes I will need on the view.

ie

public class City{
public Mall TheMall;
public School TheSchool;
}

Then your view will be strongly typed as City, and you will use Model.TheMall.Property and Model.TheSchool.Property to access what you need

EDIT

This is an example of what other posters mean by creating an object with both objects as fields/properties

查看更多
Lonely孤独者°
6楼-- · 2019-02-02 20:48

After working on a large ASP.NET MVC app, I found the approach that was most productive while minimizing runtime casting was based on using generics to mimic the nested structure of views. Essentially views get their own data type. Typically these are either domain objects, or collections of domain objects that include metadata. Generic versions of these types are available across all possible master pages, taking a type parameter that defines data relevant to the master page.

public class Car {
  // can be used as a model
} 

public class CarCollection: Collection<Car> {
  public BodyTypes BodyType {get;set;}
  public Colors Color {get;set;}
  // can also be used as a model
}

public interface ILayoutModel<TLayout> {
  TLayout LayoutModel {get;set;}
}

public class CarView<TLayout>: Car, ILayoutModel<TLayout>  {
  // model that can be used with strongly-typed master page
}

public class CarCollection<TLayout> : CarCollection, ILayoutModel<TLayout> {
  // model that can be used with strongly-typed master page
}

public class LayoutAData {
  // model for LayoutA.master
}

public class LayoutBData {
  // model for LayoutB.master
}

It's also possible to invert the generic-ness, but since the view dictates the layout, the view data should dominate over the layout data in my opinion. LayoutA.master would derive from ViewMasterPage<ILayoutModel<LayoutAData>> and LayoutB.master would derive from ViewMasterPage<ILayoutModel<LayoutBData>>. This keeps the view data and the layout data separate, in a consistent, strongly-typed and flexible way.

查看更多
相关推荐>>
7楼-- · 2019-02-02 20:59

One way is to create a new type that encapsulates both pieces of model data:

public class MyBigViewData {
    public SubData1 SubData1 { get; set; }
    public SubData2 SubData2 { get; set; }
}

public class SubData1 {
    ... more properties here ...
}

public class SubData2 {
    ... more properties here ...
}

Another way is to store the "main" model data as the strongly-typed data and store other data in the view data as dictionary items:

ViewData["username"] = "joe"; // "other" data
ViewData["something"] = "whatever"; // "other" data
ViewData["subdata1"] = new SubData1(...);
return View(myRealModelData);

The advantage of the second approach is that you don't need to do anything special at all: It works right out of the box.

查看更多
登录 后发表回答