在所有视图上访问Viewbag属性

And*_*osa 10 asp.net asp.net-mvc razor asp.net-mvc-4

如何在所有视图中访问某些ViewBag属性?我希望在任何地方都可以访问当前用户名等信息,但无需在项目的每个ActionResult方法中专门定义属性

Dar*_*eal 19

你可以通过多种方式实现自己想要的目标,每种方式都有其优点和缺点.

1.使用基类

public class BaseController : Controller
{
    protected override ViewResult View(IView view, object model)
    {
        this.ViewBag.MyProperty = "value";
        return base.View(view, model);
    }
}
Run Code Online (Sandbox Code Playgroud)

PROS:实现起来非常简单,几行代码,高度可重用,可以随意选择(参见下面的评论).

缺点:被迫从基类派生所有控制器可能会产生一些影响,特别是如果你已经有很多控制器和/或你需要从其他基类派生它们.

2.使用模块

public class ViewBagPropertyModule: Module
{
    protected override void AttachToComponentRegistration(IComponentRegistry cr,
                                                  IComponentRegistration reg)
    {
        Type limitType = reg.Activator.LimitType;
        if (typeof(Controller).IsAssignableFrom(limitType))
        {
            registration.Activated += (s, e) =>
            {
                dynamic viewBag = ((Controller)e.Instance).ViewBag;
                viewBag.MyProperty= "value";
            };
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

PROS:没有我知道.

缺点:没有我知道(除了有点违反直觉).

3.使用RegisterController Hook

builder.RegisterControllers(asm)
    .OnActivated(e => {
        dynamic viewBag = ((Controller)e.Instance).ViewBag;
        viewBag.MyProperty = "value";
    });
Run Code Online (Sandbox Code Playgroud)

PROS:快速,安全,可重复使用:适用于任何IoC设计模式.

缺点:并不总是适合小型项目和/或简单网站:如果你不使用IoC,你通常根本不使用RegisterController.

4.使用ActionFilter属性

public class MyPropertyActionFilter : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        filterContext.Controller.ViewBag.MyProperty = "value";
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在你的Global.asax.cs文件中:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    GlobalFilters.Filters.Add(new MyPropertyActionFilter(), 0);
}
Run Code Online (Sandbox Code Playgroud)

PROS:在提到的那些中容易采用不那么突兀的方法.

缺点:我没有意识到.

我还在我的博客上写了这篇文章,解释了上述所有方法.


Kar*_*sla 17

实现您的要求的最佳和最直接的方法是创建自定义基本控制器并从此基本控制器继承您的控制器.

public class MyBaseController : Controller
{
    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        ViewBag.someThing = "someThing"; //Add whatever
        base.OnActionExecuting(filterContext);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在不是继承Controller类,而是MyBaseController在Controller中继承,如下所示: -

public class MyOtherController : MyBaseController 
{
    public ActionResult MyOtherAction()
    {
       //Your Stuff
       return View();
    }
    //Other ActionResults
}
Run Code Online (Sandbox Code Playgroud)


Ash*_*Lee 7

一种方法:创建自定义属性,然后可以在FilterConfig中全局应用它.然后,您不必在控制器中执行任何操作.

public class MyCustomViewActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        dynamic ViewBag = filterContext.Controller.ViewBag;

        ViewBag.Id = "123";
        ViewBag.Name = "Bob";
    }
}
Run Code Online (Sandbox Code Playgroud)

App_Start/FilterConfig.cs:

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new MyCustomViewActionFilter());
    }
Run Code Online (Sandbox Code Playgroud)

另一种方法,如果你需要的只是用户信息.您可以将以下内容添加到视图的顶部:

@using Microsoft.AspNet.Identity
Run Code Online (Sandbox Code Playgroud)

然后使用以下语法访问您的用户名:

@User.Identity.GetUserName()
Run Code Online (Sandbox Code Playgroud)

您还可以覆盖IPrincipal实现并提供自己的属性和方法,以添加渲染所需的更多信息.

更新:在Asp.Net vNext中查看MVC 6,这实际上已经融入了框架.http://www.asp.net/vnext/overview/aspnet-vnext/vc#inj