我是asp.net mvc(5)的新手,我在网站上遇到了一个问题。
基本上,所有aspnet_users
都通过user
链接到我的特定guid
表。
我有一个BaseController
课程,其中包含UnitOfWork
和ViewModelBase
:
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; }
}
观点:
@model Project.ViewModels.HomeViewModel
@{
ViewBag.Title = "Home";
Layout = "~/Views/Shared/Layout.cshtml";
}
Welcome @Model.User.UserName !
<br />
@Model.HomeSpecificProperty
这是我的问题。事情是所有页面都有一个继承自ViewModelBase
的视图模型,因为它在布局中使用,但我不知道在哪里或如何在其中设置User
属性。
由于Membership
用于检索User
Action
,因此我无法在ViewModelBase
构造函数中执行此操作。
因此,我在BaseController
中添加了此代码,该代码在第一个ViewModelBase
上设置get
属性:
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
。
我尝试过,因为所有操作都使用ViewModelBase
我也将每个操作都设置为异步。但是,@Html.ActionLink
已经不再有效,因为所谓的操作是async
。
最后,我的问题是:这个ViewModelBase
和User
属性是正确的方法吗?如果是,那么LoadBaseContext
应该是异步的吗?然后,如何让它与行动一起工作?
非常感谢。
更新
布局摘录:
@if (!Model.IsAuthentified)
{
@Html.Action("Index", "Authentification", null) // display login partial view
}
else
{
@Html.Action("Index", "UserInfos", null) // display userinfos partial view
}
认证控制器索引的行动:
public ActionResult Index()
{
ViewModel = new AuthentificationViewModel();
// loads the ViewModelBase properties here
return PartialView("~/Views/Shared/Partials/Login.cshtml", ViewModel);
}
答案 0 :(得分:3)
如果您在所有视图中都有所需的内容,则可以确保每个视图都采用包含或扩展该核心数据集的视图模型,或您可以简单地放置Ok, passed 10000 tests.
。
要执行后者,您可以覆盖基本控制器中的ViewBag
,并在那里设置OnActionExecuting
内容。
ViewBag
如果您需要protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
this.ViewBag["IsAuthenticated"] = this.Request.IsAuthenticated;
// ...
}
行为,那么您可以根据自己的需要调整this post。
要在不覆盖async
的情况下执行此操作,您可以在控制器基类中放置OnActionExecuting
方法,以设置async
中的数据:
ViewBag
...然后只需从您的每个控制器操作中调用它:
protected async virtual Task PopulateViewBag()
{
this.ViewBag["foo"] = await MyAsyncMethod();
// ...
}
但是,这会有点单调乏味。
最后一句话:取决于您希望拥有多少用户等。一旦获取用户信息可能更容易,然后将其缓存(例如, public async Task<ActionResult> MyAction()
{
await this.PopulateViewBag();
// ... more code
}
),而不是在每次请求期间反复获取它。据推测,大多数用户信息都不会在请求之间发生变化......