asp.net web API 路由中的可选属性

Optional attribute in asp.net web API routing

我正在使用网络 api 过滤器来验证所有传入的视图模型和 return 视图状态错误(如果它为 null):

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);
        }
    }
}

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

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

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

"Message": "An error has occurred.", "ExceptionMessage": "Optional parameter 'input' is not supported by 'FormatterParameterBinding'.",
"ExceptionType": "System.InvalidOperationException", "StackTrace": " at System.Web.Http.Controllers.HttpActionBinding.ExecuteBindingAsync(

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

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

第二个选项是为所有可选参数设置一些 Base class,如下所示,只需使用 is 运算符检查即可。

public abstract class OptionalParameter
{
}

第三个选项是对界面执行相同的操作。

虽然我认为该属性是最干净的,但实现起来有点困难。