1. ホーム
  2. c#

[解決済み] ASP.NET Web APIで複数のGETメソッドを持つ単一のコントローラ

2022-04-15 16:04:59

質問内容

Web APIで、似たような構造のクラスがありました。

public class SomeController : ApiController
{
    [WebGet(UriTemplate = "{itemSource}/Items")]
    public SomeValue GetItems(CustomParam parameter) { ... }

    [WebGet(UriTemplate = "{itemSource}/Items/{parent}")]
    public SomeValue GetChildItems(CustomParam parameter, SomeObject parent) { ... }
}

個々のメソッドをマップすることができるので、適切な場所で適切なリクエストを取得するのが非常に簡単でした。類似のクラスで、単一の GET メソッドもありますが Object パラメータを使用することに成功しました。 IActionValueBinder . しかし、上記のような場合、次のようなエラーが発生します。

Multiple actions were found that match the request: 

SomeValue GetItems(CustomParam parameter) on type SomeType

SomeValue GetChildItems(CustomParam parameter, SomeObject parent) on type SomeType

をオーバーライドすることでこの問題にアプローチしようとしています。 ExecuteAsync メソッドに ApiController が、今のところうまくいきません。この問題に関して何かアドバイスがあれば教えてください。

編集:言い忘れましたが、現在、ルーティングに異なるアプローチを持つASP.NET Web API上でこのコードを動かそうとしています。問題は、このコードをASP.NET Web API上でどのように動作させるかです。

どのように解決するのですか?

これは、余分なGETメソッドをサポートし、通常のRESTメソッドもサポートするために、私が見つけた最良の方法です。 WebApiConfigに以下のルートを追加してください。

routes.MapHttpRoute("DefaultApiWithId", "Api/{controller}/{id}", new { id = RouteParameter.Optional }, new { id = @"\d+" });
routes.MapHttpRoute("DefaultApiWithAction", "Api/{controller}/{action}");
routes.MapHttpRoute("DefaultApiGet", "Api/{controller}", new { action = "Get" }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Get) });
routes.MapHttpRoute("DefaultApiPost", "Api/{controller}", new {action = "Post"}, new {httpMethod = new HttpMethodConstraint(HttpMethod.Post)});

この解決策を以下のテストクラスで検証してみました。 以下のコントローラの各メソッドを正常にヒットさせることができました。

public class TestController : ApiController
{
    public string Get()
    {
        return string.Empty;
    }

    public string Get(int id)
    {
        return string.Empty;
    }

    public string GetAll()
    {
        return string.Empty;
    }

    public void Post([FromBody]string value)
    {
    }

    public void Put(int id, [FromBody]string value)
    {
    }

    public void Delete(int id)
    {
    }
}

以下のリクエストに対応していることを確認しました。

GET /Test
GET /Test/1
GET /Test/GetAll
POST /Test
PUT /Test/1
DELETE /Test/1

備考 GET アクションが 'Get' で始まらない場合は、メソッドに HttpGet 属性を追加するとよいでしょう。