ASP.NET Web API 路由中的可选属性

Ale*_*akh 5 c# asp.net optional-parameters asp.net-web-api

我使用 Web api 过滤器来验证所有传入的视图模型,如果为空,则返回视图状态错误:

public class ValidateViewModelAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if(actionContext.ActionArguments != null)
        {
            foreach (var argument in actionContext.ActionArguments)
            {
                if (argument.Value != null)
                    continue;

                var argumentBinding = actionContext.ActionDescriptor?.ActionBinding.ParameterBindings
                    .FirstOrDefault(pb => pb.Descriptor.ParameterName == argument.Key);

                if(argumentBinding?.Descriptor?.IsOptional ?? true)
                    continue;

                actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, string.Format("Arguments value for {0} cannot be null", argument.Key));
                return;
            }
        }

        if (actionContext.ModelState.IsValid == false)
        {
            actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我有一个正在生产中运行的 Web api,现在我收到了向一项操作添加一个可选参数的新请求。可选....以保持 API 兼容性

    [Route("applyorder/{orderId}")]
    [HttpPost]
    public async Task<IHttpActionResult> ApplyOrder(int orderId, [FromBody] ApplyOrderViewModel input = null)
Run Code Online (Sandbox Code Playgroud)

如果我不指定输入,= null则它不会被视为可选参数,并且无法通过我的验证。我收到= null以下错误:

"Message": "发生错误。", "ExceptionMessage": "'FormatterParameterBinding' 不支持可选参数 'input'。",
"ExceptionType": "System.InvalidOperationException", "StackTrace": " at System. Web.Http.Controllers.HttpActionBinding.ExecuteBindingAsync(

如何保持全局视图模型验证到位,并仍然将这个唯一的方法参数标记为可选。

  • ps:我不能使用带?符号的语法路由,因为它是 [FromBody]
  • pss:我不想引入v2 api,因为它不是v2 api,我正在添加新的可选参数
  • psss:我需要某种属性来更新绑定描述符并指定我的参数是可选的,然后它将通过我的验证。

Ily*_*dik 3

由于这是您自己的验证,如果没有= null您可以添加自定义[OptionalParameter]属性并检查它是否存在,它就无法通过,例如,尽管您需要按类型进行一些缓存以避免过度使用反射。

第二个选项是为所有可选参数提供一些基类,如下所示,然后仅与is操作员检查。

public abstract class OptionalParameter
{
}
Run Code Online (Sandbox Code Playgroud)

第三种选择是对界面执行相同的操作。

尽管该属性在我看来是最干净的,但实现起来有点困难。

  • 是的,正如您所描述的“[可选]”的附加属性。您必须使用反射来检查属性是否存在。虽然您似乎已经在那里使用了反射,所以您只需要添加一个简单的属性检查。 (2认同)