2014-12-05 25 views
7

如何在所有视图中访问某些ViewBag属性?我想获得一些信息,例如当前用户名等,但无需在我的项目中专门定义每个ActionResult方法中的属性在所有视图上访问Viewbag属性

+0

你可以创建一个ActionFilter,在每个请求中添加'ViewBag'属性 – 2014-12-05 04:11:59

回答

13

完成您的要求的最佳直接方法是创建自定义基本控制器并从此基本控制器继承您的控制器。

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

现在不是继承Controller类,如继承你的控制器MyBaseController: -

public class MyOtherController : MyBaseController 
{ 
    public ActionResult MyOtherAction() 
    { 
     //Your Stuff 
     return View(); 
    } 
    //Other ActionResults 
} 
+1

我认为这是更好的,因为它与一个普通的控制器最相似(访问同一个东西,我可以在一个),也更好我的特殊应用程序,因为我已经在使用基本控制器进行国际化。 – 2014-12-08 20:37:12

6

一种方法:创建一个自定义属性,那么你可以全局应用在一个FilterConfig。那么你不必在你的控制器中做任何事情。

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

     ViewBag.Id = "123"; 
     ViewBag.Name = "Bob"; 
    } 
} 

App_Start/FilterConfig.cs

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    { 
     filters.Add(new MyCustomViewActionFilter()); 
    } 

,如果你需要的是用户信息的另一种方式。您可以添加以下到您的视图的顶部:

@User.Identity.GetUserName() 

您也可以覆盖的IPrincipal实现,并提供自己的属性和方法:

@using Microsoft.AspNet.Identity 

使用以下语法然后访问您的用户名添加更多您需要呈现的信息。

UPDATE:在Asp.Net vNext中查看MVC 6这实际上是烘焙到框架中的。 http://www.asp.net/vnext/overview/aspnet-vnext/vc#inj

15

你可以通过多种方式实现你想要的,每种方式都有其优点和缺点。

1.用碱类

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

PROS:很简单地实现,几行代码,高度可重用,可以选择退出随意(见下文评论) 。

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

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"; 
      }; 
     } 
    } 
} 

的观光:没有我所知道的。

CONS:无我知道(除了有点违反直觉)。

3.用RegisterController挂钩

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

的观光:快速,安全,可重复使用的:理想的任何IoC的设计模式。

CONS:并不总是适用于小型项目和/或简单的网站:如果您不使用IoC,您通常根本不使用RegisterController。

4.一个ActionFilter属性

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

,然后在的Global.asax.cs文件:

protected void Application_Start() 
{ 
    AreaRegistration.RegisterAllAreas(); 
    GlobalFilters.Filters.Add(new MyPropertyActionFilter(), 0); 
} 

PROS:轻松提及的那些当中的侵扰的方法少。

CONS:无我知道。

我也写了an article解释所有上述方法。

+0

BaseController实现的con同时是一个专业版:它提供了一个选择退出(不继承BaseController),其他方法似乎没有提供。 – 2015-10-05 11:48:11

+1

是的,这是肯定的优点:)更新了答案和文章。 – Darkseal 2015-10-05 20:52:49

+0

你好我想使用第四种方法,但我的viewbag它从linq查询中获取它的值。我怎样才能做到这一点?谢谢 – touinta 2016-05-18 06:09:10

0

我当前的解决方案:

创建具有所有需要的性质(非常有用和可取)基础的控制器。

public abstract class BaseController : Controller { 
    public string MyProperty { get; set; } 
} 

从基本控制器继承所有控制器。

public class MyController : BaseController { 
    //you can read your property here 
} 

在你的意见,加入这行只是“@model”一句后:

@{ BaseController ctr = ViewContext.Controller as BaseController; } 

现在,你可以使用属性在您看来,不填充ViewBag,而不需要检查和铸ViewBag值等

在视图中,可以使用一个简单的内嵌表达式:

@(ctr.MyProperty) 

或做一些神奇的逻辑...

@{ 
    if(ctr.MyProperty == "whatelse") { 
     //do ... 
    } 
} 

简单,快速,舒适。