我正在尝试访问视图中的多个模型。
我创建了一个ViewModel
类及其控制器,并导入了模型进行查看,但出现了以下错误:
传递到字典中的模型项是类型 'System.Collections.Generic.List`1 [LivrinhosMVC.Models.Category]',但这是 字典需要类型为'LivrinhosMVC.Models.ViewModel'的模型项。**
ViewModel类:
public class ViewModel
{
public List<Category> Categories { get; set; }
public List<Ad> Ads { get; set; }
}
ViewModel控制器:
// GET: ViewModel
public ActionResult Index()
{
ViewModel mymodel = new ViewModel();
mymodel.Categories = db.Categories.ToList();
mymodel.Ads = db.Ads.ToList();
return View(mymodel);
}
查看:
@model LivrinhosMVC.Models.ViewModel
<div class="container">
<div class="row" style="margin:2em 0">
<div class="col-sm-4">
@Html.Label("Categorias")
<table class="table-condensed">
@foreach (var item in Model.Categories)
{
<tr>
<td>@Html.ActionLink(item.Name, "../Category/Books", new { id = item.ID }, null)</td>
</tr>
}
</table>
</div>
<div class="col-sm-8" style="display:inline">
@Html.TextBox("BookTitle", null, new { placeholder = "Título...", @class = "form-control" })
@Html.DropDownList("Cities", "Portugal")
@Html.ActionLink("Pesquisar", "Books", null, null, new { @class = "btn btn-primary" })
</div>
<div class="row">
@foreach (var item in Model.Ads)
{
<div class="col-sm-3">
@Html.Label(item.Title)
</div>
}
</div>
</div>
</div>
答案 0 :(得分:0)
例如:
public ActionResult Index()
{
var model = db.ViewModel
.Include(c => c.Categories);
.Include(c => c.Ads);
return View(model.ToList());
}
并使视图以Strogly类型输入:
@model IEnumerable<LivrinhosMVC.Models.ViewModel>
答案 1 :(得分:0)
根据您的示例代码,我不确定为什么会收到该错误,@foreach (var item in Model.Categories)
似乎有问题。
我可以看到并推荐的是遵循视图模型方法,但不要将实体附加到视图模型中。视图模型应该是简单的POCO类,仅提供足够的细节供视图使用,仅此而已。这样做的原因是为了帮助提高性能(减少读取和传输的数据)并提高安全性。 (没有数据发送到您不希望他们看到的客户端,例如在调试工具中公开的数据,并确保实体不会再次通过调试工具被信任,附加到并提交给上下文。)
我建议创建仅包含ID和Name的CategorySummaryViewModel和AdSummaryViewModel。将所有视图模型标记为可序列化。然后,当您填充ViewModel时:
[Serializable]
public class AdsPageViewModel
{
public List<CategorySummaryViewModel> Categories { get; set; } = new List<CategorySummaryViewModel>();
public List<AdSummaryViewModel> Ads { get; set; } = new List<AdSummaryViewModel>();
}
public ActionResult Index()
{
var mymodel = new AdsPageViewModel
{
Categories = db.Categories.Select(x=> new CategorySummaryViewModel
{
Id = x.Id,
Name = x.Name // Append other fields if necessary for the view.
}).ToList(),
Ads = db.Ads.Select(x => new AdSummaryViewModel
{
Id = x.Id,
Name = x.Name
}).ToList()
};
return View(mymodel);
}
与简单地传递实体相比,这似乎需要更多的代码/精力。您可以利用Automapper之类的工具简化此过程,并利用.ProjectTo<T>
获得与上述相同的好处。这些好处包括使用.Select()
发送到数据库的EF SQL语句,并且从数据库返回的数据仅包含视图模型所需的字段。网络上更少的数据=更快,并且应用服务器和客户端上的请求所需的内存更少。这也确保我们的视图只能看到我们希望其看到的字段。在我们的客户端中使用F12的用户无法检查其他FK和隐藏的字段,这仅仅是因为我们在页面上没有可见的控件。我们还确保我们的应用程序不接受从客户端返回的实体,在这种情况下,诱使实体将它们附加到上下文并保存它们。 (看似简单,但容易受到黑客使用相同的调试工具更改实体数据并破坏保存的数据的影响。)
考虑使用可序列化的POCO视图模型来构成视图数据,并查看在呈现子集合方面是否仍然有任何异常。我怀疑如果仍然存在问题,您的示例中可能没有包含您代码中的详细信息。