#asp.net-mvc #validation #asp.net-core #asp.net-web-api #modelstate
#asp.net-mvc #проверка #asp.net-core #asp.net-web-api #modelstate
Вопрос:
Asp.net ядро 3.1 WebAPI.
У меня есть модель с требуемыми свойствами.
1. Если модель недопустима, то ответ содержит такие данные, как :
{
"errors": {
"Name": [
"Update model can't have all properties as null."
],
"Color": [
"Update model can't have all properties as null."
]
},
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "|f032f1c9-4c36d1e62aa60ead."
}
И это выглядит хорошо для меня.
Но если я добавлю некоторую пользовательскую проверку в ModelState.AddModelError(«StatusID», «Недопустимый идентификатор статуса заказа».) затем он возвращает другую структуру:
[
{
"childNodes": null,
"children": null,
"key": "statusId",
"subKey": {
"buffer": "statusId",
"offset": 0,
"length": 8,
"value": "statusId",
"hasValue": true
},
"isContainerNode": false,
"rawValue": "11202",
"attemptedValue": "11202",
"errors": [
{
"exception": null,
"errorMessage": "Invalid order status id."
}
],
"validationState": 1
}
]
Также выглядит как ModelState.isValid больше не актуален для контроллера, потому что неверный запрос возвращается еще до того, как он войдет в контроллер с недопустимым режимом. Или есть какой-то флаг с глобальной проверкой через ModelSate?
Почему структура отличается? Как сделать его таким же? Как заставить перейти к ModelState.Метод isValid внутри контроллера api, как он работал в MVC?
Обновить:
[Route("....")]
[Authorize]
[ApiController]
public class StatusesController : ApiControllerBase
{
[HttpPut, Route("{statusId}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
[Produces("application/json")]
public async Task<ObjectResult> UpdateStatusAsync(int statusId, [FromBody] StatusUpdateDto orderStatusUpdateDto)
{
int companyId = User.Identity.GetClaimValue<int>(ClaimTypes.CompanyId);
const string errorNotFound = "There is not order status with this id for such company";
if (statusId <= 0)
{
Logger.LogError(errorNotFound);
ModelState.AddErrorModel(nameof(statusId), "Invalid order status id")
throw new NotFound(ModelState);
}
if (orderStatusUpdateDto == null)
{
const string error = "Invalid (null) order status can't be added";
Logger.LogError(error);
throw new ArgumentNullException(error);
}
if (ModelState.IsValid == false) // also this code is always true or returns 400 before this line
{
return BadRequest(ModelState);
}
....
return resu<
}
}
Комментарии:
1. Где вы добавляете свою ошибку в состояние модели? Внутри метода контроллера? Украшаете ли вы контроллер атрибутом ApiController?
2. Внутри метода контроллера — да украсьте контроллер ApiController — да
3. В дополнение к приведенному ниже ответу treze, вы можете настроить фабрику, используемую для получения результата недопустимой модели
.ConfigureApiBehaviorOptions(o => o.InvalidModelStateResponseFactory = ...)
.
Ответ №1:
ApiController
Атрибут добавляет контроллеру некоторые специфические самоуверенные поведения. Одним из них является возврат ошибки 400, если модель недействительна. Это поведение можно отключить, но только на глобальном уровне.
services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressModelStateInvalidFilter = true;
});
Я думаю, у вас есть следующие варианты:
- Отключите это поведение и проверьте
ModelState.IsValid
себя. ИспользуйтеValidationProblem
метод для получения того же ответа - Добавьте эту проверку в средство проверки модели
- Оставьте все как есть. Но используйте
ValidationProblem
метод внутри контроллера для возврата ошибок проверки.
Смотрите https://docs.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-3.1#automatic-http-400-responses для получения дополнительной информации
Комментарии:
1. Спасибо. Это отвечает на некоторые из моих вопросов. Что вы думаете о другой структуре в возвращаемом результате?
2. Что вы возвращаете как ActionResult при добавлении пользовательской ошибки? Если вы вернете ValidationProblem() , вы должны получить тот же ответ. docs.microsoft.com/en-us/dotnet/api /…
3. Я исправил пример, если я возвращаю BadRequest или NotFound (если id меньше 0) и передаю ModelState в результат в обоих случаях
4. О … похоже, это причина! Как только я возвращаю NotFound — я получаю другую структуру результата, затем я возвращаю BadRequest (ожидаемая структура). Возможно, фабрика проверки имеет конкретную реализацию для плохих запросов и по умолчанию для других…
5. да, как указано в документах, на которые я ссылался в ответе «Чтобы сделать автоматические и пользовательские ответы согласованными, вызовите метод ValidationProblem вместо BadRequest . ValidationProblem возвращает объект ValidationProblemDetails, а также автоматический ответ. »