Jeer
@Jeer
уверенный пользователь

Как переопределить встроенную валидацию в конвейер обработки запроса .net core?

Добрый день,
В .net core апи контроллер наследуется от ControllerBase и ему добавляется атрибут [ApiController] который содержит в себе какой-то готовый функционал.
Но при этом валидация уже встроена в конвейер обработки запроса. Я хотел бы по прежнему пользоваться атрибутом [ApiController] но использовать свой обработчик валидации (например, возвращать 422 код ошибки вместо 400)

[Route("api/[controller]/[action]")]
[AllowAnonymous]
[ApiController]
public class AuthController : ControllerBase
{
    private readonly IAuthService service;

    public AuthController(IAuthService service)
    {
        this.service = service;
    }

    [HttpPost]
    [Produces(typeof(UserDto))]
    public async Task<IActionResult> LogIn([FromBody] LoginDto model)
    {
            var user = await service.LogIn(model);
            await SignInAsync(user);

            return Ok(user);
    }
}

public class LoginDto
    {
        [Required]
        public string Login { get; set; }

        [Required]
        public string Password { get; set; }
    }


Таким образом, если я вызову метод LogIn, но в модели LoginDto не будет заполнено поле Login - мне в ответ вернётся такой результат:

{
"type":"https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title":"One or more validation errors occurred.",
"status":400,
"traceId":"00-a0b13ea44a9cb5250a7f22771528056d-e04f1f934fc804a6-00",
"errors":{"Login":["The Login field is required."]}
}

То есть тут непонятная мне модель, непонятные поля и это даже не просто ModelStateDictionary.

Я не нашел в доках как можно переопределить валидацию в конвейере апи контроллера, помогите, пожалуйста
  • Вопрос задан
  • 588 просмотров
Решения вопроса 1
Jeer
@Jeer Автор вопроса
уверенный пользователь
Нашел самостоятельно ответ,
Речь идёт про автоматический ответ, если в запросе невалидная модель https://docs.microsoft.com/en-us/aspnet/core/web-a...
И там же ниже показано, как убрать этот обработчик:
https://docs.microsoft.com/en-us/aspnet/core/web-a...
builder.Services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true; // вот это
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
            "https://httpstatuses.com/404";
    });
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
NikFaraday
@NikFaraday
Student full-stack Developer
Что-то рано вы перешли к web api )
Лично я использую FluentValidation API (Не путать с Fluent Validator), который вы можете установить через NuGet и посмотреть на офф.сайте, как правильно настроить, буквально до часа работы займёт.
Та же можно использовать стандартное свойство Model внутри контроллера и из него свойство IsValid для валидации модели либо отдельно проверять каждое свойство/поле на какое-то конкретное значение (== null, is null, String.IsEmpty(...)) и возвращать соответствующий сетевой код, для примера, в вашем случае, можно сделать return BadRequest( new { response = "Some fields is empty });
BadRequest относится к типам, которые доступны по стандарту и в asp.net имеют соответствующие значения сетевых кодов. Вы используете в примере Ok, т.е. сетевой код 200.
Ещё попробуйте поставить на метод HttpPost - IgnoreAntiforgetToken или как-то так он называется, возможно ошибка в нём (Если об этом не читали и ничего с этим не делали, тогда прям наверняка)
Более подробно можете найти в интернете, направление я вам дал)
Ответ написан
@oleg_ods
Если хотите сделать сообщения об ошибке однотипными можно написать свой ValidationFilter. Что то вроде того как предлагают здесь.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы