Web APIのリクエストに一致する複数のアクションが見つかりました


243

2つの "Get"メソッドを実行しようとすると、このエラーが発生し続ける

リクエストに一致する複数のアクションが見つかりました:webapi

私はこれについてスタックで他の同様の質問を見回していますが、わかりません。

2つの異なる名前があり、「HttpGet」属性を使用しています

[HttpGet]
public HttpResponseMessage Summary(MyVm vm)
{
    return null;
}

[HttpGet]
public HttpResponseMessage FullDetails()
{
    return null;
}

回答:


485

あなたのルートマップはおそらくこのようなものです:

routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional });

ただし、同じhttpメソッドで複数のアクションを実行するには、次のようなルートを介してwebapiに詳細情報を提供する必要があります。

routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional });

routeTemplateにアクションが含まれていることに注意してください。詳細はこちら:http : //www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api

更新:

了解しました。これであなたが何をしているのか理解できると思いますので、これについてもう1つ説明します。

おそらく、action urlパラメータは必要なく、別の方法で後のコンテンツを説明する必要があります。メソッドが同じエンティティからデータを返すと言っているので、パラメーターに説明を任せます。

たとえば、2つのメソッドは次のようになります。

public HttpResponseMessage Get()
{
    return null;
}

public HttpResponseMessage Get(MyVm vm)
{
    return null;
}

MyVmオブジェクトで渡すデータの種類は何ですか?URIを介して変数を渡すことができる場合は、そのルートを使用することをお勧めします。それ以外の場合は、リクエストの本文でオブジェクトを送信する必要があります。GETを実行するとき、それはあまりHTTPではありません(MyVmの前で[FromBody]を使用するだけです)。

うまくいけば、これは、アクション名や[HttpGet]属性を使用しなくても、単一のコントローラーで複数のGETメソッドを使用できることを示しています。


何らかの方法でメリットはありますか?セカンダリを実行する場合、各メソッドにHttpアクションを配置する必要がありますか?それは大きな欠点ですか?
chobo2 2013年

3
一方が他方よりも有利であるかどうかは、実際にはプロジェクトによって異なります。RESTful APIを構築している場合は、HTTP規則(GET、POST、PUT、DELETE ...)を使用する必要があります。この場合、ルーティングコードの最初のブロックが先ですが、APIを通じて公開するエンティティごとに異なるコントローラーが必要になります。あなたのメソッド名に基づいて、これはそうではないと思いますので、より説明的なルーティングを使用してください。ルートにアクションが含まれている場合は、各メソッドにhttp属性を明示的に設定する必要があります。
Jed

1
@ chobo2コントローラ内でそれに応じて名前が付けられたメソッドを使用しないのはなぜですか?GetSummary(MyVm wm)およびGetDetails()
Jed

1
あなたの答えをありがとう、ちょうど私の両方のアクションが異なる名前を持っていたにもかかわらず、ルート解決が機能しなかった理由を理解するのを助けてくれました。なぜデフォルトの動作だけではないのか(つまり、webapiconfig.csのデフォルトのルートテンプレートが「{action}」を含まないのはなぜですか?)
Tejas Sharma

1
@brunoエリアを使用している場合は、AdminAreaRegistrationで次のような「admin」固有のAPIを追加することもできますstackoverflow.com/a/9849011/16940
Simon_Weaver

67

Web API 2以降の更新。

このAPI構成をWebApiConfig.csファイルに含めます。

public static void Register(HttpConfiguration config)
{
    //// Web API routes
    config.MapHttpAttributeRoutes(); //Don't miss this

    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = System.Web.Http.RouteParameter.Optional }
    );
}

次のようにコントローラーをルーティングできます。

[Route("api/ControllerName/Summary")]
[HttpGet]
public HttpResponseMessage Summary(MyVm vm)
{
    rturn null;
}

[Route("api/ControllerName/FullDetails")]
[HttpGet]
public HttpResponseMessage FullDetails()
{
    return null;
}

