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

本文关键字:属性 路由 net web API asp | 更新日期: 2023-09-27 18:16:18

我正在使用web api过滤器来验证所有传入的视图模型,并返回视图状态错误,如果它是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);
        }
    }
}

我有web api在生产中工作,现在我有新的请求添加一个可选参数到一个动作。可选的…保持API兼容性

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

,如果我不指定输入= null,它不被认为是一个可选参数,不能通过我的验证。使用= null,我得到以下错误:

"Message": "出错","ExceptionMessage": "可选'FormatterParameterBinding'不支持参数'input' .",
:"ExceptionType系统。InvalidOperationException", "StackTrace": "在System.Web.Http.Controllers.HttpActionBinding.ExecuteBindingAsync (

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

  • ps:我不能使用语法路由与?符号,因为它是[FromBody]
  • pss:我不想介绍v2 api,因为它不是v2 api。我正在添加新的可选参数ps:我需要某种属性更新绑定描述符并指定我的参数为

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

因为这是你自己的验证,它不能通过没有= null,你可以添加一个自定义的[OptionalParameter]属性,并检查它的存在,例如,虽然你需要做一些缓存的类型,以避免过度使用反射。

第二个选项是为所有可选参数设置一些基类,就像下面这样,然后使用is操作符检查。

public abstract class OptionalParameter
{
}

第三个选择是对接口做同样的事情。

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