这更像是一个高层次的问题。
我有一个MVC项目,除其他外,管理用户。 我目前正在坚持一种更严格的方法,在我的视图页面上,我只使用一个声明的模型,这意味着我有一个:
@model MVCApp.Models.SomeModel
在每个View.cshtml的顶部
有些页面需要1个以上的型号。此时,我将2个模型合并为1,并将其作为一个模型发送到视图。
这是棘手的部分。假设我有一些用于保存用户数据的模型。该用户数据存储在会话cookie中(典型的表单身份验证)。我现在必须将我使用的每个模型都包装在我自己的模型中,这个模型包含用户模型和我想在该视图中使用的模型,这似乎很奇怪。
我问自己的问题是为什么不将用户模型传递给ViewBag并在View中使用它。为什么这被认为是不好的做法?它允许我将该模型附加到每个页面,而不必最终复制我的所有模型。
我很乐意得到一些指导。我可能会以错误的方式看待这个问题。任何帮助都有很大的帮助。
谢谢,
答案 0 :(得分:4)
应该避免使用ViewBag的原因有几个:
现在我们知道ViewBag很糟糕且不应该使用,有不同的方法可以通过使用视图模型来解决这个问题。
一种可能性是使用Html.Action helper,它允许您通过完整的Controller / Model / View生命周期在视图中插入部分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属性将填充相关信息,而不会使用执行提取的代码污染所有控制器操作这个性质。你仍然可以在视图中输入强大的内容=>没有ViewBag(youpeeee)。
当然,根据您的具体情况,可能还有其他方法可以实现这一目标(显然不涉及任何ViewBag
)。
答案 1 :(得分:0)
您可以ActionFilterAttribute,在那些加载需要特定ViewBag项目的视图的操作中,您可以初始化它们。
我不推荐它,因为它会更难以保留,但它将是一种可以解决你的问题的通用方法。