ここで、ControllerNameはコントローラーの名前です(「コントローラー」なし)。これにより、上記のルートで各アクションを取得できます。

詳細については、http//www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2


私はこのソリューションが本当に好きでした。私のデフォルトルートも同じと私は例外の「例外」ルート持って
レアンドロ・デ・メロFagundes

パラメータをURL EXにマップすることもできます:[Route( "api / ControllerName / Summary / {vm}")]
nulltron

15

Web API(デフォルト)では、メソッドはHTTPメソッドとルート値の組み合わせに基づいて選択されます

MyVm複雑なオブジェクトのように見え、本文からフォーマッターによって読み取られるため、ルートデータに関して2つの同一のメソッドがあります(どちらにもルートからのパラメーターがないため)-これにより、ディスパッチャー(IHttpActionSelector)が適切なものと一致しなくなります。

あいまいさを解決するには、クエリ文字列またはルートパラメータのいずれかでそれらを区別する必要があります。


14

多くのウェブを検索し、以下を見つけた場合、ルーティングマップに最も適したフォームを見つけようと試みた後

config.Routes.MapHttpRoute("DefaultApiWithId", "Api/{controller}/{id}", new { id =RouteParameter.Optional }, new { id = @"\d+" });
config.Routes.MapHttpRoute("DefaultApiWithAction", "Api/{controller}/{action}");

これらのマッピングは、アクション名マッピングと基本的なhttp規則(GET、POST、PUT、DELETE)の両方に適用されます


9
私にとってこれはうまく
いきました

まさに順序はここでは重要である
AT


5

アクションを使用しない場合のオプションは次のとおりです。

  1. メソッドの1つを別のコントローラーに移動して、それらが衝突しないようにします。

  2. パラメータを受け取るメソッドを1つだけ使用し、それがnullの場合はコードから他のメソッドを呼び出します。


それは解決策かもしれませんが、最適ではありませんが、とにかく私の側から+1します:)
satish kumar V '18年5

4

この解決策は私にとってうまくいきました。

Route2を最初にWebApiConfigに配置してください。また、各メソッドの前にHttpGetとHttpPostを追加し、URLにコントローラー名とメソッド名を含めます。

WebApiConfig =>

config.Routes.MapHttpRoute(
           name: "MapByAction",
           routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional });
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional });

コントローラー=>

public class ValuesController : ApiController
{

    [HttpPost]
    public string GetCustomer([FromBody] RequestModel req)
    {
        return "Customer";
    }

    [HttpPost]
    public string GetCustomerList([FromBody] RequestModel req)
    {
        return "Customer List";
    }
}

URL =>

http://localhost:7050/api/Values/GetCustomer

http://localhost:7050/api/Values/GetCustomerList

4

これは、すべてが正しいことを知っていて、50回チェックしたすべての人に対する答えです .....

繰り返し見ないでくださいRouteConfig.cs

編集するファイルの名前は WebApiConfig.cs

また、おそらく次のようになります。

using System.Web.Http;

namespace My.Epic.Website
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
          config.MapHttpAttributeRoutes();

          // api/Country/WithStates
          config.Routes.MapHttpRoute(
            name: "ControllerAndActionOnly",
            routeTemplate: "api/{controller}/{action}",
            defaults: new { },
            constraints: new { action = @"^[a-zA-Z]+([\s][a-zA-Z]+)*$" });

          config.Routes.MapHttpRoute(
            name: "DefaultActionApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
          );
    }
    }
}

3時間くらいは助かったと思います。


1
ありがとう、あなたは私を約3時間救ってくれました
geedubb

3

2つのGetメソッドがある場合、1つはパラメーターなし、もう1つはパラメーターとして複合型を使用しているときに、同じエラーが発生することがわかりました。これを解決するには、Idという名前のint型のダミーパラメーターを最初のパラメーターとして追加し、その後に複合型パラメーターを追加します。次に、複合型パラメーターをルートテンプレートに追加しました。以下は私のために働いた。

最初に取得:

