#c# #asp.net-core #modelstate #model-validation
#c# #asp.net-core #modelstate #проверка модели
Вопрос:
Я ищу способ добавить код ошибки вместе с сообщением об ошибке в ModelState
. например
ModelState.AddModelError("ErrorKey", new { Code = 4001, Message = "Some error message" });
Для некоторых плохих запросов клиент должен выполнить действие, и сравнение сообщения об ошибке не является идеальным решением для принятия решения. ModelState.AddModelError
метод принимает только два параметра, ключ ошибки и сообщение. Есть ли способ добиться этого или чего-то подобного?
Ответ №1:
Нет, в вашем коде нет способа достичь того, что вы ищете, когда вы пытаетесь сделать что-то подобное:
return BadRequest(ModelState);
Вы получите 400 bad request
ответ с сообщением, которое вы уже добавили (как вы можете видеть, код ошибки уже был представлен здесь). Итак, в вашем случае нет ни использования, ни способа добавления кода ошибки.
Ответ №2:
Я нашел способ добавить код ошибки в ValidationProblemDetails
:
public class CustomValidationProblemDetails : ValidationProblemDetails
{
public CustomValidationProblemDetails()
{
}
[JsonPropertyName("errors")]
public new IEnumerable<ValidationError> Errors { get; } = new List<ValidationError>();
}
ValidationProblemDetails
имеет свойство Error, которое есть IDictionary<string, string[]>
, и замените это свойство нашей версией, чтобы добавить ошибку кода.
public class ValidationError
{
public int Code { get; set; }
public string Message { get; set; }
}
Конструктор ValidationProblemDetails
принимает ModelStateDictionary и должен преобразовать его в список ValidationError
:
public CustomValidationProblemDetails(IEnumerable<ValidationError> errors)
{
Errors = errors;
}
public CustomValidationProblemDetails(ModelStateDictionary modelState)
{
Errors = ConvertModelStateErrorsToValidationErrors(modelState);
}
private List<ValidationError> ConvertModelStateErrorsToValidationErrors(ModelStateDictionary modelStateDictionary)
{
List<ValidationError> validationErrors = new();
foreach (var keyModelStatePair in modelStateDictionary)
{
var errors = keyModelStatePair.Value.Errors;
switch (errors.Count)
{
case 0:
continue;
case 1:
validationErrors.Add(new ValidationError { Code = 100, Message = errors[0].ErrorMessage });
break;
default:
var errorMessage = string.Join(Environment.NewLine, errors.Select(e => e.ErrorMessage));
validationErrors.Add(new ValidationError { Message = errorMessage });
break;
}
}
return validationErrors;
}
Создайте пользовательский ProblemDetailsFactory для создания пользовательских validationproblemdetails, когда мы хотим вернуть неверный ответ на запрос:
public class CustomProblemDetailsFactory : ProblemDetailsFactory
{
public override ProblemDetails CreateProblemDetails(HttpContext httpContext, int? statusCode = null, string title = null,
string type = null, string detail = null, string instance = null)
{
var problemDetails = new ProblemDetails
{
Status = statusCode,
Title = title,
Type = type,
Detail = detail,
Instance = instance,
};
return problemDetails;
}
public override ValidationProblemDetails CreateValidationProblemDetails(HttpContext httpContext,
ModelStateDictionary modelStateDictionary, int? statusCode = null, string title = null, string type = null,
string detail = null, string instance = null)
{
statusCode ??= 400;
type ??= "https://tools.ietf.org/html/rfc7231#section-6.5.1";
instance ??= httpContext.Request.Path;
var problemDetails = new CustomValidationProblemDetails(modelStateDictionary)
{
Status = statusCode,
Type = type,
Instance = instance
};
if (title != null)
{
// For validation problem details, don't overwrite the default title with null.
problemDetails.Title = title;
}
var traceId = Activity.Current?.Id ?? httpContext?.TraceIdentifier;
if (traceId != null)
{
problemDetails.Extensions["traceId"] = traceId;
}
return problemDetails;
}
}
И в конце зарегистрировать фабрику:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddTransient<ProblemDetailsFactory, CustomProblemDetailsFactory>();
}
Прочитайте Расширяющиеся ProblemDetails — Добавьте код ошибки в ValidationProblemDetails для получения более подробной информации.