构造函数控制器中的MVC异步方法

Dim*_*hko 7 c# asp.net-mvc async-await

我正在尝试制作动态菜单(存储在数据库中),该菜单显示在所有Web应用程序页面上.使用Google我发现将菜单视图作为Master View(_Layout.cshtml)的一部分更好.因此,控制器的每个操作方法都必须包含菜单模型的数据.为了避免代码重复,我找到了创建基本控制器并使用其构造函数提供数据的解决方案:

https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/views/passing-data-to-view-master-pages-cs

此外,我正在尝试使用async/await可能性,而我的PageService(菜单)正在使用ToListAsync()从DB获取数据.所以现在我有一个问题,BaseController构造函数有一个异步方法:

public class BaseController : AsyncController, IBaseController
{
    private readonly IPageService _pageService;

    public BaseController(IPageService pageService)
    {
        _pageService = pageService;
        SetBaseViewModelAsync();
    }

    private async Task SetBaseViewModelAsync()
    {
        ViewData["Pages"] = await _pageService.GetAllAsync();
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道这是坏代码,但我不知道如何正确设计这种情况.也许有另一种更好的方法来创建动态菜单或另一种异步获取数据的方法?

此外,我发现了这篇文章,但我不知道我是否可以应用它的解决方案,因为我不知道我是否可以处理控制器实例创建:

http://blog.stephencleary.com/2013/01/async-oop-2-constructors.html

Eri*_*ips 6

您可以创建一个名为的控制器MenuController,创建一个调用的方法Default,然后从您的布局中调用它,而不是从基本控制器(可以进行大量额外工作和测试)中获取所有内容:

[ChildActionOnly]
public Default()
{
  var viewModel = _pageService.GetAllAsync();
  return Partial(viewModel);
}
Run Code Online (Sandbox Code Playgroud)

在你的布局中:

@{Html.RenderAction("Default", "Menu");}
Run Code Online (Sandbox Code Playgroud)

这确实是最简单,最干净的解决方案.最大的PRO是你可以控制菜单的缓存,与方法调用分开.asp.net-mvc(1-5)没有很好的解决方案以这种方式运行异步代码.(ActionFilters不能异步和(渲染)Partials不能是异步的.你仍然可以调用异步方法,它只会运行Sync.

渲染与非渲染性能.