我正在尝试解析子视图的依赖关系,从而使用@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如何在幕后处理这个问题,我该如何自己处理?是否会在找到新模型时添加新模型?也许我错过了一个让框架处理这个问题的简单方法?
答案 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
由于视图组件只是类,因此它们可以像任何其他类一样注入,这意味着您可以轻松访问您可能需要的上下文或任何其他注册服务,只需为其添加构造函数参数。