Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ViewBag作为会话模型的持有者_C#_Asp.net Mvc_Asp.net Mvc 3_Razor - Fatal编程技术网

C# ViewBag作为会话模型的持有者

C# ViewBag作为会话模型的持有者,c#,asp.net-mvc,asp.net-mvc-3,razor,C#,Asp.net Mvc,Asp.net Mvc 3,Razor,这是一个更高层次的问题 我有一个MVC项目,其中包括管理用户。 我目前坚持一种更严格的方法,即在我的视图页面上,我只使用声明的模型,这意味着我有: @model MVCApp.Models.SomeModel 在每个View.cshtml的顶部 有些页面需要一个以上的模型。此时,我将2个模型合并为1个,并将其作为一个模型发送到视图 棘手的部分来了。假设我有一个保存用户数据的模型。该用户数据存储在会话cookie中(典型的表单身份验证)。我觉得奇怪的是,我现在必须用我自己的模型包装我使用的每个模

这是一个更高层次的问题

我有一个MVC项目,其中包括管理用户。 我目前坚持一种更严格的方法,即在我的视图页面上,我只使用声明的模型,这意味着我有:

@model MVCApp.Models.SomeModel
在每个View.cshtml的顶部

有些页面需要一个以上的模型。此时,我将2个模型合并为1个,并将其作为一个模型发送到视图

棘手的部分来了。假设我有一个保存用户数据的模型。该用户数据存储在会话cookie中(典型的表单身份验证)。我觉得奇怪的是,我现在必须用我自己的模型包装我使用的每个模型,该模型包含用户模型和我想在该视图中使用的模型

我问自己的问题是,为什么不将用户模型传递给ViewBag,并在视图中使用它。为什么这被认为是不好的做法?它允许我将该模型附加到每个页面,而无需最终复制所有模型

我很想得到一些指导。我可能看错了。任何帮助都将不胜感激


谢谢,

避免使用ViewBag有几个原因:

  • ViewBag是弱类型的
  • 你在视图中看不到Intellisense
  • 视图是ViewBag和视图模型的混合体,视图从不同的位置获取信息,而不是将所有内容集中到强类型视图模型中
  • ViewBag不能与强类型帮助程序和表达式一起使用,因为动态类型不能与扩展方法一起使用(这不是ASP.NET MVC的限制,它是.NET=>您不能对动态类型分派扩展方法)
  • 由于ViewBag的这种弱类型特性,您必须在视图中强制转换,将它们转换为意大利面代码,因为HTML帮助程序希望特定类型作为参数传递
  • 。。。这个列表还在继续(我真的没有时间填写,但它是一个非常大的列表)
现在我们知道ViewBag是不好的,不应该使用它,有不同的方法可以通过使用视图模型来解决这个需求

一种可能性是使用,它允许您通过完整的控制器/模型/视图生命周期在视图中插入部分HTML。这样,您就可以拥有一个常用的小部件,而不会干扰主视图模型

另一种可能性是拥有一个基本视图模型,该模型将包含一个表示用户详细信息的属性,并由一个自定义全局操作过滤器填充,该过滤器可在每次控制器操作完成执行并返回视图结果时执行。操作筛选器可以截获此视图结果,读取身份验证cookie信息并设置视图模型属性。这假定您的所有视图模型都源自公共基础视图模型。如果您需要在每个页面上显示此用户信息,这显然是有意义的

例如:

public class UserInfoInjectorAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var result = filterContext.Result as ViewResultBase;
        if (result == null)
        { 
            // the controller action didn't return any view result => no need to continue
            return;
        }

        var model = result.Model as BaseViewModel;
        if (model == null)
        {
            // the controller action didn't pass a model or the model passed to the view
            // doesn't derive from the common base view model that will contain 
            // the user info property => no need to continbue any further
            return;
        }

        model.UserInfo = ... go ahead and read the forms authentication cookie
                             userData portion and extract the information
                             you are looking for
    }
}
现在剩下的就是将这个动作过滤器注册为全局动作过滤器,它将应用于所有控制器动作

现在,如果您的所有视图模型都源于此
BaseViewModel
,您将知道,一旦您到达视图,UserInfo属性将填充相关信息,而不会用获取此属性的代码污染所有控制器操作。你仍然可以在view=>no-ViewBag(youpeee)中进行强输入


当然,根据您的具体情况,可能会有其他方法来实现这一点(显然不涉及任何
ViewBag
)。

应避免使用ViewBag的原因有两个:

  • ViewBag是弱类型的
  • 你在视图中看不到Intellisense
  • 视图是ViewBag和视图模型的混合体,视图从不同的位置获取信息,而不是将所有内容集中到强类型视图模型中
  • ViewBag不能与强类型帮助程序和表达式一起使用,因为动态类型不能与扩展方法一起使用(这不是ASP.NET MVC的限制,它是.NET=>您不能对动态类型分派扩展方法)
  • 由于ViewBag的这种弱类型特性,您必须在视图中强制转换,将它们转换为意大利面代码,因为HTML帮助程序希望特定类型作为参数传递
  • 。。。这个列表还在继续(我真的没有时间填写,但它是一个非常大的列表)
现在我们知道ViewBag是不好的,不应该使用它,有不同的方法可以通过使用视图模型来解决这个需求

一种可能性是使用,它允许您通过完整的控制器/模型/视图生命周期在视图中插入部分HTML。这样,您就可以拥有一个常用的小部件,而不会干扰主视图模型

另一种可能性是拥有一个基本视图模型,该模型将包含一个表示用户详细信息的属性,并由一个自定义全局操作过滤器填充,该过滤器可在每次控制器操作完成执行并返回视图结果时执行。操作筛选器可以截获此视图结果,读取身份验证cookie信息并设置视图模型属性。这假定您的所有视图模型都源自公共基础视图模型。如果您需要在每个页面上显示此用户信息,这显然是有意义的

例如:

public class UserInfoInjectorAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var result = filterContext.Result as ViewResultBase;
        if (result == null)
        { 
            // the controller action didn't return any view result => no need to continue
            return;
        }

        var model = result.Model as BaseViewModel;
        if (model == null)
        {
            // the controller action didn't pass a model or the model passed to the view
            // doesn't derive from the common base view model that will contain 
            // the user info property => no need to continbue any further
            return;
        }

        model.UserInfo = ... go ahead and read the forms authentication cookie
                             userData portion and extract the information
                             you are looking for
    }
}
现在剩下的就是将这个动作过滤器注册为全局动作过滤器,它将应用于所有控制器动作

现在,如果您的所有视图模型都源自此
BaseViewModel
,您将知道,一旦您到达视图,UserInfo属性将填充相关信息,而不会用获取此属性的代码污染所有控制器操作