お気づきの動作は、属性ルーティングではなく、アクションの選択とモデル バインディングに関連しています。
「ID」がクエリ文字列から取得されることを期待している場合は、次のようにルート テンプレートを変更します (定義した方法では、URI パスで「ID」が必須になるため)。
[HttpPost("api/set/copy")]
2 番目の質問を見て、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;
}
}