[英]How to use asynchronous ViewModel in every controller action?
I'm new to asp.net mvc (5) and I am facing an issue on my website. 我是asp.net mvc(5)的新手,我在我的网站上遇到了一个问题。
Basically, all aspnet_users
are linked to my specific user
table via the guid
. 基本上,所有
aspnet_users
都通过guid
链接到我的特定user
表。
I have a BaseController
class with a UnitOfWork
and a ViewModelBase
: 我有一个带有
UnitOfWork
和ViewModelBase
的BaseController
类:
public class BaseController : Controller
{
protected UnitOfWork UnitOfWork { get; private set; }
public ViewModelBase ViewModel { get; set; }
}
(Extract of) the ViewModelBase
class, containing the information needed in the layout page : (摘录)
ViewModelBase
类,包含布局页面中所需的信息:
public class ViewModelBase
{
public User User { get; set; }
public bool IsAuthentified { get; set; }
public bool Loaded { get; set; }
}
And the layout which uses it : 以及使用它的布局:
@model Project.ViewModels.ViewModelBase
<html>
<body>
Some very cool layout stuff related to the User in the ViewModelBase
</body>
</html>
Here is an example of use with the HomeController
: 以下是与
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);
}
}
The HomeViewModel
: HomeViewModel
:
public class HomeViewModel : ViewModelBase
{
public string HomeSpecificProperty { get; set; }
}
And the view : 并且观点:
@model Project.ViewModels.HomeViewModel
@{
ViewBag.Title = "Home";
Layout = "~/Views/Shared/Layout.cshtml";
}
Welcome @Model.User.UserName !
<br />
@Model.HomeSpecificProperty
And here is my problem. 这是我的问题。 The thing is all the pages have a viewmodel inherited from
ViewModelBase
, since it is used in the layout, but I don't know where nor how to set the User
property in it. 事情是所有页面都有一个从
ViewModelBase
继承的viewmodel,因为它在布局中使用,但我不知道在哪里以及如何在其中设置User
属性。 Since Membership
is used to retrieve the User
it has to be in an Action
, I can't do this in the ViewModelBase
constructor. 由于
Membership
用于检索User
因此它必须在Action
,我不能在ViewModelBase
构造函数中执行此操作。
Thus I added this code in the BaseController
, which sets the ViewModelBase
properties on the first get
: 因此我在
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;
}
Might not be very beautiful, but works. 可能不是很漂亮,但有效。 However, since there is some database acesses in it (notably to get the
User
), I thought I should put the LoadBaseContext
function async
. 但是,由于其中有一些数据库(特别是获取
User
),我认为我应该将LoadBaseContext
函数设置为async
。 I tried, and since all actions use ViewModelBase
I put every action async too. 我试过了,因为所有动作都使用
ViewModelBase
所以我也把每个动作都设置为异步。 But then @Html.ActionLink
doesn't work anymore since the action called is async
. 但是,由于调用的操作是
async
因此@Html.ActionLink
不再起作用。
Finally, my question is : Is this ViewModelBase
and User
property the right way to do ? 最后,我的问题是:这个
ViewModelBase
和User
属性是否正确? If it is, should the LoadBaseContext
be async ? 如果是,
LoadBaseContext
应该是异步的吗? Then, how to make it work with the actions ? 然后,如何让它与行动一起工作?
Thanks a lot. 非常感谢。
UPDATE UPDATE
Extract of the layout : 布局提取:
@if (!Model.IsAuthentified)
{
@Html.Action("Index", "Authentification", null) // display login partial view
}
else
{
@Html.Action("Index", "UserInfos", null) // display userinfos partial view
}
Authentification controller Index's action : 认证控制器索引的行动:
public ActionResult Index()
{
ViewModel = new AuthentificationViewModel();
// loads the ViewModelBase properties here
return PartialView("~/Views/Shared/Partials/Login.cshtml", ViewModel);
}
If you have something that you always want in all of your views, you could either ensure that every view takes a view model that includes or extends that core set of data, or you could simply put the data in the ViewBag
. 如果您在所有视图中都有所需的内容,则可以确保每个视图都采用包含或扩展该核心数据集的视图模型, 或者您可以简单地将数据放入
ViewBag
。
To do the latter, you could override OnActionExecuting
in your base controller, and set the ViewBag
contents there. 要执行后者,您可以在基本控制器中覆盖
OnActionExecuting
,并在那里设置ViewBag
内容。
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
this.ViewBag["IsAuthenticated"] = this.Request.IsAuthenticated;
// ...
}
If you want async
behaviour, then you might be able to adapt this post to your needs. 如果您想要
async
行为,那么您可以根据需要调整此帖子 。
To do this without overriding OnActionExecuting
, you could put an async
method in your controller base class that sets the data in the ViewBag
: 要在不重写
OnActionExecuting
情况下执行此操作,可以在控制器基类中放置一个async
方法,以设置ViewBag
的数据:
protected async virtual Task PopulateViewBag()
{
this.ViewBag["foo"] = await MyAsyncMethod();
// ...
}
... and then simply call this from each and every one of your controller actions: ...然后只需从您的每个控制器操作中调用它:
public async Task<ActionResult> MyAction()
{
await this.PopulateViewBag();
// ... more code
}
It would be a bit tedious, though. 不过,这会有点单调乏味。
One final word: depending on how many users you expect to have etc. it may be easier to get the user information once , and then cache it (eg in the Session
), rather than repeatedly get it during every request. 最后一句话:取决于您期望拥有多少用户等,可能更容易获取用户信息一次 ,然后将其缓存(例如在
Session
),而不是在每次请求期间反复获取。 Presumably most of the user info isn't going to change between requests... 据推测,大多数用户信息不会在请求之间发生变化......
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.