如何使用内置 DI 来解析子视图的模型?

How can I use the built in DI to resolve a Child View's model?

我试图在使用 @Html.Partial() 从父视图调用它时解决子视图的依赖关系。

@inject IServiceProvider ServiceProvider

//...

<body>
    @Html.RenderPartial("Layouts/Elements/_Header", ServiceProvider.GetRequiredService<_HeaderModel>())
</body>

//...

问题是模型 _HeaderModel 没有注册到 DI 容器。所以我得到错误:

InvalidOperationException: No service for type 'Client_Portal.Pages.Layouts._HeaderModel' has been registered.

但是等等,我的任何其他模型和框架都不能很好地解决它们的依赖关系! ASP.NET Core 如何在幕后处理这个问题,我自己该如何处理?它会在发现新模型时添加它们吗?也许我错过了一个让框架处理这个问题的简单方法?

您实际上是在尝试在所谓的服务定位器 模式中实现这一点。因为这不是你应该做的事情。 ASP.NET Core 提供了一种使用单独且不同的模型 and/or 注入依赖项来呈现部分的方法:它称为视图组件。 usage 总体来说非常基础。

首先,在您的项目中创建一个 ViewComponents 目录并向其中添加一个 HeaderViewComponent.cs 文件。在里面,添加一个 class 比如:

public class HeaderViewComponent : ViewComponent
{
    public async Task<IViewComponentResult> InvokeAsync()
    {
        var model = await GetModelAsync();
        return View(model);
    }

    public Task<HeaderModel> GetModelAsync()
        => return Task.FromResult(new HeaderModel());
}

唯一需要的方法是InvokeAsync。视图组件始终是异步的。然而,因为在这个例子中,异步实际上没有发生任何事情(只是更新一个实例 HeaderModel,我添加了一个方便的方法,GetModelAsync returns 模型包裹在 Task,所以 await 有一些东西。如果你 实际上 做一些异步的事情,比如查询数据库来获取你的模型,那么就没有必要把它包装在 Task分别.

完成后,将新视图添加到 Views\Shared\Components\Header\Default.cshtml。按照惯例,目录由视图组件的 class 名称指定,即 HeaderViewComponent 的视图将在 Components\Header 中查找。在此处添加您现有的局部视图代码。

最后,在您的布局中或您需要引入此部分的任何其他地方,只需执行以下操作:

@await Component.InvokeAsync("Header")

由于视图组件只是 classes,它们可以像任何其他组件一样注入 class,这意味着您可以轻松访问您的上下文或您可能需要的任何其他注册服务,只需添加一个它的构造函数参数。