Using ASP.NET Core 1.1 with VS2015 (sdk 1.0.0-preview2-003131), I have the following controller:
public class QueryParameters { public int A { get; set; } public int B { get; set; } } [Route("api/[controller]")] public class ValuesController : Controller { // GET api/values [HttpGet] public IEnumerable<string> Get([FromQuery]QueryParameters parameters) { return new [] { parameters.A.ToString(), parameters.B.ToString() }; } }
As you can see, I have two query parameters. What I would like is to have one of them (ex: A
) to be required. That is, I would like to use an attribute (if possible) to say that this attribute is required. Then, I would like like ASP.NET to do this validation before even calling my controller.
I would have liked to use the Newtonsoft RequiredAttribute to use the same attributes as I already use to validate the required properties in the PUT/POST content, but since the url is not a JSON string, it is obviously not used.
Any suggestion to have ASP.NET Core automatically check for required query parameters?
Note that I know that I can code the check myself using nullable query parameters but that beats the purpose of letting ASP.NET do the validation before calling my controller, thus keeping my controller tidy.
The first solution to make query string parameters mandatory is to use Model Binding on the public properties of a class. We make the Number property mandatory by using the [BindRequired] attribute.
[FromQuery] - Gets values from the query string. [FromRoute] - Gets values from route data. [FromForm] - Gets values from posted form fields. [FromBody] - Gets values from the request body.
Yes, mandatory parameters can be used in query parameters. In that case you need to put a validation after the API is hit to check whether the value of the parameter is not null and is of specified format.
In ASP.NET Core 2.1 and above you can use top level parameters validation. You can put attributes on parameters
[HttpGet] public IActionResult GetDices([BindRequired, Range(1, 6)]int number) { if (!ModelState.IsValid) { return BadRequest("Invalid number"); } return Ok(_diceRepo.GetDices(number)); }
More about this https://programmingcsharp.com/asp-net-parameter-validation/#Top-level_node_validation
You can consider using the model binding feature of the framework
According to documentation here: Customize model binding behavior with attributes
MVC contains several attributes that you can use to direct its default model binding behavior to a different source. For example, you can specify whether binding is required for a property, or if it should never happen at all by using the
[BindRequired]
or[BindNever]
attributes.
So I suggest you add a BindRequiredAttribute
to the model property.
public class QueryParameters { [BindRequired] public int A { get; set; } public int B { get; set; } }
From there the framework should be able to handle the binding and updating model state so that you can check the state of the model in the action
[Route("api/[controller]")] public class ValuesController : Controller { // GET api/values [HttpGet] public IActionResult Get([FromQuery]QueryParameters parameters) { if (ModelState.IsValid) { return Ok(new [] { parameters.A.ToString(), parameters.B.ToString() }); } return BadRequest(); } }
The other option would be to create a custom model binder that would fault the action if the required query string is not present.
Reference: Custom Model Binding
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With