Global.asaxにデフォルトルートがあります。
RouteTable.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = System.Web.Http.RouteParameter.Optional }
);
特定の機能をターゲットにできるようにしたかったので、別のルートを作成しました。
RouteTable.Routes.MapHttpRoute(
name: "WithActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = System.Web.Http.RouteParameter.Optional }
);
だから、私のコントローラーには、
public string Get(int id)
{
return "object of id id";
}
[HttpGet]
public IEnumerable<string> ByCategoryId(int id)
{
return new string[] { "byCategory1", "byCategory2" };
}
.../api/records/bycategoryid/5
を呼び出すと、欲しいものが得られます。ただし、.../api/records/1
を呼び出すとエラーが発生します
要求に一致する複数のアクションが見つかりました:...
その理由はわかります-ルートは有効なURLを定義するだけですが、関数の一致に関してはGet(int id)
とByCategoryId(int id)
の両方がapi/{controller}/{id}
に一致しますconfusesフレームワーク。
デフォルトのAPIルートを再び機能させるために何をする必要があり、{action}
でルートを保持しますか?デフォルトのAPIルートに一致するRecordByCategoryIdController
という名前の別のコントローラーを作成して、.../api/recordbycategoryid/5
を要求することを考えました。しかし、私はそれが「汚い」(したがって不満足な)解決策であることがわかりました。これに関する答えを探しましたが、{action}
でルートを使用することに関するチュートリアルはありません。
ルートエンジンは、ルールを追加するのと同じシーケンスを使用します。最初に一致したルールを取得すると、他のルールのチェックを停止し、これを使用してコントローラーとアクションを検索します。
したがって、次のことを行う必要があります。
一般的なルール(デフォルトなど)の前に特定のルールを置きます。つまり、RouteTable.Routes.MapHttpRoute
を使用して最初に "WithActionApi"をマッピングし、次に "DefaultApi"をマッピングします。
「WithActionApi」ルールのdefaults: new { id = System.Web.Http.RouteParameter.Optional }
パラメータを削除します。IDがオプションになった場合、「/ api/{part1}/{part2}」などのURLは「DefaultApi」になりません。
名前付きアクションを「DefaultApi」に追加して、入力するアクションをルートエンジンに伝えます。それ以外の場合、コントローラーに複数のアクションがあると、エンジンはどのアクションを使用するかを認識せず、「要求に一致する複数のアクションが見つかりました:...」をスローします。次に、Getメソッドと一致させるために、 ActionNameAttribute を使用します。
したがって、ルートは次のようになります。
// Map this rule first
RouteTable.Routes.MapRoute(
"WithActionApi",
"api/{controller}/{action}/{id}"
);
RouteTable.Routes.MapRoute(
"DefaultApi",
"api/{controller}/{id}",
new { action="DefaultAction", id = System.Web.Http.RouteParameter.Optional }
);
そしてコントローラー:
[ActionName("DefaultAction")] //Map Action and you can name your method with any text
public string Get(int id)
{
return "object of id id";
}
[HttpGet]
public IEnumerable<string> ByCategoryId(int id)
{
return new string[] { "byCategory1", "byCategory2" };
}
属性ルーティングを使用して問題を解決できます
コントローラー
[Route("api/category/{categoryId}")]
public IEnumerable<Order> GetCategoryId(int categoryId) { ... }
jqueryのURI
api/category/1
ルート設定
using System.Web.Http;
namespace WebApplication
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API routes
config.MapHttpAttributeRoutes();
// Other Web API configuration not shown.
}
}
}
デフォルトのルーティングはデフォルトとして機能しています慣習ベースのルーティング
コントローラー
public string Get(int id)
{
return "object of id id";
}
JqueryのURI
/api/records/1
ルート設定
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Attribute routing.
config.MapHttpAttributeRoutes();
// Convention-based routing.
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
詳細については、記事を参照してください ここで属性ルーティングとonvention-basedルーティング & this
考えられる理由は、ApiControllerからControllerを継承していないことも考えられます。同じことを理解するのに少し時間がかかりました。
これを試して。
public class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
var json = config.Formatters.JsonFormatter;
json.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"));
config.Formatters.Remove(config.Formatters.XmlFormatter);
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional , Action =RouteParameter.Optional }
);
}
}
ルートを区別するには、idが数値でなければならないという制約を追加してみてください。
RouteTable.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
constraints: new { id = @"\d+" }, // Only matches if "id" is one or more digits.
defaults: new { id = System.Web.Http.RouteParameter.Optional }
);