ASP.Net Web API GETに複数のパラメーターを渡すにはどうすればよいですか?


136

.Net MVC4 Web APIを使用して(うまくいけば)RESTful APIを実装しています。システムにいくつかのパラメーターを渡し、システムに何らかのアクションを実行させてから、オブジェクトのリストを結果として返す必要があります。具体的には、2つの日付を渡し、その間にあるレコードを返しています。また、後続の呼び出しがシステムで再処理されないように、返されたレコードを追跡しています。

私はいくつかのアプローチを検討しました:

  1. paramsを1つのJSON文字列にシリアル化し、APIで分離します。 http://forums.asp.net/t/1807316.aspx/1

  2. クエリ文字列でパラメータを渡します。
    複数のクエリパラメータをRESTful APIに渡す最良の方法は何ですか?

  3. ルートのパラメータの定義:api / controller / date1 / date2

  4. 本質的にparamsでオブジェクトを渡すことができるPOSTを使用します。

  5. Web APIが(現在)サポートしているため、ODATAを調査しています。私はまだこれで多くのことをしていないので、私はそれにあまり詳しくありません。

適切なRESTプラクティスは、データがプルされるときはGETを使用する必要があることを示しているようです。ただし、GETもnullipotent(副作用を生成しない)である必要があります。APIシステムでレコードをマークしているため、特定の実装がこれに違反しているかどうかを知り、副作用を生成しています。

また、可変パラメーターのサポートについても質問しました。入力パラメーターリストが変更された場合、それが頻繁に発生する場合、選択肢3のルートを再定義するのは面倒です。そして、パラメータが実行時に定義されるとどうなるか...

いずれにせよ、私の特定の実装では、どの選択(もしあれば)が最良と思われますか?

回答:


10

このレコードマーキングはどういう意味ですか?これをロギング目的でのみ使用する場合は、GETを使用してすべてのキャッシュを無効にします。これは、このリソースに対するすべてのクエリをログに記録したいためです。レコードマーキングに別の目的がある場合、POSTが適しています。ユーザーは、彼のアクションがシステムに影響を与え、POSTメソッドが警告であることを知っておく必要があります。


マークすることは、後続の呼び出しで繰り返されないように、処理されて返されるレコードを単に追跡することを意味します。私の場合、処理されているものを追跡するために、別のテーブルに挿入しているだけです。
sig606

現在、私は主にあなたが言った理由のためにPOSTとしてそれを実装しています-アクションが起こり、消費者はそれらを認識しています。プラスは簡単で、異なるデータを渡すことにRESPで最も柔軟性のようです。
sig606

@ sig606:POSTは私にとっての道ですが、あなたのプロトコルは安全ではないようです。何かが起こり、レコードがクライアント側で取得されたが、バグのために処理されなかった場合はどうなりますか?あなたはそれらをもう返さず、クライアントは失われたデータを残されます。
LukLed

現在、私のAPIはレコードが処理された後にのみレコードを返します。したがって、コンシューマはAPIに2つの日付を渡します。これら2つの日付の間のレコードが処理され、マークされます。次に、データが呼び出し元に返されます。処理中または処理後、クライアントに到達する前に何か問題が発生した場合、問題が発生したと思います。
sig606

141

最も簡単な方法は、単に使用することだと思いますAttributeRouting

それはあなたのコントローラー内で明白です、なぜあなたはこれをあなたのグローバルWebApiConfigファイルにしたいですか?

例:

    [Route("api/YOURCONTROLLER/{paramOne}/{paramTwo}")]
    public string Get(int paramOne, int paramTwo)
    {
        return "The [Route] with multiple params worked";
    }

{}名前は、あなたのパラメータと一致する必要があります。

そのように単純ですが、GETこれで、このインスタンスで複数のパラメーターを処理するができました。


12
これは素晴らしい。ほとんどの人はWebApiConfigファイルにルートを設定することを推奨しますが、これは確かに優れています。
rhyek 2015年

4
確かに、私たち(ほとんどの人)はあなたの設定のための集中管理エリアを持つことを推奨します。Web API(Microsoftまたはその他)の場合、RESTの一元化されたパターンが重要です。属性ルーティングはかわいいですが、1回限りの例外が魅力的です。
David Betz、

