在.netcore api中不使用模型的情况下验证查询参数 [英] Validate query parameters without using a model in .netcore api
问题描述
是否可以在不使用模型的情况下验证操作的查询参数?我的API中的许多调用都是一次性的,如果只使用一次,我看不出为它们创建模型的意义.
我看了下面的文章,似乎正是我所需要的,只是我不希望它在不存在所需的parm的情况下返回404,我希望它返回类似错误消息的对象进行模型验证的过程-实际上,我只是希望将参数像模型一样对待,而无需实际创建模型.
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)
[FromQueryRequired]是一个自定义ActionConstraint,如果缺少ID参数,则抛出404(直接从文章中获取).但是,我不需要404,而是想要一个对象,该对象的信息为{MESSAGE:"ID is required"}.我认为问题是我无法从操作约束中访问Response上下文.
这是我最终使用的解决方案.将属性添加到名为[RequiredParm]的参数中.我大致基于其他人对另一个问题的答案,但我目前似乎找不到它,对任何人都表示歉意,如果可以找到,我会以信誉为目的来更新此答案.
找到它,由@James Law回答-"Web API必需参数" >
用法:
[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
{
}
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.
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
{
}
这篇关于在.netcore api中不使用模型的情况下验证查询参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!