Is it possible to validate query parameters on an action without using a model? A lot of the calls in my API are one-offs and I don't see a point in making models for them if they will only be used one time.
I saw the following article, which seemed like it was exactly what I needed, except I don't want it to return a 404 if the required parm doesn't exist, I want it to return an object of error messages similar to the baked in model validation - really, I just want the parameters to be treated like a model, without actually having to make a model.
https://www.strathweb.com/2016/09/required-query-string-parameters-in-asp-net-core-mvc/
[HttpPost]
public async Task<IActionResult> Post(
[FromQueryRequired] int? Id,
[FromQuery] string Company)
EDIT:
The [FromQueryRequired] is a custom ActionConstraint that throws a 404 if the ID parm is missing (this was taken directly from the article). However I don't want the 404, I want an object that has a message that says {MESSAGE: "ID is required"}. I think the issue is that i can't access the Response context from within an Action Constraint.
[FromQuery] - Gets values from the query string. [FromRoute] - Gets values from route data.
You need to check whether the submitted data is valid or not in the controller. In other words, you need to check the model state. Use the ModelState. IsValid to check whether the submitted model object satisfies the requirement specified by all the data annotation attributes.
Here is the solution I ended up using. Add an Attribute to the parms named [RequiredParm]. I loosely based it on someone else's answer for a different question, but I can't seem to find it at the moment, apologies to whoever you are, if I can find it I'll update this answer for credit.
EDIT: Found it, answered by @James Law - Web Api Required Parameter
Usage:
[HttpPost]
public async Task<IActionResult> Post(
[FromQuery, RequiredParm] int? Id,
[FromQuery] string Company)
ActionFilterAttribute:
[AttributeUsage(AttributeTargets.Method)]
public sealed class CheckRequiredParmAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
var requiredParameters = context.ActionDescriptor.Parameters.Where(
p => ((ControllerParameterDescriptor)p).ParameterInfo.GetCustomAttribute<RequiredParmAttribute>() != null).Select(p => p.Name);
foreach (var parameter in requiredParameters)
{
if (!context.ActionArguments.ContainsKey(parameter))
{
context.ModelState.AddModelError(parameter, $"The required argument '{parameter}' was not found.");
}
else
{
foreach (var argument in context.ActionArguments.Where(a => parameter.Equals(a.Key)))
{
if (argument.Value == null)
{
context.ModelState.AddModelError(argument.Key, $"The requried argument '{argument.Key}' cannot be null.");
}
}
}
}
if (!context.ModelState.IsValid)
{
context.Result = new BadRequestObjectResult(context.ModelState);
return;
}
base.OnActionExecuting(context);
}
}
/// <summary>
/// Use this attribute to force a [FromQuery] parameter to be required. If it is missing, or has a null value, model state validation will be executed and returned throught the response.
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public sealed class RequiredParmAttribute : Attribute
{
}
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