簡體   English   中英

如何在每個控制器動作中使用異步ViewModel?

[英]How to use asynchronous ViewModel in every controller action?

我是asp.net mvc(5)的新手,我在我的網站上遇到了一個問題。

基本上,所有aspnet_users都通過guid鏈接到我的特定user表。

我有一個帶有UnitOfWorkViewModelBaseBaseController類:

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繼承的viewmodel,因為它在布局中使用,但我不知道在哪里以及如何在其中設置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 我試過了,因為所有動作都使用ViewModelBase所以我也把每個動作都設置為異步。 但是,由於調用的操作是async因此@Html.ActionLink不再起作用。

最后,我的問題是:這個ViewModelBaseUser屬性是否正確? 如果是, LoadBaseContext應該是異步的嗎? 然后,如何讓它與行動一起工作?

非常感謝。

UPDATE

布局提取:

@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);
}

如果您在所有視圖中都有所需的內容,則可以確保每個視圖都采用包含或擴展該核心數據集的視圖模型, 或者您可以簡單地將數據放入ViewBag

要執行后者,您可以在基本控制器中覆蓋OnActionExecuting ,並在那里設置ViewBag內容。

protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
    base.OnActionExecuting(filterContext);
    this.ViewBag["IsAuthenticated"] = this.Request.IsAuthenticated;
    // ...
}

如果您想要async行為,那么您可以根據需要調整此帖子

要在不重寫OnActionExecuting情況下執行此操作,可以在控制器基類中放置一個async方法,以設置ViewBag的數據:

protected async virtual Task PopulateViewBag()
{
    this.ViewBag["foo"] = await MyAsyncMethod();

    // ...
}

...然后只需從您的每個控制器操作中調用它:

public async Task<ActionResult> MyAction()
{
    await this.PopulateViewBag();

    // ... more code
}

不過,這會有點單調乏味。

最后一句話:取決於您期望擁有多少用戶等,可能更容易獲取用戶信息一次 ,然后將其緩存(例如在Session ),而不是在每次請求期間反復獲取。 據推測,大多數用戶信息不會在請求之間發生變化......

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM