问题描述
我正在创建一个具有Forms身份验证的ASP.NET MVC4网站,并且在以正确的方式在视图中包含多个模型的过程中遇到了困难.
I'm creating an ASP.NET MVC4 web site with Forms authentication and am encountering difficulties in the correct way to include multiple models within a view.
具体来说,有一个属于给定视图的模型,例如"CartModel".但是,鉴于站点的当前UI,在局部视图中使用了一个模型,该模型包含在主布局视图中,其中包含有关当前登录用户的信息.
Specifically, there is a model that belongs to a given view, say "CartModel". However, given the current UI of the site, there is a model used within a partial view that is included in the master layout view with information about the currently logged in user.
我当前解决此问题的方法是将LoginModel包含在每个视图模型中.但是,这似乎是重复的,无法正常工作.
My current approach for solving this issue is to include the LoginModel as a part of every view model. However, this seems repetitive and doesn't work correctly.
解决此类问题的最正确方法是什么?
What is the most correct way to resolve an issue such as this?
推荐答案
有两种方法使其可访问.
There are two ways to make it accessible.
- 使用过滤器(或在所有控制器都派生自其的基本控制器中覆盖
OnActionExecuting
方法),该过滤器会将您需要的模型添加到ViewBag
/ViewData
. - 使用您自己的基本
WebViewPage
来公开模型,但是您仍然需要填充模型.因此,它可能需要访问您的API并正确完成,可能需要注入一些依赖项.
- Use a filter (or override the
OnActionExecuting
method in a base controller your controllers all derive from) that add a models you need toViewBag
/ViewData
. - Use your own base
WebViewPage
to expose the models, but you'll still need to populate it. Thus, it may need to access your APIs, and done correctly, would probably require some dependency injection.
方法1:OnActionExecuting
从基本控制器覆盖
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 */;
}
}
}
然后将其用作基类(或继承的更高层次):
Then use it as the base class (or somewhere further up the inheritance):
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);
}
}
然后装饰控制器类,操作方法或添加为全局过滤器.
Then decorate a controller class, action method, or add as a global filter.
[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类型上组成了一个属性值以进行说明):
Then use the model you placed in the ViewBag
in referenced partials, layouts, etc., but keep using Model
for the action's view.
Access the ViewBag
normally in your view (also accessible to layouts, and I made up a property value on LoginModel type to illustrate):
<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
将可用于从该控制器派生的所有操作,而无需进行额外的工作.我建议将其设置为一个属性,因为它将为您提供更大的灵活性,使您可以更方便地使用基类以及要将其应用于哪些控制器/动作.
ViewBag.LoginModel
will be available for all actions that derive from this controller without extra work. I'd recommend making it an attribute as it will give you more flexibility with base classes and to which controllers/actions you want to apply it to.
您不太可能希望使用自己的WebPageView基类.如果您想添加成员以帮助处理数据或视图中的任何内容,那将非常有用.但这不是添加或以其他方式操纵视图数据或模型的正确位置,尽管这是可能的.
It is less likely you'll want to use your own WebPageView base class. If you want to add members to assist in working through data or whatever for a view, it's great for that. But it's not the right place to add to or otherwise manipulate viewdata or the model, although it's possible.
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.
Then use the members in your views, partials, and layouts
Make sure your web.config in the views folder is updated correctly.
<span>@GetLoginModel().Name</span>
这篇关于在每个视图中包括用户模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!