4

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-

Alan B
  • 2,219
  • 4
  • 32
  • 62
  • Why do you think this code should be fired? You have some filter, that checks for this attribute? Have you read the docs? Also, this should be named `CheckValidRouteAttribute`. – vasily.sib Oct 09 '18 at 03:21
  • The name is something I'd definitely check. Move it above authorize to ensure that's notr getting in the way. https://learn.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-2.1#custom-validation for docs – Steven Mayer Oct 09 '18 at 03:24
  • @StevenMayer, thanks for the link, but title "**Model** validation in ASP.NET Core MVC" doesn't bother you? – vasily.sib Oct 09 '18 at 03:35
  • 1
    I read Net Core Custom Attribute and his code is for that, so provided the code I used for that. I, myself, would probably have looked into using a different filter that ran earlier instead of the custom validation attribute: https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-2.1#resource-filters – Steven Mayer Oct 09 '18 at 03:40

1 Answers1

5

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

Simply Ged
  • 8,250
  • 11
  • 32
  • 40