【问题标题】:Conditional validation based on request route with asp.net core 2.2 and FluentValidation基于请求路由的条件验证与 asp.net core 2.2 和 FluentValidation
【发布时间】:2019-07-22 21:11:05
【问题描述】:

所以基本上我用 FluentValidation 为我的类编写了一个验证器,还用一个过滤器在我的 webAPI 项目中为我完成了验证任务,到目前为止还可以,但假设我的 User 类具有名字、姓氏、电子邮件、密码属性 我有两条路线(一条用于注册,另一条用于登录) 并且您可能已经注意到,这些路由所需的属性不同。

因此,我是否真的需要为我拥有的每一个操作编写单独的验证?因为这会导致大量代码重复并且很难更改。有没有办法根据即将到来的请求添加所需的条件单一验证类? 有什么建议???

【问题讨论】:

    标签: asp.net-core-mvc fluentvalidation asp.net-core-2.2


    【解决方案1】:

    更好的做法是使用工厂模式进行验证,并使用操作过滤器来缩短错误请求。您可以使用类似的方式验证任何操作参数(标头、请求正文等)。

    public class TestValidationAttribute : Attribute, IActionFilter
    {
        private string _requestModelName;
    
        public TestValidationAttribute(string requestModelName)
        {
            _requestModelName = requestModelName;
        }
    
        public void OnActionExecuting(ActionExecutingContext context)
        {
            // using Microsoft.Extensions.DependencyInjection;
            var services = context.HttpContext.RequestServices;
            var accessor = services.GetService<IHttpContextAccessor>();
            var factory = services.GetService<ITestValidatorFactory>();
    
            var tokens = accessor.HttpContext.GetRouteData().DataTokens;
            if (!tokens.TryGetValue("RouteName", out var routeNameObj))
            {
                throw new Exception($"Action doesn't have a named route.");
            }
            var routeName = routeNameObj.ToString();
    
            var validator = factory.Create(routeName);
            if (!context.ActionArguments.TryGetValue(_requestModelName, out var model))
            {
                throw new Exception($"Action doesn't have argument named {_requestModelName}.");
            }
    
            TestModel test;
            try
            {
                test = (TestModel) model;
            }
            catch (InvalidCastException)
            {
                throw new Exception($"Action argument can't be casted to {nameof(TestModel)}.");
            }
    
            var validation = validator.Validate(test);
            if (!validation.Successful)
            {
                context.Result = new BadRequestObjectResult(validation.ResponseModel);
            }
        }
    
        public void OnActionExecuted(ActionExecutedContext context)
        {
        }
    }
    
    public class TestController : Controller
    {
        [HttpPost]
        [Route("Test/{id}", Name = "TestGet")]
        [TestValidation("model")]
        public IActionResult Test(TestModel model)
        {
            return Ok();
        }
    }
    
    public class ValidationResult
    {
        public bool Successful { get; }
        public ResponseModel ResponseModel { get; }
    }
    
    public class TestModel
    {
    }
    
    public interface ITestValidator
    {
        ValidationResult Validate(TestModel model);
    }
    
    public interface ITestValidatorFactory
    {
        ITestValidator Create(string routeName);
    } 
    

    【讨论】:

    • 完美运行,谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-27
    • 2019-08-03
    • 1970-01-01
    • 2021-08-28
    • 1970-01-01
    • 1970-01-01
    • 2018-08-28
    相关资源
    最近更新 更多