95

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)matchapi/{controller}/{id}であり、これがフレームワークを混乱させます。

デフォルトの API ルートを再び機能させるにはどうすればよい{action}ですか? RecordByCategoryIdControllerデフォルトの API ルートに一致する名前の別のコントローラーを作成することを考えました.../api/recordbycategoryid/5。ただし、それは「汚い」(したがって不十分な)解決策であることがわかりました。私はこれに関する回答を探しましたが、{action}この問題について言及しているルートの使用に関するチュートリアルはありません。

4

5 に答える 5

105

ルート エンジンは、ルールを追加するときと同じシーケンスを使用します。最初に一致したルールを取得すると、他のルールのチェックを停止し、これを使用してコントローラーとアクションを検索します。

したがって、次のことを行う必要があります。

  1. 特定のルールを一般的なルール (デフォルトなど) の前に置きます。つまりRouteTable.Routes.MapHttpRoute、最初に "WithActionApi" をマップし、次に "DefaultApi" をマップします。

  2. defaults: new { id = System.Web.Http.RouteParameter.Optional }ID がオプションになると、「/api/{part1}/{part2}」などの URL が「DefaultApi」に入れられなくなるため、「WithActionApi」ルールのパラメーターを削除します。

  3. 名前付きアクションを「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" };
}
于 2012-11-28T02:15:42.763 に答える
40

属性ルーティングの助けを借りて問題を解決できます

コントローラ

[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 }
        );
    }
}

詳細については、記事を確認してください属性ルーティングと発明ベースのルーティングはこちらこちら

于 2014-06-18T07:56:53.637 に答える
0

これを試して。

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 }

        );
    }
}
于 2018-09-10T07:53:31.083 に答える