Веб-API ASP.NET Core 8.0 — мой controller выглядит так:
[HttpGet("teacher/{source}/{id}"]
public async Task<ActionResult<Teacher?>> GetTeacher(TeacherEnumSource source, string id)
{
var result = await _teacherData.GetTeacher(source, id);
return result == null ? StatusCode(404, $"No Teacher found for Source: {source} and ID: {id}") : Ok(result);
}
Обратите внимание, что параметр source — это enum:
public enum TeacherEnumSource
{
SCHOOL,
UNIVERSITY,
KINDERGARTEN
}
Если я передам неверный параметр своему API в качестве источника, которого нет в списке enum, я автоматически получаю эту ошибку, что довольно приятно:
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"source": [
"The value 'camping' is not valid."
]
},
"traceId": "00-4e2baa0235572f8359e0e15225fffd3e-4ccac5f22f8ede03-00"
}
Если я ставлю точки останова, строка _teacherData.GetTeacher(source, id) даже не запускается, поэтому нет необходимости показывать этот код.
Я еще не добавил обработку ошибок и даже закомментировал эти две строки из своего program.cs, чтобы убедиться:
//app.UseStatusCodePages();
//app.UseExceptionHandler();
Итак, кто делает за меня эту обработку ошибок и, что более важно: как я могу ее немного настроить, потому что я действительно хочу ЗАРЕГИСТРИРОВАТЬ этот инцидент на своем внешнем регистраторе (в моем случае DataDog).
Отвечает ли это на ваш вопрос? Как заставить «Произошла одна или несколько ошибок проверки» вызывать исключение?
Сама платформа обрабатывает проверку и ошибку. Он пытается привести значения, заданные в качестве параметра, к типу, ожидаемому вашим действием, но это не удается.
Нашел сам. Это делала строка [ApiController] в верхней части класса.
ApiControllerAttribute делает немного больше (см. документацию). А проверка выполняется связующим AFAIK.





Вам следует выбрать использование
Смоделируйте и используйте валидатор модели (сообщение не получено)
Вручную проверьте значение перечисления, чтобы проверить, является ли значение допустимым.
Подтвердите свой маршрут, используя ограничение маршрута:
public class RangeConstraint : IRouteConstraint
{
private readonly int _min;
private readonly int _max;
public RangeConstraint(int min, int max)
{
_min = min;
_max = max;
}
public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
{
if (values.TryGetValue(routeKey, out var value) && int.TryParse(value.ToString(), out int intValue))
{
return intValue >= _min && intValue <= _max;
}
return false;
}
}
и интегрировать его, используя:
services.Configure<RouteOptions>(options =>
{
options.ConstraintMap.Add("range", typeof(RangeConstraint));
});
Спасибо, значит подход 2 не является плохой практикой? Мне нужно, чтобы они были GET . Итак, я выполнил ручную проверку в контроллере, чтобы проверить, находится ли значение в моем списке перечислений, целое число является реальным int и т. д., так что это тоже нормально, если я сделаю это таким образом?
@Бон, все, что ты делаешь, хорошо. Чем проще решение, тем лучше. ;-)