Asp.Net核心依赖项注入ValidateOnBuild无法正常工作



我在.NET 5中有一个带有RazorPages的项目,我设置此代码来验证Progam.cs文件中的Dependency注入:

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseDefaultServiceProvider(options =>
{
options.ValidateOnBuild = true;
options.ValidateScopes = true;
})....

我忘记注册注入页面的服务,所以我本以为当我尝试启动应用程序时,错误页面会显示这种问题,但我不明白为什么没有发生,因为例如,如果我没有注册ILocalizerService,就会发生这种情况:这是我的剃刀页面:

public class SignupModel : IdentityPageModel
{
[BindProperty]
public Models.Account.Signup Signup { get; set; }
private readonly CustomUserManager _userManager;
private readonly ILogger<SignupModel> _logger;
private readonly INcsService _ncsService;
public SignupModel(CustomUserManager userManager, 
ILogger<SignupModel> logger,
INcsService ncsService) : base(localizerService)
{
Guard.Against.Null(userManager, nameof(userManager));
Guard.Against.Null(logger, nameof(logger));
Guard.Against.Null(ncsService, nameof(ncsService));

_userManager = userManager;
_logger = logger;
_ncsService = ncsService;
}
// Other code....
}

这是我的服务:

[PublicAPI]
public class NcsService : INcsService
{
private readonly IHttpClientFactory _httpClientFactory;
public NcsService(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
// Other code...
}

我只注册了IHttpClientFactory,但没有注册INcsService接口和实现:

services.AddHttpClient(nameof(NcsService), client =>
{
client.BaseAddress = new Uri(ncsSettings.BaseUri);
client.DefaultRequestHeaders.Add("x-functions-key", ncsSettings.ApiKey);
client.DefaultRequestHeaders.Add("x-app-name", "TSID");
}).AddHeaderPropagation(options =>
{
options.Headers.Add("x-request-id");
options.Headers.Add("x-correlation-id");
})
.AddPolicyHandler(GetRetryPolicy());

我希望我是清白的
谢谢

问题的根源是Microsoft的默认IComponentActivator实现(DefaultComponentActivator(。Component Activator控制创建Razor页面,但内置行为不会从内置容器请求这些页面。相反,它只是使用Activator.CreateInstance.创建它们

这意味着Blazor不会在内置容器中注册您的页面,因此,该页面将不会成为容器验证过程的一部分。

这是Blazor中的一个设计缺陷,因为众所周知,如果您使用DI容器,您应该让所有应用程序组件通过容器管道。这是容器能够为您的应用程序组件的有效性提供合理确定性的唯一方法。

然而,Blazor并不是ASP.NET核心框架中发生这种情况的唯一部分。例如,ASP.NET MVC控制器默认情况下不会在容器中注册,也不会从容器中解析。虽然这是可配置的,但由于这不是默认行为,ValidateOnBuild会给人一种虚假的安全感。

其他容器可能有一个更合理的默认值。例如,SimpleInjector(我维护的容器(包含始终预先注册所有MVC控制器的扩展方法。随着Blazor集成,类似的事情也会发生。

如果您坚持使用内置容器,那么最好确保从容器中解析所有组件。使用MVC,这很容易,因为您可以简单地调用AddControllersAsServices。不幸的是,对于Blazor,这要困难得多,因为不存在AddComponentsAsServices这样的方法。这意味着您必须创建一个调用回容器的自定义IComponentActivator。但是,对于Microsoft创建的所有Blazor组件,您可能不得不使用Activator.CreateInstance返回到原始行为,因为使用反射可能更难找到和注册它们。有关如何创建此类自定义组件激活器并注册应用程序Blazor组件的灵感,请查看此处提供的代码。

最新更新