c# - 如何使用 Fluent Validation 从 ModelState 创建自定义错误响应 dto

我有这个实现流利验证的类。

public class MarketingEventRequestValidator : AbstractValidator<CreateMarketingEventRequest>
{
    public MarketingEventRequestValidator()
    {
        RuleFor(marketingEventRequest => marketingEventRequest.Name).NotNull().NotEmpty();
        RuleFor(marketingEventRequest => marketingEventRequest.EventDate).NotNull().NotEmpty()
            .Must(BeAValidEventDate).WithMessage("Event date must be equal or greater than system date");
        RuleFor(marketingEventRequest => marketingEventRequest.StartTime).NotNull().NotEmpty().Length(4);
        RuleFor(marketingEventRequest => marketingEventRequest.EndTime).NotNull().NotEmpty().Length(4);
    }
    private bool BeAValidEventDate(DateTime date)
    {
        return date < DateTime.Now;
    }
}

这是我的控制器

public async Task<ActionResult> AddMarketingEvent([FromBody] CreateMarketingEventRequest request)
    {
    // code removed for brevity
    }

当我测试它时,它会立即返回如下错误

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "00-e4b8b00b0204bd915763cb7243fdcc60-1646ac57370e44bd-00",
  "errors": {
    "Name": [
      "'' is not in the correct format."
    ],
    "State": [
      "'' is not in the correct format."
    ],
    "Venue": [
      "'' is not in the correct format."
    ],
    "Remark": [
      "'' is not in the correct format."
    ],
    "EndTime": [
      "'' is not in the correct format.",
      "'End Time' must be 4 characters in length. You entered 6 characters."
    ],
    "StartTime": [
      "'' is not in the correct format.",
      "'Start Time' must be 4 characters in length. You entered 6 characters."
    ]
  }
}

但是我想要的错误响应 dto 就在下面

public class ErrorResponse
{
    public string? Errors { get; init; }
    public string? Message { get; init; }
    public int StatusCode { get; init; }
}

样本数据将是

{
  "errors":  {
    "Name": [
      "'' is not in the correct format."
    ],
    "State": [
      "'' is not in the correct format."
    ],
    "Venue": [
      "'' is not in the correct format."
    ],
    "Remark": [
      "'' is not in the correct format."
    ],
    "EndTime": [
      "'' is not in the correct format.",
      "'End Time' must be 4 characters in length. You entered 6 characters."
    ],
    "StartTime": [
      "'' is not in the correct format.",
      "'Start Time' must be 4 characters in length. You entered 6 characters."
    ]
  },
  "message": "Bad request. One or more validation errors occurred.",
  "statusCode": 400
}

如何将 ModelState 映射到此自定义错误类?

我试图通过实现 IAsyncActionFilter 将其放入创建过滤器中。它在某些方面起作用,但如果我这样做,它适用于我不想使用的所有控制器。

原因是因为有许多控制器操作方法只采用一种原始数据类型,即 int id。如果我使用 Fluent Validation,我需要创建一个类。我不想只为 store 一列创建一个类。

回答1

您是否只想通过 Fluent Validation 获得这种响应模型?还是方法没关系?

所以这是我的方法,但是我没有使用“Fluent Validation”,但结果是你想要的,此外我使用它更动态,但我为你简化了,在这种方法中你可以注入 ICustomerError 在你的所需的控制器并调用 CustomError.BadRequestError(ModelState);

所以创建一个 ICustomError 并实现它:

public interface ICustomError
{
    ErrorResponse BadRequestError(ModelStateDictionary modelState);
}


public class CustomError : ICustomError
    {
        private ErrorResponse _errorResponseModel;

        public ErrorResponse BadRequestError(ModelStateDictionary modelState)
        {
            _errorResponseModel = new ErrorResponse();
            var errorFlields = modelState.ToDictionary(
                 kvp => kvp.Key,
                 kvp => kvp.Value.Errors.Select(e => e.ErrorMessage).ToArray()
                );

            _errorResponseModel.Errors = errorFlields;
            _errorResponseModel.Message = "Bad request. One or more validation errors occurred.";
            _errorResponseModel.StatusCode = 400;

            return _errorResponseModel;
        }
    }

这是 ErrorResponse

public class ErrorResponse
    {
        public Dictionary<string, string[]> Errors { get; set; }
        public string Message { get; set; }
        public int StatusCode { get; set; }
    }

最后使用 CreateMarketingEventRequest 的模型验证属性。我希望它有用。

相似文章