Consider the following controller action signatures:
[HttpGet]
public IEnumerable<Whatever> Get(DateTime from, DateTime to)
Or
[HttpGet]
public Whatever Get(int amount, SomeUnit unit)
I'd like to be able to run a validation on parameters supplied by the caller. In both cases what passes as valid input in the first parameter depends on the value of second one.
So far I have failed to find an explanation or example of how this can be achieved with validation attributes in ASP.NET Core 3.0
I see that for example CustomValidationAttribute allows using it on methods. I can give it a method that IsValid will delegate to and provide object and validation context:
IsValid(Object, ValidationContext)
I checked documentation of both IsValid and ValidationContext and I cannot find any hint on how would I access the parameters passed to the validated action.
While googling for hints I found an excerpt from "Pro ASP.NET Web API" HTTP Web Services in ASP.NET" where they implement something similar. The excerpt ends however before the code is shown and I don't have that book (didn't find a corresponding book but on ASP.NET Core).
CustomValidationAttribute
is used for properties and parameters. For an action validation you should write your own filter. Here is an example:
public class MyValidationAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
if(context.ModelState.IsValid)
{
var dateFrom = (DateTime)context.ActionArguments["from"];
var dateTo = (DateTime)context.ActionArguments["to"];
if(dateFrom <= dateTo)
{
// continue the flow in pipeline
return;
}
}
context.Result = new BadRequestResult();
}
}
And then you can use it in your controller:
[HttpGet]
[MyValidation]
public IEnumerable<Whatever> Get(DateTime from, DateTime to)
{
// Here ModelState.IsValid is true
}