In order for that to work with out of the box validation support nicely, I created my own action selector which makes it possible to bind URI parameters to complex type objects without duplication.
So, you can do the following with this action selector:
public class CarsByCategoryRequestCommand {
public int CategoryId { get; set; }
public int Page { get; set; }
[Range(1, 50)]
public int Take { get; set; }
}
public class CarsByColorRequestCommand {
public int ColorId { get; set; }
public int Page { get; set; }
[Range(1, 50)]
public int Take { get; set; }
}
[InvalidModelStateFilter]
public class CarsController : ApiController {
public string[] GetCarsByCategoryId(
[FromUri]CarsByCategoryRequestCommand cmd) {
return new[] {
"Car 1",
"Car 2",
"Car 3"
};
}
public string[] GetCarsByColorId(
[FromUri]CarsByColorRequestCommand cmd) {
return new[] {
"Car 1",
"Car 2"
};
}
}
Then, you can register an action filter to validate the user inputs to terminate request and return back a "400 Bad Request" response along with the validation error messages:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class InvalidModelStateFilterAttribute : ActionFilterAttribute {
public override void OnActionExecuting(HttpActionContext actionContext) {
if (!actionContext.ModelState.IsValid) {
actionContext.Response = actionContext.Request.CreateErrorResponse(
HttpStatusCode.BadRequest, actionContext.ModelState);
}
}
}
Check out the below posts for more information about this action selector and how you can get it: