ASP.NET Web API 重载/参数



tl;dr 版本是:我可以模拟 Web API 方法的 params/重载而不必实现自定义 IHttpActionSelector 吗?


参数

我很惊讶地发现 Web API 方法不支持params(并且此后在可能错误的地方打开了一个问题(

[HttpPost]
[Route("Test")]
public IHttpActionResult Test([FromBody] params Int32[] values) {
    // ...
}

POST -ing [1,2,3]的有效负载按预期工作,但只是4会导致values null

超载

所以我决定尝试方法重载。然而,这也行不通。

[HttpPost]
[Route("Test")]
public IHttpActionResult Test([FromBody] Int32 value) {
    return this.Test(new[] { value });
}
[HttpPost]
[Route("Test")]
public IHttpActionResult Test([FromBody] Int32[] values) {
    // ...
}

不管这(我想是意料之中的(抛出的有效载荷如何:

找到与请求匹配的多个操作:...

结论

看起来我将不得不尝试实现自定义 IHttpActionSelector,但我想知道是否有任何我错过的魔法可以代替?

我可以模拟 Web API 方法的参数/重载而不必 实现自定义IHttpActionSelector

是的


这是与模型相关的绑定问题。

引用 HttpParameterBinding

已创建以下绑定程序和属性。

public class ParamsAttribute : ParameterBindingAttribute {
    public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter) {
        //Check to make sure that it is a params array
        if (parameter.ParameterType.IsArray &&
            parameter.GetCustomAttributes<ParamArrayAttribute>().Count() > 0) {
            return new ParamsParameterBinding(parameter);
        }
        return parameter.BindAsError("invalid params binding");
    }
}
public class ParamsParameterBinding : HttpParameterBinding {
    public ParamsParameterBinding(HttpParameterDescriptor descriptor)
        : base(descriptor) {
    }
    public override async Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken) {
        var descriptor = this.Descriptor;
        var paramName = descriptor.ParameterName;
        var arrayType = descriptor.ParameterType;
        var elementType = arrayType.GetElementType();
        try {
            //can it be converted to array
            var obj = await actionContext.Request.Content.ReadAsAsync(arrayType);
            actionContext.ActionArguments[paramName] = obj;
            return;
        } catch { }
        try {
            //Check if single and wrap in array
            var obj = await actionContext.Request.Content.ReadAsAsync(elementType);
            var array = Array.CreateInstance(elementType, 1);
            array.SetValue(obj, 0);
            actionContext.ActionArguments[paramName] = array;
            return;
        } catch { }
    }
}

这允许以下内容接受在请求正文中发布的单个和多个值。

[HttpPost]
[Route("Test")]
public IHttpActionResult Test([Params] params Int32[] values) {
    // ...
}

POST -ing 有效载荷为 [1,2,3] 将按预期工作,也只需 4 将导致values [4]

绑定程序现在遵循 params 修饰符,从而使端点能够接受一个或多个给定参数。它也适用于非基元对象

[HttpPost]
[Route("Customers")]
public IHttpActionResult Test([Params] params Customer[] customers) {
    // do important stuff
}

这可以进一步改进,以将任何集合作为参数来接受单个或多个值,而不仅仅是params

相关内容

  • 没有找到相关文章

最新更新