【问题标题】:C# Centralizing repeating VIewData in MVCC# 在 MVC 中集中重复 VIewData
【发布时间】:2015-02-06 15:57:05
【问题描述】:

当用户登录我的应用程序时,我想在整个应用程序中显示他的名字。我正在使用 asp.net MVC 框架。但我不想要的是必须在每个控制器中放入类似的东西:

ViewData["User"] = Session["User"];

这是因为您可能不会重复自己。 (我相信这就是 OO 编程的 DRY [Don't Repeat Yourself] 原则。) ViewData["User"] 在我的母版页上。所以我的问题是,在一个地方处理我的 ViewData["User"] 的巧妙方法是什么?

【问题讨论】:

    标签: c# asp.net-mvc viewdata


    【解决方案1】:

    您可以在控制器基类或应用于控制器/动作的动作过滤器中相当容易地做到这一点。无论哪种情况,您都有机会在操作之前(或之后)触摸请求 - 因此您可以在此处添加此功能。

    例如:

    public class UserInfoAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(
            ActionExecutingContext filterContext)
        {
            base.OnActionExecuting(filterContext);
            filterContext.Controller.ViewData["user"] = "Foo";
        }
    }
    ...
    [HandleError, UserInfo]
    public class HomeController : Controller
    {...}
    

    (也可以在action(方法)级别使用)


    或使用通用基类:

    public abstract class ControllerBase : Controller
    {
        protected override void OnActionExecuting(
            ActionExecutingContext filterContext)
        {
            ViewData["user"] = "Bar";
            base.OnActionExecuting(filterContext);
        }
    }
    
    [HandleError]
    public class HomeController : ControllerBase
    {...}
    

    【讨论】:

    • Thnx,我会试试基类。但是为什么要重写 OnActionExecuting() 方法呢?这个方法有什么作用?它的目的是什么?
    • 它在您的操作(方法)执行之前执行。如果您愿意,您可以改用 OnActionExecuted,它会在您的操作执行后立即执行
    • 好的,因为我把它放在我的基类中,它会影响我在控制器中的所有操作?
    • 正确。将[UserInfo] 放在类级别(而不是方法级别)的操作过滤器方法也是如此。
    【解决方案2】:

    已经一年了,但我只是偶然发现了这个问题,我相信有更好的答案。

    Jimmy Bogard 将接受的答案中描述的解决方案描述为反模式,并提供了一个更好的解决方案,涉及 RenderAction:http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/06/18/the-filter-viewdata-anti-pattern.aspx

    【讨论】:

      【解决方案3】:

      在整个应用程序中提供持久模型数据的另一种方法是用您的自定义控制器覆盖 DefaultFactoryController。在您的 CustomerFactoryController 中,您可以将 ViewBag 与您想要保留的模型相结合。

      【讨论】:

        【解决方案4】:

        使用 UserName 属性为您的模型创建一个基类:

        public abstract class ModelBase
        {
            public string UserName { get; set; }
        }
        

        为您的控制器创建一个基类并覆盖它的 OnActionExecuted 方法。在其中检查模型是否派生自 BaseModel,如果是,则设置它的 UserName 属性。

        public class ControllerBase : Controller
        {
            protected override void OnActionExecuted(
                ActionExecutedContext filterContext)
            {
                var modelBase = ViewData.Model as ModelBase;
        
                if (modelBase != null)
                {
                    modelBase.UserName = "foo";
                }
        
                base.OnActionExecuted(filterContext);
            }
        }
        

        然后您将能够在视图中显示用户的用户名,如下所示:

        <%= Html.Encode(Model.UserName) %>
        

        另见

        【讨论】:

        • "检查模型是否源自 BaseModel 和 .." 我该怎么做?可以举个例子吗?
        • 我想我得到了你的解决方案。但我是不是有点复杂?在某种程度上,Marc Gravell 的通用基类不是做同样的事情吗?
        • @Martijn,它允许您使用强类型模型而不是 ViewData[..] 字典。有了它,您的视图等中就有了智能支持。
        • @KonstantinTarkus - 不应该是var modelBase = ViewData.Model as BaseModel; 吗?
        猜你喜欢
        • 2016-07-02
        • 1970-01-01
        • 1970-01-01
        • 2023-03-26
        • 2011-07-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-29
        相关资源
        最近更新 更多