我正在使用Forms身份验证创建一个ASP.NET MVC4网站,并且在查看视图中包含多个模型的正确方法遇到了困难。
具体来说,有一个属于给定视图的模型,比如“CartModel”。但是,考虑到站点的当前UI,在部分视图中使用的模型包含在主布局视图中,其中包含有关当前登录用户的信息。
我目前解决此问题的方法是将LoginModel作为每个视图模型的一部分。但是,这似乎是重复的,并且无法正常工作。
解决此问题的最正确方法是什么?
答案 0 :(得分:4)
有两种方法可以访问它。
OnActionExecuting
方法),将ViewBag
/ ViewData
所需的模型添加到其中。WebViewPage
公开模型,但您仍然需要填充它。因此,它可能需要访问您的API,并且正确完成,可能需要一些依赖注入。public abstract MyBaseController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (User != null && User.Identity.IsAuthenticated) // check if user is logged in if you need to
{
ViewBag.LoginModel = /* add data here */;
}
}
}
然后将它用作基类(或继承的某个地方):
public MyController : MyBaseController
{
//etc.
}
PopulateLoginModelAttribute : ActionFilterAttribute, IActionFilter
{
void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.User != null && filterContext.HttpContext.User.Identity.IsAuthenticated)
{
filterContext.Controller.ViewBag.LoginModel = /* add data here */;
}
this.OnActionExecuting(filterContext);
}
}
然后装饰控制器类,操作方法或添加为全局过滤器。
[PopulateLoginModel] // will be applied to all actions in this controller
public class MyController : Controller // note you can use the normal base type, or whatever you need
{
public ActionResult MyView()
{
return View(new CartModel());
}
}
ViewBag
中放置的模型,但继续使用Model
作为操作的视图。通常在视图中访问ViewBag
(也可以访问布局,我在LoginModel类型上编写了一个属性值来说明):
<span>@ViewBag.LoginModel.Name</span> <!-- available because of the filter !-->
Number of items in your cart: @Model.Items.Count <!-- the model provided by the action method !-->
ViewBag.LoginModel
将可用于从此控制器派生的所有操作,无需额外工作。我建议将它作为一个属性,因为它可以让您更灵活地使用基类以及要将其应用到哪些控制器/操作。
您不太可能想要使用自己的WebPageView基类。如果您想添加成员以帮助处理数据或视图的任何内容,那么它非常适合。但它不是添加或操纵viewdata或模型的正确位置,尽管它是可能的。
public abstract class MyWebViewPage<T> : WebViewPage<T>
{
protected LoginModel GetLoginModel()
{
// you could resolve some dependency here if you need to
return /* add data here */
}
}
确保views文件夹中的web.config已正确更新。
<span>@GetLoginModel().Name</span>
答案 1 :(得分:2)
您可以通过多种方法在视图中包含多个模型:
使用ViewBag
动作:
public ActionResult Index()
{
ViewBag.CartData = _repository.GetCartData();
ViewBag.LoginData = _repository.GetLoginData();
return View();
}
查看:
@foreach (var item in ViewBag.CartData)
{
// Do something here with item in CartData model
}
@foreach (var item in ViewBag.LoginData)
{
// Do something here with item in LoginData model
}
使用ViewData
动作:
public ActionResult Index()
{
ViewData["CartData"] = _repository.GetCartData();
ViewData["LoginData"] = _repository.GetLoginData();
return View();
}
查看:
@foreach (var item in ViewData["CartData"] as List<Cart>)
{
// Do something here with item in CartData model
}
@foreach (var item in ViewData["LoginData"] as List<Login>)
{
// Do something here with item in LoginData model
}
答案 2 :(得分:0)
假设从User.Identity
读取“用户信息”,您实际上不需要创建模型实例以在当前视图中使用。
假设您正在尝试这样做:
@model MyMasterViewModel
<div>
@* Displaying some property of the primary model *@
@Model.SomeProperyOrAnother
@* Displaying some property of the model that is a member of the primary model *@
@Model.InnerModel.SomeOtherProperty
</div>
如果辅助模型与主模型无关,则可以调用@Html.Action()
方法,如下所示:
@model MyMasterViewModel
<div>
@* Displaying some property of the primary model *@
@Model.SomeProperyOrAnother
@Html.Action("LoginInfo")
</div>
调用的结果被注入当前视图。我为我的帐户菜单做了类似的事情,因为我只是从Identity
对象中读取Request
信息并使用它来获取我需要的任何其他信息。如果你想确保永远不会直接调用“助手”动作,你可以用[ChildActionOnly]