英文:
.NET Core 7 Minimal API MediatR IRequest Handler mapping error
问题
以下是您提供的信息的中文翻译:
我在使用.NET Core 7 Minimal API执行命令时遇到以下错误:
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
执行请求时发生未处理的异常。
System.InvalidOperationException:构造处理程序时出错,类型为MediatR.IRequestHandler`2[mNet.FileServer.Commands.Core.Application.Features.StoredFileTypes.NewStoredFileType.NewStoredFileTypeCommand,mNet.Common.Core.Application.Commands.BaseCommandResponse`1[mNet.FileServer.Shared.Core.Domain.StoredFileTypes.ValueObjects.StoredFileTypeId]]。请将您的处理程序注册到容器中。请参阅GitHub中的示例。
---> System.InvalidOperationException:尚未注册类型为' MediatR.IRequestHandler`2[mNet.FileServer.Commands.Core.Application.Features.StoredFileTypes.NewStoredFileType.NewStoredFileTypeCommand,mNet.Common.Core.Application.Commands.BaseCommandResponse`1[mNet.FileServer.Shared.Core.Domain.StoredFileTypes.ValueObjects.StoredFileTypeId]]' 的服务。
在Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)中获取所需的服务。
在MediatR.ServiceFactoryExtensions.GetInstance[T](ServiceFactory factory)中获取实例。
在MediatR.Wrappers.HandlerBase.GetHandler[THandler](ServiceFactory factory)中获取处理程序。
--- 内部异常堆栈跟踪的结尾 ---
在MediatR.Wrappers.HandlerBase.GetHandler[THandler](ServiceFactory factory)中获取处理程序。
在MediatR.Wrappers.RequestHandlerWrapperImpl`2.<>c__DisplayClass1_0.<Handle>g__Handler|0()中获取处理程序。
在MediatR.Pipeline.RequestExceptionProcessorBehavior`2.Handle(TRequest request, RequestHandlerDelegate`1 next, CancellationToken cancellationToken)中处理。
在MediatR.Pipeline.RequestExceptionProcessorBehavior`2.Handle(TRequest request, RequestHandlerDelegate`1 next, CancellationToken cancellationToken)中处理。
在MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2.Handle(TRequest request, RequestHandlerDelegate`1 next, CancellationToken cancellationToken)中处理。
在MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2.Handle(TRequest request, RequestHandlerDelegate`1 next, CancellationToken cancellationToken)中处理。
在MediatR.Pipeline.RequestPostProcessorBehavior`2.Handle(TRequest request, RequestHandlerDelegate`1 next, CancellationToken cancellationToken)中处理。
在MediatR.Pipeline.RequestPreProcessorBehavior`2.Handle(TRequest request, RequestHandlerDelegate`1 next, CancellationToken cancellationToken)中处理。
在C:\Users\dcmea\OneDrive\mNet Microservices\mNet.FileServer\mNet.FileServer.Commands.Ui.MinimalApi\Endpoints\StoredFileTypeEndpoint.cs:line 47中的mNet.FileServer.Commands.Ui.MinimalApi.Endpoints.StoredFileTypeEndpoint.NewStoredFileTypeAsync(NewStoredFileTypeDto request, IMediator mediator)中处理。
在Microsoft.AspNetCore.Http.RequestDelegateFactory.<ExecuteTaskOfT>g__ExecuteAwaited|111_0[T](Task`1 task, HttpContext httpContext)中处理。
在Microsoft.AspNetCore.Http.RequestDelegateFactory.<>c__DisplayClass89_2.<<HandleRequestBodyAndCompileRequestDelegateForJson>b__2>d.MoveNext()中处理。
--- 上一个位置的堆栈跟踪的结尾 ---
在Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)中处理。
在Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)中处理。
在Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)中处理。
在Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)中处理。
代码的关键部分位于以下项目中,具体如下:
- mNet.Common.Core.Application:包含
BaseCommand
和BaseCommandResponse
类 - mNet.FileServer.Shared.Core.Domain:包含
StoredFileTypeId
值对象 - mNet.FileServer.Commands.Core.Domain:包含
StoredFileType
聚合 - mNet.FileServer.Commands.Core.Application:包含
NewStoredFileTypeCommand
和NewStoredFileTypeCommandHandler
类 - mNet.FileServer.Commands.Ui.MinimalApi:包含主要的
Program.cs
和最小API端点
关键类包括:
Program.cs(摘录)
builder.Services.AddMediatR(AppDomain.CurrentDomain.GetAssemblies());
Minimal API端点
private static async Task<BaseCommandResponse<StoredFileTypeId>> NewStoredFileTypeAsync(NewStoredFileTypeDto request, IMediator mediator)
{
var messageId = Guid.NewGuid();
var command = new NewStoredFileTypeCommand
{
Id = new MessageId(messageId),
CorrelationId = new CorrelationId(messageId),
CausationId = new CausationId(messageId),
CommandDto = request
};
var response = await mediator.Send(command); //错误发生在这个MediatR调用之后,如错误中引用的第47行
return response;
}
NewStoredFileTypeCommand
public class NewStoredFileTypeCommand : BaseCommand, IRequest<BaseCommandResponse<StoredFileTypeId>>
{
public NewStoredFileTypeDto CommandDto { get; init; } = default!;
}
NewStoredFileTypeCommandHandler
public class NewStoredFileTypeCommandHandler : IRequestHandler<NewStoredFileTypeCommand, BaseCommandResponse<StoredFileTypeId>>
{
private readonly IMapper _mapper;
private readonly IEventSourcingHandler<StoredFileType, StoredFileTypeId> _eventSourcingHandler;
public NewStoredFileTypeCommandHandler(IMapper mapper,
IEventSourcingHandler<StoredFileType, StoredFileTypeId> eventSourcingHandler)
{
_mapper = mapper;
_eventSourcingHandler = eventSourcingHandler;
}
public async Task<BaseCommandResponse<StoredFileTypeId>> Handle(NewStoredFileTypeCommand request, CancellationToken cancellationToken)
{
var response = new BaseCommandResponse<StoredFileTypeId>();
var aggregate = new StoredFileType(
new StoredFileTypeId(Guid.NewGuid()),
request.CorrelationId,
new CausationId(request.Id.Id),
request.CommandDto.Name,
request.CommandDto.IsImageFileType,
_mapper.Map<BootstrapIconCode>(request.CommandDto.BootstrapIconCode),
_mapper.Map<MimeType>(request.CommandDto.MimeType)
);
await _eventSourcingHandler.SaveAsync(aggregate);
response.Id = aggregate.Id;
response.Message = "创建了新的StoredFileType聚合!";
response.IsSuccessful = true;
return response;
}
通过一些调试追踪,
英文:
I am currently getting the following error when executing a command via .NET Core 7 Minimal API:
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
System.InvalidOperationException: Error constructing handler for request of type MediatR.IRequestHandler`2[mNet.FileServer.Commands.Core.Application.Features.
StoredFileTypes.NewStoredFileType.NewStoredFileTypeCommand,mNet.Common.Core.Application.Commands.BaseCommandResponse`1[mNet.FileServer.Shared.Core.Domain.StoredFile
Types.ValueObjects.StoredFileTypeId]]. Register your handlers with the container. See the samples in GitHub for examples.
---> System.InvalidOperationException: No service for type 'MediatR.IRequestHandler`2[mNet.FileServer.Commands.Core.Application.Features.StoredFileTypes.NewS
toredFileType.NewStoredFileTypeCommand,mNet.Common.Core.Application.Commands.BaseCommandResponse`1[mNet.FileServer.Shared.Core.Domain.StoredFileTypes.ValueObjects.S
toredFileTypeId]]' has been registered.
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at MediatR.ServiceFactoryExtensions.GetInstance[T](ServiceFactory factory)
at MediatR.Wrappers.HandlerBase.GetHandler[THandler](ServiceFactory factory)
--- End of inner exception stack trace ---
at MediatR.Wrappers.HandlerBase.GetHandler[THandler](ServiceFactory factory)
at MediatR.Wrappers.RequestHandlerWrapperImpl`2.<>c__DisplayClass1_0.<Handle>g__Handler|0()
at MediatR.Pipeline.RequestExceptionProcessorBehavior`2.Handle(TRequest request, RequestHandlerDelegate`1 next, CancellationToken cancellationToken)
at MediatR.Pipeline.RequestExceptionProcessorBehavior`2.Handle(TRequest request, RequestHandlerDelegate`1 next, CancellationToken cancellationToken)
at MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2.Handle(TRequest request, RequestHandlerDelegate`1 next, CancellationToken cancellationToken)
at MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2.Handle(TRequest request, RequestHandlerDelegate`1 next, CancellationToken cancellationToken)
at MediatR.Pipeline.RequestPostProcessorBehavior`2.Handle(TRequest request, RequestHandlerDelegate`1 next, CancellationToken cancellationToken)
at MediatR.Pipeline.RequestPreProcessorBehavior`2.Handle(TRequest request, RequestHandlerDelegate`1 next, CancellationToken cancellationToken)
at mNet.FileServer.Commands.Ui.MinimalApi.Endpoints.StoredFileTypeEndpoint.NewStoredFileTypeAsync(NewStoredFileTypeDto request, IMediator mediator) in C:\U
sers\dcmea\OneDrive\mNet Microservices\mNet.FileServer\mNet.FileServer.Commands.Ui.MinimalApi\Endpoints\StoredFileTypeEndpoint.cs:line 47
at Microsoft.AspNetCore.Http.RequestDelegateFactory.<ExecuteTaskOfT>g__ExecuteAwaited|111_0[T](Task`1 task, HttpContext httpContext)
at Microsoft.AspNetCore.Http.RequestDelegateFactory.<>c__DisplayClass89_2.<<HandleRequestBodyAndCompileRequestDelegateForJson>b__2>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
The key parts of the code are in the following projects and are as follows:
- mNet.Common.Core.Application: Contains the
BaseCommand
andBaseCommandResponse
classes - mNet.FileServer.Shared.Core.Domain: Contains the
StoredFileTypeId
value object - mNet.FileServer.Commands.Core.Domain: Contains the
StoredFileType
aggregate - mNet.FileServer.Commands.Core.Application: Contains the
NewStoredFileTypeCommand
andNewStoredFileTypeCommandHandler
classes - mNet.FileServer.Commands.Ui.MinimalApi: Contains the main
Program.cs
and minimal api endpoints
The key classes are:
Program.cs (extract)
builder.Services.AddMediatR(AppDomain.CurrentDomain.GetAssemblies());
Minimal Api Endpoint
private static async Task<BaseCommandResponse<StoredFileTypeId>> NewStoredFileTypeAsync(NewStoredFileTypeDto request, IMediator mediator)
{
var messageId = Guid.NewGuid();
var command = new NewStoredFileTypeCommand
{
Id = new MessageId(messageId),
CorrelationId = new CorrelationId(messageId),
CausationId = new CausationId(messageId),
CommandDto = request
};
var response = await mediator.Send(command); //Error happens after this MediatR call and is line 47 as referenced in the error
return response;
}
NewStoredFileTypeCommand
public class NewStoredFileTypeCommand : BaseCommand, IRequest<BaseCommandResponse<StoredFileTypeId>>
{
public NewStoredFileTypeDto CommandDto { get; init; } = default!;
}
NewStoredFileTypeCommandHandler
public class NewStoredFileTypeCommandHandler : IRequestHandler<NewStoredFileTypeCommand, BaseCommandResponse<StoredFileTypeId>>
{
private readonly IMapper _mapper;
private readonly IEventSourcingHandler<StoredFileType, StoredFileTypeId> _eventSourcingHandler;
public NewStoredFileTypeCommandHandler(IMapper mapper,
IEventSourcingHandler<StoredFileType, StoredFileTypeId> eventSourcingHandler)
{
_mapper = mapper;
_eventSourcingHandler = eventSourcingHandler;
}
public async Task<BaseCommandResponse<StoredFileTypeId>> Handle(NewStoredFileTypeCommand request, CancellationToken cancellationToken)
{
var response = new BaseCommandResponse<StoredFileTypeId>();
var aggregate = new StoredFileType(
new StoredFileTypeId(Guid.NewGuid()),
request.CorrelationId,
new CausationId(request.Id.Id),
request.CommandDto.Name,
request.CommandDto.IsImageFileType,
_mapper.Map<BootstrapIconCode>(request.CommandDto.BootstrapIconCode),
_mapper.Map<MimeType>(request.CommandDto.MimeType)
);
await _eventSourcingHandler.SaveAsync(aggregate);
response.Id = aggregate.Id;
response.Message = $"Created new {nameof(StoredFileType)} aggregate!";
response.IsSuccessful = true;
return response;
}
From doing a few debug traces, it seems like MediatR isn't mapping the NewStoredFileTypeCommandHandler
to the NewStoredFileTypeCommand
and I cannot work out why.
Also, as I have declared AppDomain.CurrentDomain.GetAssemblies()
in Program.cs
, it shouldn't be the scope.
Any ideas would be massively appreciated as it's driving me mad!
答案1
得分: 3
我的猜测基于AppDomain.GetAssemblies
文档中的以下引用:
获取已加载到此应用程序域的执行上下文中的程序集。
有可能对应的程序集尚未加载到应用程序域中。尝试使用AddMediatr
并提供包含 Mediatr 组件的程序集/类型:
// 使用每个包含 MediatR 组件的程序集的类型
builder.Services.AddMediatR(typeof(NewStoredFileTypeCommandHandler), typeof(BaseCommand), ...);
英文:
My guess relies on the following quote from the docs for AppDomain.GetAssemblies
:
> Gets the assemblies that have been loaded into the execution context of this application domain.
There is a chance that the corresponding assembly has not yet been loaded into the app domain. Try using the AddMediatr
and providing assemblies/types from the assemblies storing mediatr parts:
// use a type per assembly containing the MediatR components
builder.Services.AddMediatR(typeof(NewStoredFileTypeCommandHandler), typeof(BaseCommand), ...);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论