我是 asp.net mvc (5) 的新手,我的网站遇到了问题。
基本上,所有 aspnet_users
都通过 guid
链接到我的特定 user
表。
我有一个带有 UnitOfWork
和 ViewModelBase
的 BaseController
类:
public class BaseController : Controller
{
protected UnitOfWork UnitOfWork { get; private set; }
public ViewModelBase ViewModel { get; set; }
}
(摘自)ViewModelBase
类,包含布局页面中所需的信息:
public class ViewModelBase
{
public User User { get; set; }
public bool IsAuthentified { get; set; }
public bool Loaded { get; set; }
}
以及使用它的布局:
@model Project.ViewModels.ViewModelBase
<html>
<body>
Some very cool layout stuff related to the User in the ViewModelBase
</body>
</html>
这是一个使用 HomeController
的例子:
public class HomeController : BaseController
{
private new HomeViewModel ViewModel
{
get { return (HomeViewModel)base.ViewModel; }
}
public HomeController()
{
ViewModel = new HomeViewModel();
}
public ActionResult Index()
{
// I need to get the MembershipUser here to retrieve the related User and set it in the ViewModel
return View(ViewModel);
}
}
HomeViewModel
:
public class HomeViewModel : ViewModelBase
{
public string HomeSpecificProperty { get; set; }
}
和 View :
@model Project.ViewModels.HomeViewModel
@{
ViewBag.Title = "Home";
Layout = "~/Views/Shared/Layout.cshtml";
}
Welcome @Model.User.UserName !
<br />
@Model.HomeSpecificProperty
这是我的问题。问题是所有页面都有一个继承自 ViewModelBase
的 View 模型,因为它用于布局,但我不知道在哪里以及如何设置 User
属性它。
由于 Membership
用于检索 User
,它必须在 Action
中,我不能在 ViewModelBase< 中执行此操作
构造函数。
因此我在 BaseController
中添加了这段代码,它在第一个 get
上设置了 ViewModelBase
属性:
private ViewModelBase viewModel;
protected ViewModelBase ViewModel
{
get
{
if (!viewModel.Loaded)
LoadBaseContext();
return viewModel;
}
set { viewModel = value; }
}
private void LoadBaseContext()
{
viewModel.IsAuthentified = HttpContext.User.Identity.IsAuthenticated;
if (viewModel.IsAuthentified)
{
MembershipUser user = Membership.GetUser();
viewModel.Player = UnitOfWork.UserRepo.Get((Guid)user.ProviderUserKey);
}
viewModel.Loaded = true;
}
可能不是很漂亮,但是很管用。但是,由于其中有一些数据库访问(特别是获取 User
),我想我应该将 LoadBaseContext
函数放在 async
中。
我试过了,因为所有 Action 都使用 ViewModelBase
我也把每个 Action 都异步了。但是 @Html.ActionLink
不再起作用,因为调用的操作是 async
。
最后,我的问题是:ViewModelBase
和 User
属性是正确的做法吗?如果是,LoadBaseContext
应该是异步的吗?那么,如何让它配合 Action 呢?
非常感谢。
更新
布局摘录:
@if (!Model.IsAuthentified)
{
@Html.Action("Index", "Authentification", null) // display login partial view
}
else
{
@Html.Action("Index", "UserInfos", null) // display userinfos partial view
}
Authentication controller Index 的 Action :
public ActionResult Index()
{
ViewModel = new AuthentificationViewModel();
// loads the ViewModelBase properties here
return PartialView("~/Views/Shared/Partials/Login.cshtml", ViewModel);
}
最佳答案
如果您在所有 View 中都有一些您一直想要的东西,您可以确保每个 View 都采用包含或扩展该核心数据集的 View 模型,或者您可以简单地把ViewBag
中的数据。
要执行后者,您可以覆盖基本 Controller 中的 OnActionExecuting
,并在那里设置 ViewBag
内容。
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
this.ViewBag["IsAuthenticated"] = this.Request.IsAuthenticated;
// ...
}
如果您想要async
行为,那么您可以调整this post满足您的需求。
要在不覆盖 OnActionExecuting
的情况下执行此操作,您可以在 Controller 基类中放置一个 async
方法来设置 ViewBag
中的数据:
protected async virtual Task PopulateViewBag()
{
this.ViewBag["foo"] = await MyAsyncMethod();
// ...
}
...然后只需从您的每个 Controller 操作中调用它:
public async Task<ActionResult> MyAction()
{
await this.PopulateViewBag();
// ... more code
}
不过,这会有点乏味。
最后一句话:根据您希望拥有的用户数量等,获取用户信息一次,然后将其缓存(例如在Session
),而不是在每次请求时重复获取它。大概大多数用户信息不会在请求之间改变......
关于c# - 如何在每个 Controller Action 中使用异步 ViewModel?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34024050/