问题
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.
回答1:
From Asp.Net Core 2.1 there is a built-in parameter [BindRequired] which is doing this validation automatically.
public async Task<ActionResult<string>> CleanStatusesAsync([BindRequired,
FromQuery]string collection, [BindRequired, FromQuery]string repository,
[BindRequired, FromQuery]int pullRequestId)
{
// all parameters are bound and valid
}
If you are calling this method without parameters, a ModelState error is returned:
{
"collection": [
"A value for the 'collection' parameter or property was not provided."
],
"repository": [
"A value for the 'repository' parameter or property was not provided."
],
"pullRequestId": [
"A value for the 'pullRequestId' parameter or property was not provided."
],
}
More details you can find in this excellent article.
回答2:
You can read from request and validate it
string id= HttpContext.Request.Query["Id"].ToString();
if (id==nll)
{
//do any thing here
}
回答3:
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
{
}
回答4:
i haven't tried yet may be like that;
public class MyActionFilterAttribute: IActionFilter
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
var id = actionContext.ActionArguments["Id"];
if(string.IsNullOrEmpty(id))
actionContext.Response = actionContext.Request.CreateResponse(
HttpStatusCode.OK,
new {MESSAGE = "ID is required"},
actionContext.ControllerContext.Configuration.Formatters.JsonFormatter
);
}
}
[HttpPost]
[MyActionFilterAttribute]
public ActionResult Post([FromQueryRequired] int? Id,[FromQuery] string Company)
来源:https://stackoverflow.com/questions/52977418/validate-query-parameters-without-using-a-model-in-netcore-api