public IEnumerable<SearchItem> Get()
{
...
}

2番目の取得:

public IEnumerable<SearchItem> Get(int id, [FromUri] List<string> layers)
{
...
}

WebApiConfig:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}/{layers}",
    defaults: new { id = RouteParameter.Optional, layers RouteParameter.Optional }
);

3

Web APIコントローラーの代わりにMVCコントローラーを使用していることが原因である可能性があります。Web APIコントローラーの名前空間を確認してください。

using System.Net;
using System.Net.Http;
using System.Web.Http;

名前空間が次のとおりである場合、Web APIコントローラのメソッド呼び出しで上記のエラーが発生します

using System.Web;
using System.Web.Mvc;

2

名前が異なり、パラメータが同じ2つのメソッドがあることを確認してください。

もしそうなら、メソッドのいずれかを削除して試してください。


2

WebAPIコントローラーに追加のアクションを追加しようとしているときに、この問題に遭遇しました。

あなたが持っていると仮定

public IEnumerable<string> Get()
{
    return this.Repository.GetAll();
}

[HttpGet]
public void ReSeed()
{
    // Your custom action here
}

TSによって記述された問題をトリガーする/ api / controllerの要求を満たす2つのメソッドが存在します。

追加のアクションに「ダミー」パラメーターを追加したくなかったので、デフォルトのアクションを調べて次のようにしました。

[ActionName("builtin")]
public IEnumerable<string> Get()
{
    return this.Repository.GetAll();
}

「デュアル」ルートバインディングと組み合わせた最初の方法の場合:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { action = "builtin", id = RouteParameter.Optional },
    constraints: new { id = @"\d+" });

config.Routes.MapHttpRoute(
    name: "CustomActionApi",
    routeTemplate: "api/{controller}/{action}");

最初のルートテンプレートに「action」パラメータがないように見えても、デフォルトのアクションを構成して、「通常の」WebAPI呼び出しのルーティングと追加のアクションへの呼び出しを分離できることに注意してください。


2

私の場合、すべてが正しかった

1)Web Configが適切に構成されている2)ルートプレフィックスとルート属性が適切であった

それでもエラーが発生しました。私の場合、「ルート」属性(F12キーを押す)はSystem.Web.MVcを指していましたが、System.Web.Httpではなく、問題を引き起こしていました。


この答えは私を大いに助けてくれました!
tvb108108

1

[Route("api/[controller]/[action]")]コントローラクラスに追加できます。

[Route("api/[controller]/[action]")]
[ApiController]
public class MySuperController : ControllerBase
{
 ...
}

0

古い質問であることは承知していますが、AngularJSなどのサービスリソースを使用してWebAPIに接続するときに、正しいルートを使用していることを確認してください。そうしないと、このエラーが発生します。


0

[HttpPost / Put / Get / Delete]属性を使用して、デフォルトのGET | PUT | POST | DELETEアクションのコントローラーメソッドを装飾しないでください。この属性をバニラポストコントローラーアクションに追加したところ、404が発生しました。

それが非常にイライラさせられ、進歩を停止させる可能性があるので、これが誰かを助けることを願っています。


0

例=> TestController

        [HttpGet]
        public string TestMethod(int arg0)
        {
            return "";
        }

        [HttpGet]
        public string TestMethod2(string arg0)
        {
            return "";
        }

        [HttpGet]
        public string TestMethod3(int arg0,string arg1)
        {
            return "";
        }

WebApiConfig.csファイルのみを変更できる場合。

 config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/",
                defaults: null
            );

それでおしまい :)

そして結果: ここに画像の説明を入力してください


0

次のようにしてみましたか:

[HttpGet("Summary")]
public HttpResponseMessage Summary(MyVm vm)
{
    return null;
}

[HttpGet("FullDetails")]
public HttpResponseMessage FullDetails()
{
    return null;
}

1
HttpGet属性には文字列引数を受け入れるコンストラクターがないため、これは非.NET Coreプロジェクトではコンパイルされません。
Hoppeduppeanut、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.