How to perform async ModelState validation with FluentValidation in Web API?

筅森魡賤 提交于 2020-01-01 12:27:11

问题


I setup a web api project to use FluentValidation using the webapi integration package for FluentValidation. Then I created a validator that uses CustomAsync(...) to run queries against the database.

The issue is that the validation seems to deadlock when awaiting for the database task. I did some investigation, it seems that the MVC ModelState API is synchronous, and it calls a synchronous Validate(...) method that makes FluentValidation to call task.Result, causing the deadlock.

Is it correct to assume that async calls won't work well with webapi integrated validation?

And if that is the case, what is the alternative? WebApi ActionFilters seem to support for async processing. Do I need to build my own filter to handle the validation manually or is there something already there to do that that I'm not seeing?


回答1:


I ended up creating a custom filter and skipped built-in validation entirely:

public class WebApiValidationAttribute : ActionFilterAttribute
{
    public WebApiValidationAttribute(IValidatorFactory factory)
    {
        _factory = factory;
    }

    IValidatorFactory _factory;

    public override async Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
    {
        if (actionContext.ActionArguments.Count > 0)
        {
            var allErrors = new Dictionary<string, object>();

            foreach (var arg in actionContext.ActionArguments)
            {
                // skip null values
                if (arg.Value == null)
                    continue;

                var validator = _factory.GetValidator(arg.Value.GetType());

                // skip objects with no validators
                if (validator == null)
                    continue;

                // validate
                var result = await validator.ValidateAsync(arg.Value);

                // if there are errors, copy to the response dictonary
                if (!result.IsValid)
                {
                    var dict = new Dictionary<string, string>();

                    foreach (var e in result.Errors)
                        dict[e.PropertyName] = e.ErrorMessage;

                    allErrors.Add(arg.Key, dict);
                }
            }

            // if any errors were found, set the response
            if (allErrors.Count > 0)
            {
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.BadRequest, allErrors);
                actionContext.Response.ReasonPhrase = "Validation Error";
            }
        }
    }
}


来源:https://stackoverflow.com/questions/33278845/how-to-perform-async-modelstate-validation-with-fluentvalidation-in-web-api

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!