gpt4 book ai didi

asp.net-mvc - MVC BaseController 和 BaseModel 确保值对所有 View 可用

转载 作者:行者123 更新时间:2023-12-03 10:33:37 27 4
gpt4 key购买 nike

这是关于@Andre Calil 在以下 SO 中提供的解决方案的问题 Razor MVC, where to put global variables that's accessible across master page, partiview and view?

我正在使用 Andre 的方法,但有一个小问题:我的 _Layout 被强类型化为 BaseModel,我的 View 被强类型化为继承自 BaseModel 的 AccountModel。

问题是:如果我返回一个没有模型的 View ,即返回 View(),那么我会得到一个异常。这是因为 BaseController OnActionExecuted 事件正在检查提供的模型是否为空,如:

protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Result is ViewResultBase)//Gets ViewResult and PartialViewResult
{
object viewModel = ((ViewResultBase)filterContext.Result).Model;

if (viewModel != null && viewModel is MyBaseModel)
{
MyBaseModel myBase = viewModel as MyBaseModel;
myBase.Firstname = CurrentUser.Firstname; //available from base controller
}
}
base.OnActionExecuted(filterContext);//this is important!
}

模型为空,因此这种情况并不总是有效。我的下一步是确保我始终将模型传递到 View 中,即使它是一个空的 BaseModel 对象。问题是我得到以下异常:

The model item passed into the dictionary is of type 'MyNamespace.BaseModel', but this dictionary requires a model item of type 'MyNamespace.AccountModel'.

我需要澄清的两点:

  1. 我认为这可行,因为 AccountModel 是 BaseModel 的子类?
  2. 如果上面代码中的模型为 null,是否有另一种方法可以将模型注入(inject)每个 View ,这样我就可以避免重构所有代码以包含 return View(BaseModel.Empty)?

最佳答案

您需要查看 Phil Haacked 在本文中描述的自定义 Razor View :

http://haacked.com/archive/2011/02/21/changing-base-type-of-a-razor-view.aspx

所以基本上在您的 BaseController 中您将设置一个公共(public)变量,该变量将在基本 Controller 的 Initialize 事件中的每个请求中获取(在我的例子中它是 User 的实例):

public class BaseController : Controller
{
public User AppUser;

protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);
AppUser = _userService.GetUser(id);
ViewBag.User = AppUser;
}
}

现在你有了一个变量,它可以被任何继承自基础 Controller 的 Controller 访问。剩下要做的唯一一件事就是弄清楚如何在您的 View 中使用这个变量。这是我上面链接的文章可以帮助你的地方。默认情况下,所有 View 都是从 System.Web.Mvc.WebViewPage 生成的。但是,您可以通过执行以下操作来自定义此类的实现:

namespace YourApplication.Namespace
{
public abstract class CustomWebViewPage : WebViewPage
{
private User _appUser;

public User AppUser
{
get
{
try
{
_appUser = (User)ViewBag.User;
}
catch (Exception)
{
_appUser = null;
}
return _appUser;
}
}
}

public abstract class CustomWebViewPage<TModel> : WebViewPage<TModel> where TModel : class
{
private User _appUser;

public User AppUser
{
get
{
try
{
_appUser = (User)ViewBag.User;
}
catch (Exception)
{
_appUser = null;
}
return _appUser;
}
}
}
}

您刚刚定义了一个自定义 razor View 类,它具有 user 属性,并尝试从我们在基本 Controller 中设置的 ViewBag.User 中获取它。剩下唯一要做的就是告诉您的应用程序在尝试生成 View 时使用此类。您可以通过在 VIEWS web.config 文件中设置以下行来执行此操作:

<pages pageBaseType="YourApplication.Namespace.CustomWebViewPage">

现在,在您的 View 中,您获得了 User 属性的助手,您可以像这样使用它:

@AppUser

请注意,页面声明需要进入 VIEWS web.config 文件而不是主应用程序 web.config!

我认为这对您来说是一个更好的解决方案,因为您不必通过 View 模型为所有 View 提供基础模型。 View 模型应按预期保留。

关于asp.net-mvc - MVC BaseController 和 BaseModel 确保值对所有 View 可用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18915990/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com