如何使用内置DI解析Child View的模型?

时间:2018-04-09 15:00:25

标签: c# razor dependency-injection asp.net-core-mvc razor-pages

我正在尝试解析子视图的依赖关系,从而使用@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如何在幕后处理这个问题,我该如何自己处理?是否会在找到新模型时添加新模型?也许我错过了一个让框架处理这个问题的简单方法?

1 个答案:

答案 0 :(得分:0)

您实际上正试图在名为服务定位器 anti -pattern的内容中实现此功能。因为这不是你应该做的事情。 ASP.NET Core提供了一种使用单独且不同的模型和/或注入依赖项来呈现部分的方法:它被称为视图组件。 usage总体来说非常基本。

首先,在项目中创建一个ViewComponents目录,并为其添加一个HeaderViewComponent.cs文件。在其中,添加一个类:

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返回包裹在Task中的模型,所以& #39; s await。如果你实际做了异步,比如查询数据库来获取你的模型,那么就没有必要将它包装在{ {1}}分开。

准备好后,将新视图添加到Task。按照惯例,目录由视图组件的类名决定,即Views\Shared\Components\Header\Default.cshtml的视图将在HeaderViewComponent中查找。在此处添加现有的部分视图代码。

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

Components\Header

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