Запуск InvalidModelStateResponseFactory, когда ModelState недопустим - PullRequest
0 голосов
/ 13 октября 2019

Я пишу API, используя asp.net core 3.0, и настроил мое приложение следующим образом для всех контроллеров:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers()                    
                .ConfigureApiBehaviorOptions(setupAction =>
                {                        
                    setupAction.InvalidModelStateResponseFactory = context =>
                    {
                        var problemDetails = new ValidationProblemDetails(context.ModelState)
                        {
                            Type = "https://courselibrary.com/modelvalidationproblem",
                            Title = "One or more model validation errors occurred.",
                            Status = StatusCodes.Status422UnprocessableEntity,
                            Detail = "See the errors property for details",
                            Instance = context.HttpContext.Request.Path
                        };

                        problemDetails.Extensions.Add("traceId", context.HttpContext.TraceIdentifier);

                        return new UnprocessableEntityObjectResult(problemDetails)
                        {
                            ContentTypes = { "application/problem+json" }
                        };
                    };
                });
        ...  
    }

Это прекрасно работает с аннотациями данных на моем входе (например: [Required]) свойства класса. Он возвращает ответ 422 Unprocessable Entity, как этот, если какие-либо аннотации терпят неудачу:

{
    "type": "https://courselibrary.com/modelvalidationproblem",
    "title": "One or more model validation errors occurred.",
    "status": 422,
    "detail": "See the errors property for details",
    "instance": "/api/songbooks/21924d66-dac6-43a5-beee-206de4d35216/songs",
    "traceId": "0HLQFGSFIFL5L:00000001",
    "errors": {
        "Title": [
            "The Title field is required."
        ]
    }
}

Однако я реализую FluentValudation в моем контроллере следующим образом:

if (!newSong.IsValid)
{
    newSong.Validate().AddToModelState(ModelState, null);
    _logger.LogWarning("{method} failed model validation (ModelState: {@modelState}), returning Unprocessable Entity", nameof(Post), ModelState.Values.SelectMany(v => v.Errors));
    return UnprocessableEntity(ModelState);                
}

Однако это невызвать InvalidModelStateResponseFactory, как это делает встроенная проверка.

Кто-нибудь знает, как я могу вызвать такое же событие из моего контроллера, чтобы использовать этот удобный обработчик?

1 Ответ

0 голосов
/ 16 октября 2019

На самом деле, есть довольно простой ответ. Вместо того, чтобы возвращать ActionResult из Ok() или BadRequest() или еще что-то, используя этот шаблон ValidationProblem, вы можете просто вернуть ValidationProblem(ModelState), и он будет использовать заводские настройки в Startup.cs конфигурации Api!

Итак, вот что я могу сделать вместо этого:

if (!newSong.IsValid)
{
    newSong.Validate().AddToModelState(ModelState, null);
    _logger.LogWarning("{method} failed model validation (ModelState: {@modelState}), returning Unprocessable Entity", nameof(Post), ModelState.Values.SelectMany(v => v.Errors));
    return ValidationProblem(ModelState);                
}

Кроме того, вам нужно переопределить поведение, чтобы вытащить его из своего стартапа следующим образом (спасибо Кевину Доксу за эту идею):

public override ActionResult ValidationProblem([ActionResultObjectValue] ModelStateDictionary modelStateDictionary)
    {
        var options = HttpContext.RequestServices.GetRequiredService<IOptions<ApiBehaviorOptions>>();
        return (ActionResult)options.Value.InvalidModelStateResponseFactory(ControllerContext);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...