c# - FluentValidation 命令验证器未由 AutoFac 注册

标签 c# asp.net-core domain-driven-design autofac fluentvalidation

我已经被一个问题困扰了一段时间。我正在构建一个基于 eShopOnContainers GitHub 项目 See Here 的项目。我的项目正在 asp.net core 2.2 上运行,我正在使用

MediatR 6.0,

  • MediatR 6.0
  • MediatR.Extensions.Microsoft.DependencyInjection 6.0.1
  • FluentValidation.AspNetCore 8.1.2
  • Autofac.Extensions.DependencyInjection 4.3.1

我正在使用由命令处理程序处理的 MediatR 命令,通过许多文章以及在线 eShopOnContainers 示例,我已经实现了 ValidatorBehavior实现 IPipelineBehavior 的类.

public class ValidatorBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
    where TRequest : IRequest<TResponse>
{
    private readonly IEnumerable<IValidator<TRequest>> _validators;

    public ValidatorBehavior(IEnumerable<IValidator<TRequest>> validators)
    {
        _validators = validators;
    }

    public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
    {
        var context = new ValidationContext(request);
        var failures = _validators
            .Select(v => v.Validate(context))
            .SelectMany(result => result.Errors)
            .Where(error => error != null)
            .ToList();

        if (failures.Any())
        {
            throw new PlanningDomainException(
                $"Command Validation Errors for type {typeof(TRequest).Name}", new ValidationException("Validation exception", failures));
        }

        var response = await next();
        return response;
    }
}

我还包含了一个 MediatorModule,就像在示例项目中实现的那样。

public class MediatorModule : Autofac.Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterAssemblyTypes(typeof(IMediator).GetType().Assembly)
            .AsImplementedInterfaces();

        // Get the assembly name
        var assembly = typeof(Startup).GetType().Assembly;

        // Register all the Command classes (they implement IRequestHandler) in assembly holding the Commands
        builder.RegisterAssemblyTypes(assembly)
            .AsClosedTypesOf(typeof(IRequestHandler<,>));

        // Register the DomainEventHandler classes (they implement INotificationHandler<>) 
        // in assembly holding the Domain Events
        builder.RegisterAssemblyTypes(assembly)
            .AsClosedTypesOf(typeof(INotificationHandler<>));

        // Register the Command's Validators (Validators based on FluentValidation library)
        builder.RegisterAssemblyTypes(assembly)
            .Where(t => t.IsClosedTypeOf(typeof(IValidator<>)))
            .AsImplementedInterfaces();

        builder.Register<ServiceFactory>(context =>
        {
            var componentContext = context.Resolve<IComponentContext>();
            return t => { object o; return componentContext.TryResolve(t, out o) ? o : null; };
        });

        builder.RegisterGeneric(typeof(LoggingBehavior<,>)).As(typeof(IPipelineBehavior<,>));
        builder.RegisterGeneric(typeof(ValidatorBehavior<,>)).As(typeof(IPipelineBehavior<,>));
        builder.RegisterGeneric(typeof(TransactionBehaviour<,>)).As(typeof(IPipelineBehavior<,>));

    }
}

我的测试 Controller 是:

[Route("api/[controller]")]
[ApiController]
public class ApplicationsController : ControllerBase
{
    private readonly IMediator _mediator;

    public ApplicationsController(IMediator mediator)
    {
        _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
    }

    [HttpPost]
    [ProducesResponseType((int)HttpStatusCode.OK)]
    [ProducesResponseType((int)HttpStatusCode.BadRequest)]
    public async Task<IActionResult> Put([FromBody]ApplicationCreateCommand command, [FromHeader(Name = "x-requestid")] string requestId)
    {
        var c = await _mediator.Send(command);
        return c ? Ok() : (IActionResult)BadRequest();
    }
}

我有以下问题:

  1. 每当我尝试调用此 API 时,都会收到以下错误:

    无法解析构造函数“Void .ctor(MediatR.IMediator)”的参数“MediatR.IMediator mediator”。

我通过使用.AddMediatR()添加中介作为服务来解决这个问题即使在示例项目中它从未像这样添加。

  • 添加 mediatr 后,API 就会正确运行,并且正在发送命令,并且处理的命令正在正确处理。同时,ValidatorBehavior 正在正确调用,但 CommandValidator 不存在。 _validators列表实际上是空的,因此没有进行任何验证。
  • 我还在命令验证器中设置了断点,但没有被击中。

    这是我的命令验证器:

    public class ApplicationCreateCommandValidator : AbstractValidator<ApplicationCreateCommand>
    {
        public ApplicationCreateCommandValidator()
        {
            RuleFor(cmd => cmd.CategoryType).NotEmpty().Must(BeValidCategoryType).WithMessage("The category type is not valid.");
            RuleFor(cmd => cmd.CompetitionId).NotEmpty().WithMessage("The competition id must be specified.");
            RuleFor(cmd => cmd.ParticipantId).NotEmpty().WithMessage("The participant id must be specified.");
        }
    
        private bool BeValidCategoryType(int categoryType)
        {
            return categoryType != 0;
        }
    }
    

    一切都应该正常!我不明白为什么它不会。也许我没有在 autofac 中正确加载命令验证器,但是,我在网上找到的每个示例代码都指向相同的注册方法:

    builder.RegisterAssemblyTypes(assembly)
                .Where(t => t.IsClosedTypeOf(typeof(IValidator<>)))
                .AsImplementedInterfaces();
    

    如果您想仔细查看,我的 git hub 帐户上有该项目的完整源代码。 This is the API

    任何人都可以帮助我理解我做错了什么吗?这几天我都快疯了。

    最佳答案

    我的配置和你的差不多。我能找到的唯一区别是 start.cs 文件中的以下几行

    public IServiceProvider ConfigureServices(IServiceCollection services)
            {
                services.AddMvc()
                    .AddFluentValidation(fv =>
                    {
                        fv.RegisterValidatorsFromAssemblyContaining<MediatorModule>();
                        fv.RunDefaultMvcValidationAfterFluentValidationExecutes = false;
                    }
                );
    }
    

    关于c# - FluentValidation 命令验证器未由 AutoFac 注册,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54272950/

    相关文章:

    c# - 如何在 Xamarin.iOS 中从 URL 加载图像

    c# - 针对 10240 的 UWP 应用中的辅助 View 中未调用卸载事件

    asp.net-core - 使用库中的可配置路径映射 Controller 路由

    .net - http://localhost:xxxx/api/values 无法在 .net core 2.2 中加载页面

    c# - 告诉 Swashbuckle 只查找具有 ApiControllerAttribute 的 Controller

    c# - 如何在单个字段中存储值对象的集合而不在 EF Core 中创建新表

    domain-driven-design - 在 DDD 中,命令是严格同步的 API 调用吗?

    c# - 当任何数学运算在 .net 4 中产生 'NaN' 时,如何强制 C# 编译器抛出异常?

    c# - c# 中 [Serializable] 和 [Serializable()] 之间有区别吗?

    design-patterns - 聚合内部的实体能否在聚合外部访问或可见?