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
。