3
同意しました。実際に回答を更新する必要があります。GETを使用して複数のパラメーターを実行する方法には、はるかに優れた方法があります。WebAPIが初めてのときにこれを投稿しましたが、(新しいコントローラーを作成したくない場合を除いて)AttributeRoutingを使用せず、すべてのパラメーターをQueryStringに渡して、自動的にマッピングします。人々がこの古い方法を使用しないように、機会があれば更新します
Mark Pieszak-Trilon.io

Route名前付きパラメーター(クエリパラメーターなど)にを設定する方法はありますか?
Shimmy Weitzhandler 2015

1
アクションメソッド名が必要な場合は、それに合わせて変更できます。[Route( "api / YOURCONTROLLER / Get / {paramOne} / {paramTwo}")] public string Get(int paramOne、int paramTwo){return "something"; }
ダッシュ

49

に新しいルートを追加するだけです WebApiConfigエントリにです。

たとえば、次のように呼び出します。

public IEnumerable<SampleObject> Get(int pageNumber, int pageSize) { ..

追加:

config.Routes.MapHttpRoute(
    name: "GetPagedData",
    routeTemplate: "api/{controller}/{pageNumber}/{pageSize}"
);

次に、パラメーターをHTTP呼び出しに追加します。

GET //<service address>/Api/Data/2/10 

10
これは、すべての部分をリストする唯一の答えのようです。誰かがapi/controller?start=date1&end=date2スタイルURIの使い方をよりよく説明してくれることを願っています。
Hot Licks

@Hot Licks Andrew Verigaの回答は、クエリ文字列引数でうまく機能します。基本的に、クエリ文字列名をクラスプロパティにバインドし、メソッドに渡します。メソッドは、[FromUri]属性でマークされた単一のクラス引数を取り、そのプロパティとしてクエリ文字列引数を持ちます。
David Peterson

素晴らしいもの。ありがとう!
Hugo Nava Kopp、2017

こんにちは@HotLicksとGrahamWrightこの質問に答えられると思いますか?おかげで、stackoverflow.com

45

パラメータを渡す必要があるRESTfull APIを実装する必要がありました。Markの最初の例「api / controller?start = date1&end = date2」で説明されているのと同じスタイルでクエリ文字列のパラメーターを渡すことでこれを行いました

コントローラでは、C#でURL分割のヒントを使用しましたか?

// uri: /api/courses
public IEnumerable<Course> Get()
{
    NameValueCollection nvc = HttpUtility.ParseQueryString(Request.RequestUri.Query);
    var system = nvc["System"];
    // BL comes here
    return _courses;
}

私の場合、次のようなAjaxを介してWebApiを呼び出していました。

$.ajax({
        url: '/api/DbMetaData',
        type: 'GET',
        data: { system : 'My System',
                searchString: '123' },
        dataType: 'json',
        success: function (data) {
                  $.each(data, function (index, v) {
                  alert(index + ': ' + v.name);
                  });
         },
         statusCode: {
                  404: function () {
                       alert('Failed');
                       }
        }
   });

これが役に立てば幸い...


2
ParameterBindingがクエリ文字列をapiメソッドのパラメーターに自動的にマップするため、WebApiを使用していないと思います...
emp

1
はい、より良い方法は、[Route( "api / DbMetaData / {system} / {searchString}")]のような属性を使用してから、Get(string system、string searchString)にパラメーターを追加して、 " ... api / DbMetaData / mysystem / mysearchstring "
Nigel Findlater

私はC#MVC WebApiで彼の例を使用しましたが、うまくいきました。+1例
Si8 2017

38

私はhttp://habrahabr.ru/post/164945/で優れたソリューションを見つけました

public class ResourceQuery
{
   public string Param1 { get; set; }
   public int OptionalParam2 { get; set; }
}

public class SampleResourceController : ApiController
{
    public SampleResourceModel Get([FromUri] ResourceQuery query)
    {
        // action
    }
}

5
ここでの手がかりは[FromUri]です
トランスポーター、

2
記事はロシア語ですが、@ tranceporterは正しいです。「FromUri」は、URLからパラメーターを取得するための優れた方法のように見えます。役に立つかもしれません別の記事:asp.net/web-api/overview/formats-and-model-binding/...
グレッグ

これは私がかなり長い間やってきたことであり、とてもうまくいきました!このソリューションもお勧めします。
David Peterson、

(以外のGet)別のヘルパーメソッドを呼び出す場合でも、使用できます[FromUri]か?うまくいかないようです。
ジョクル

8

GETまたはPOSTの使用は、@ LukLedによって明確に説明されています。パラメーターを渡す方法については、2番目のアプローチを使用することをお勧めします(ODATAについてもあまり知りません)。

1. paramsを1つのJSON文字列にシリアル化し、APIでそれを選択します。http://forums.asp.net/t/1807316.aspx/1

これはユーザーフレンドリーではなく、SEOフレンドリーでもありません

2.クエリ文字列にパラメータを渡します。複数のクエリパラメータをRESTful APIに渡す最良の方法は何ですか?

これは通常の望ましいアプローチです。

3.ルートのパラメーターの定義:api / controller / date1 / date2

これは間違いなく良い方法ではありません。これdate2は、誰かがのサブリソースであるdate1と感じさせ、それはそうではありません。date1date2はどちらもクエリパラメータであり、同じレベルになります。

単純なケースでは、私はこのようなURIを提案します、

api/controller?start=date1&end=date2

しかし、個人的には以下のURIパターンが好きですが、この場合、パラメーターをマップするためのカスタムコードを記述する必要があります。

api/controller/date1,date2

実際、それらは私の元の説明でした。LukLedは私のタグとURLリンクを輝かせたと思います。
sig606

SEOに関する限り、この場合は適用されません。このコードは「サーバー間」なので、外部の世界がそれを発見したかどうかは気にしません。実際、ランダムアクセスを回避するために、適切なセキュリティ対策を講じる必要があります。私はシステムの別の部分でJSONシリアル化を行う必要がありました(objの大きなリストをPOSTしようとするバグのようなので、文字列にシリアル化する必要がありました)。この場合、それほど長くはかかりません。 。
sig606

1
私はあなたがすでに答えを持っているといいのですが、なぜあなたは質問をしているのですか?
VJAI

2
この返事が遅くなってすみません、マーク。私はいくつかの解決策を試しましたが、どれが最善であり、業界標準のアプローチに固執しようとしているのか確信が持てなかったため、SOに投稿しました。
sig606

1
@Mark次のようなもの:stackoverflow.com/questions/9681658/…
RredCat 2013年


3
 [Route("api/controller/{one}/{two}")]
    public string Get(int One, int Two)
    {
        return "both params of the root link({one},{two}) and Get function parameters (one, two)  should be same ";
    }

ルートリンクのパラメーター({one}、{two})とGet関数パラメーター(1、2)は両方とも同じである必要があります


2

これは本当に古いのはわかっていますが、最近同じものが欲しかったのですが、これが見つかりました...

    public HttpResponseMessage Get([FromUri] string var, [FromUri] string test) {
        var retStr = new HttpResponseMessage(HttpStatusCode.OK);
        if (var.ToLower() == "getnew" && test.ToLower() == "test") {
            retStr.Content = new StringContent("Found Test", System.Text.Encoding.UTF8, "text/plain");
        } else {
            retStr.Content = new StringContent("Couldn't Find that test", System.Text.Encoding.UTF8, "text/plain");
        }

        return retStr;
    }

だから今あなたのアドレス/ URI / ...

http(s):// myURL / api / myController /?var = getnew&test = test

結果:「見つかったテスト」


http(s):// myURL / api / myController /?var = getnew&test = anything

結果:「そのテストを見つけることができませんでした」


元のメソッドのシグネチャを変更し、ルーティング構成を微調整することなく、達成しようとしていることを正確にオーバーロードできるため、私はC#でこのスタイルを個人的に気に入っています。GETリクエストを作成するこの(おそらく時代遅れの)アプローチに慣れている他の人を助けることを願っています。
リックリッグス

1
このアプローチを使用するサードパーティのカレンダーアプリで使用されるイベントAPIを作成する必要がありました。私はこの答えを見つけてうれしいです!
クレイレイ


0
    public HttpResponseMessage Get(int id,string numb)
    {
        //this will differ according to your entity name
        using (MarketEntities entities = new MarketEntities())
        {
          var ent=  entities.Api_For_Test.FirstOrDefault(e => e.ID == id && e.IDNO.ToString()== numb);
            if (ent != null)
            {
                return Request.CreateResponse(HttpStatusCode.OK, ent);
            }
            else
            {
                return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Applicant with ID " + id.ToString() + " not found in the system");
            }
        }
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.