简体   繁体   English

如何在每个控制器动作中使用异步ViewModel?

[英]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 : 我有一个带有UnitOfWorkViewModelBaseBaseController类:

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 ? 最后,我的问题是:这个ViewModelBaseUser属性是否正确? 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.

相关问题 如何将带有变音符号/特殊字符的 viewModel 字符串值传递给控制器​​动作 - How to pass viewModel string value with umlauts/special characters to controller action 如何在异步控制器中使用Dapper? - How do I use Dapper in an asynchronous controller? 如何检查控制器的每个动作的会话? - How to check sessions on every action of a controller? 如何将控制器动作转换为非阻塞/异步 - How to convert controller action to be non-blocking/asynchronous 我在另一个viewmodel中有一个viewmodel列表。 如何将参数从动作传递到控制器? - I have a list of viewmodel in another viewmodel. How can I pass parameter from action to controller? 我的 ViewModel 流程正确吗? 如何将其发送回 controller 并在 controller 操作中刷新它? - Is my ViewModel flow right? How to send it back to controller and refresh it on a controller action? 仅仅返回视图的控制器操作是否必须是异步的? - Is it necessary for a controller action that only returns a view to be asynchronous? 如何避免重复为控制器中的每个操作发生的代码 - How to avoid duplicating code that occurs for every action in a controller 只读会话以及异步操作和任务线程。 控制器的行为如何? - ReadOnly Session coupled with Asynchronous Action and Task Thread. How does the Controller behave then? EventHandler 传递连续的异步 I2C 数据以在 ViewModel 中使用 - EventHandler to pass continuous asynchronous I2C data for use in ViewModel
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM