您注意到的行为与动作选择和模型绑定更相关,而不是属性路由。
如果您期望 'ids' 来自查询字符串,请修改您的路由模板,如下所示(因为您定义它的方式使得 uri 路径中的 'ids' 是强制性的):
[HttpPost("api/set/copy")]
查看您的第二个问题,您是否希望接受 uri 本身中的 id 列表,例如api/set/copy/[1,2,3]
?如果是,我认为 web api 没有对这种模型绑定的内置支持。
您可以实现如下所示的自定义参数绑定来实现它(我猜还有其他更好的方法可以通过模型绑定器和值提供者来实现这一点,但我不太了解它们......所以你可能需要探索这些选项也是):
[HttpPost("api/set/copy/{ids}")]
public HttpResponseMessage CopySet([CustomParamBinding]int[] ids)
例子:
[AttributeUsage(AttributeTargets.Parameter, Inherited = false, AllowMultiple = false)]
public class CustomParamBindingAttribute : ParameterBindingAttribute
{
public override HttpParameterBinding GetBinding(HttpParameterDescriptor paramDesc)
{
return new CustomParamBinding(paramDesc);
}
}
public class CustomParamBinding : HttpParameterBinding
{
public CustomParamBinding(HttpParameterDescriptor paramDesc) : base(paramDesc) { }
public override bool WillReadBody
{
get
{
return false;
}
}
public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext,
CancellationToken cancellationToken)
{
//TODO: VALIDATION & ERROR CHECKS
string idsAsString = actionContext.Request.GetRouteData().Values["ids"].ToString();
idsAsString = idsAsString.Trim('[', ']');
IEnumerable<string> ids = idsAsString.Split(',');
ids = ids.Where(str => !string.IsNullOrEmpty(str));
IEnumerable<int> idList = ids.Select(strId =>
{
if (string.IsNullOrEmpty(strId)) return -1;
return Convert.ToInt32(strId);
}).ToArray();
SetValue(actionContext, idList);
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
tcs.SetResult(null);
return tcs.Task;
}
}