Search code examples
c#asp.net-corecustom-attributesvalidationattribute

ASP.NET Core Custom Validation Attribute Not Firing


I have a GET method in API Controller. I would like that method to be validated using custom validation attribute as below. However it's not getting fired for some reasons.

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
    public class CheckValidRoute : ValidationAttribute
    {
        private readonly string _apiRoute;
        private readonly string _operation;

        public override bool RequiresValidationContext { get { return true; } }

        public CheckValidRoute(string apiRoute, string operation)
        {
            _apiRoute = apiRoute;
            _operation = operation;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
           //Validation logic here
        }
    }

Controller

public class TestController : ControllerBase
    {
        [HttpGet("production/{movieId}/Test")]
        [ProducesResponseType(typeof(ResponseModel<string>), 200)]
        [Authorize(Policy = SecurityConstants.PseudofilmAuthorizationPolicy)]
        [CheckValidRoute("production/{movieId}/Test", "GET")]
        public async Task<ResponseModel<string>> TestGet(long movieId)
        {
            return ResponseModelHelper.BuildResponse("Success", $"production/{movieId}/Test", "Test");
        }
    }

I am not sure what I am missing here.

-Alan-


Solution

  • You are using the wrong base class to implement your attribute. ValidationAttribute is used on Models to validate their property values. An example of this is the Required attribute.

    In your case you want to implement an ActionFilter, which can be applied to a controller method and can perform validation before the method is called. An example for you would be:

    public class CheckValidRouteAttribute : ActionFilterAttribute
    {
        private readonly string _apiRoute;
        private readonly string _operation;
    
        public CheckValidRouteAttribute(string apiRoute, string operation) : base()
        {
            _apiRoute = apiRoute;
            _operation = operation;
        }
    
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            var request = context.HttpContext.Request;
    
            var method = request.Method;
    
            if (string.Compare(method, _operation, true) != 0)
            {
                context.Result = new BadRequestObjectResult("HttpMethod did not match");
            }
        }
    }
    

    In the OnActionExecuting method you can perform your checks against the HttpContext.Request object. I have left that as an exercise for you as I don't know your exact requirements :-)

    After applying this attribute to your controller method, the OnActionExecuting will be called before the controller method is called so you can do your validation.

    You can read more about ActionFilters here