Bagaimana cara mengirimkan beberapa parameter ke ASP.Net Web API GET?


136

Saya menggunakan .Net MVC4 Web API untuk (semoga) mengimplementasikan RESTful api. Saya perlu meneruskan beberapa parameter ke sistem dan membuatnya melakukan beberapa tindakan, lalu mengembalikan daftar objek sebagai hasilnya. Secara khusus saya melewati dua tanggal dan mengembalikan catatan yang ada di antara mereka. Saya juga melacak catatan yang dikembalikan sehingga panggilan berikutnya tidak diproses ulang di sistem.

Saya telah mempertimbangkan beberapa pendekatan:

  1. Menyerialkan params ke dalam satu string JSON dan memisahkannya di API. http://forums.asp.net/t/1807316.aspx/1

  2. Teruskan params dalam string kueri.
    Apa cara terbaik untuk meneruskan beberapa parameter kueri ke restful api?

  3. Mendefinisikan params dalam rute: api / controller / date1 / date2

  4. Menggunakan POST yang secara inheren memungkinkan saya meneruskan objek dengan params.

  5. Meneliti ODATA sejak Web API (saat ini) mendukungnya. Saya belum melakukan banyak hal dengan ini jadi saya tidak terlalu terbiasa dengannya.

Tampaknya praktik REST yang tepat menunjukkan saat data ditarik, Anda harus menggunakan GET. Namun, GET juga harus nullipotent (tidak menghasilkan efek samping), dan saya bertanya-tanya apakah penerapan khusus saya melanggar itu karena saya menandai catatan dalam sistem API, maka saya menghasilkan efek samping.

Itu juga membawa saya ke pertanyaan tentang parameter variabel pendukung. Jika daftar parameter masukan berubah, akan membosankan jika harus menentukan ulang rute Anda untuk Pilihan 3 jika itu sering terjadi. Dan apa yang mungkin terjadi jika parameter ditentukan pada waktu proses ...

Bagaimanapun, untuk penerapan spesifik saya, pilihan mana (jika ada) yang paling baik?

Jawaban:


10

Apa arti dari penandaan catatan ini? Jika ini digunakan hanya untuk tujuan logging, saya akan menggunakan GET dan menonaktifkan semua caching, karena Anda ingin mencatat setiap query untuk resource ini. Jika penandaan catatan memiliki tujuan lain, POST adalah cara yang tepat. Pengguna harus tahu, bahwa tindakannya mempengaruhi sistem dan metode POST adalah peringatan.


Yang saya maksud dengan menandai adalah melacak catatan mana yang diproses dan dikembalikan sehingga panggilan berikutnya tidak mengulanginya. Dalam kasus saya, saya hanya membuat sisipan ke tabel lain untuk melacak yang diproses.
sig606

Saat ini saya menerapkannya sebagai POST terutama karena alasan yang Anda katakan - tindakan terjadi dan konsumen menyadarinya. Selain itu, tampaknya mudah dan paling fleksibel
sehubungan dengan penyampaian

@ sig606: POST adalah cara terbaik bagi saya, tetapi protokol Anda tampaknya tidak aman. Bagaimana jika sesuatu terjadi dan catatan diambil di sisi klien, tetapi tidak diproses karena bug? Anda tidak akan mengembalikannya lagi dan klien memiliki data yang hilang.
LukLed

Saat ini API saya hanya mengembalikan catatan setelah diproses. Jadi konsumen melewati API dua tanggal. Catatan antara dua tanggal tersebut diproses dan ditandai. Kemudian data tersebut dikembalikan ke pemanggil. Saya kira jika sesuatu terjadi selama pemrosesan atau setelah pemrosesan sebelum mencapai klien, saya punya masalah.
sig606

144

Menurut saya cara termudah adalah dengan menggunakan AttributeRouting.

Sudah jelas dalam pengontrol Anda, mengapa Anda menginginkan ini di WebApiConfigfile Global Anda ?

Contoh:

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

The {}nama harus mencocokkan parameter Anda.

Sesederhana itu, sekarang Anda memiliki pemisah GETyang menangani beberapa parameter dalam contoh ini.


12
Ini bagus. Kebanyakan orang menyarankan untuk mengatur rute dalam WebApiConfigfile tersebut, tetapi ini memang lebih bagus.
rhyek

4
Memang, kami (kebanyakan orang) merekomendasikan memiliki area manajemen terpusat untuk konfigurasi Anda. Dalam kasus API Web (Microsoft atau lainnya), pola terpusat untuk REST adalah kuncinya. Perutean atribut memang lucu, tetapi membuat pengecualian satu kali terlalu menggoda.
David Betz

3
Setuju, sebenarnya saya perlu memperbarui jawaban saya. Ada cara yang jauh lebih baik untuk melakukan banyak parameter dengan GET. Memposting ini ketika saya masih baru di WebAPI, sekarang saya tidak menggunakan AttributeRouting (kecuali saya hanya tidak ingin membuat Controller baru), dan meneruskan semua Parameter di QueryString, mereka memetakan secara otomatis. Memperbarui ketika saya mendapat kesempatan sehingga orang tidak menggunakan metode yang lebih lama ini
Mark Pieszak - Trilon.io

Apakah ada cara untuk menyetel Routeparameter bernama (misalnya parameter kueri)?
Shimmy Weitzhandler

1
Jika nama metode tindakan diperlukan, ini dapat dimodifikasi untuk mengakomodasi itu. [Route ("api / YOURCONTROLLER / Get / {paramOne} / {paramTwo}")] string publik Dapatkan (int paramOne, int paramTwo) {return "sesuatu"; }
Dash

49

Cukup tambahkan rute baru ke WebApiConfigentri.

Misalnya, untuk memanggil:

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

Menambahkan:

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

Kemudian tambahkan parameter ke panggilan HTTP:

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

10
Tampaknya ini satu-satunya jawaban yang mencantumkan semua bagian. Saya berharap seseorang menjelaskan dengan lebih baik cara menggunakan api/controller?start=date1&end=date2URI gaya.
Hot Licks

@Hot Licks Jawaban Andrew Veriga bekerja dengan baik dengan argumen string kueri. Pada dasarnya, Anda mengikat nama string kueri ke properti kelas dan meneruskannya ke metode Anda. Metode Anda akan mengambil argumen kelas tunggal yang ditandai dengan atribut [FromUri] dan akan memiliki argumen string kueri Anda sebagai propertinya.
David Peterson

Barang bagus. Terima kasih!
Hugo Nava Kopp

hai @HotLicks dan GrahamWright, apakah Anda dapat menjawab pertanyaan ini? Terima kasih, stackoverflow.com/questions/57565318/…

45

Saya hanya perlu menerapkan RESTfull api di mana saya harus meneruskan parameter. Saya melakukan ini dengan meneruskan parameter dalam string kueri dengan gaya yang sama seperti yang dijelaskan oleh contoh pertama Mark "api / controller? Start = date1 & end = date2"

Di pengontrol saya menggunakan tip dari perpecahan URL di C #?

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

Dalam kasus saya, saya memanggil WebApi melalui Ajax dengan tampilan seperti:

$.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');
                       }
        }
   });

Saya harap ini membantu...


2
Saya kira Anda tidak menggunakan WebApi karena ParameterBinding akan memetakan string kueri Anda ke parameter metode api Anda secara otomatis ...
emp

1
Ya, cara yang lebih baik adalah dengan menggunakan dan atribut seperti [Route ("api / DbMetaData / {system} / {searchString}")] dan kemudian menambahkan parameter ke Get (string system, string searchString) dan kemudian memanggil dengan " ... api / DbMetaData / mysystem / mysearchstring "
Nigel Findlater

Saya menggunakan contohnya di C # MVC WebApi saya dan itu berfungsi dengan baik. +1 misalnya
Si8

38

Saya menemukan solusi yang sangat baik di 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
Petunjuk di sini adalah [FromUri]
tranceporter

2
Meskipun artikel itu dalam bahasa Rusia, @tranceporter benar. "FromUri" sepertinya cara yang bagus untuk mendapatkan parameter dari url. Artikel lain yang mungkin bisa membantu: asp.net/web-api/overview/formats-and-model-binding/…
Greg

Inilah yang telah saya lakukan cukup lama sekarang dan berhasil dengan baik! Saya juga merekomendasikan solusi ini.
David Peterson

Jika Anda memanggil ke metode pembantu lain (bukan Get), apakah Anda masih dapat menggunakan [FromUri]? Saya tidak bisa membuatnya bekerja.
bercanda

8

Menggunakan GET atau POST dijelaskan dengan jelas oleh @LukLed . Mengenai cara Anda dapat menyampaikan parameter, saya sarankan untuk menggunakan pendekatan kedua (saya juga tidak tahu banyak tentang ODATA ).

1. Menserialisasi params ke dalam satu string JSON dan memilihnya secara terpisah di API. http://forums.asp.net/t/1807316.aspx/1

Ini tidak ramah pengguna dan ramah SEO

2. Lewati params dalam string kueri. Apa cara terbaik untuk meneruskan beberapa parameter kueri ke restful api?

Ini adalah pendekatan yang lebih disukai biasa.

3. Mendefinisikan params di rute: api / controller / date1 / date2

Ini jelas bukan pendekatan yang baik. Hal ini membuat seseorang merasa bahwa seseorang date2adalah sub sumber dari date1dan bukan itu masalahnya. Baik date1dan date2parameter query dan datang dalam tingkat yang sama.

Dalam kasus sederhana, saya akan menyarankan URI seperti ini,

api/controller?start=date1&end=date2

Tetapi saya pribadi menyukai pola URI di bawah ini tetapi dalam hal ini kita harus menulis beberapa kode khusus untuk memetakan parameter.

api/controller/date1,date2

Sebenarnya, itulah penjelasan awal saya. Saya pikir LukLed menyempurnakan tag dan tautan URL saya.
sig606

Sejauh SEO, dalam hal ini tidak akan berlaku. Kode ini akan menjadi "server-ke-server", jadi saya tidak akan peduli jika dunia luar pernah menemukannya. Sebenarnya, saya harus memastikan langkah-langkah keamanan yang tepat diambil untuk menghindari akses acak. Saya harus melakukan serialisasi JSON untuk bagian lain dari sistem (tampaknya merupakan bug yang mencoba POST daftar besar dari objek jadi saya harus membuat serial ke string), jadi tidak akan terlalu merepotkan dalam kasus ini .
sig606

1
Saya harap Anda sudah memiliki jawaban lalu mengapa Anda mengajukan pertanyaan?
VJAI

2
Maaf atas tanggapan yang terlambat ini, Mark. Saya telah mencoba beberapa solusi tetapi tidak yakin mana yang terbaik dan mencoba untuk tetap menggunakan pendekatan standar industri, jadi saya memposting di sini di SO.
sig606

1
@ Tandai Sesuatu seperti berikut ini: stackoverflow.com/questions/9681658/… ?
RredCat


4
 [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 ";
    }

Kedua parameter dari tautan root ({one}, {two}) dan Get function parameter (satu, dua) harus sama


2

Saya tahu ini sangat tua, tetapi saya menginginkan hal yang sama baru-baru ini dan inilah yang saya temukan ...

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

Jadi sekarang di alamat Anda / URI / ...

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

Hasil: "Found Test"


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

Hasil: "Can't Find that test"


Saya pribadi menyukai gaya ini di C #, karena saya dapat mengubah tanda tangan dari metode asli, dan membebani dengan tepat apa yang ingin saya capai, tanpa mengubah konfigurasi perutean. Semoga dapat membantu orang lain yang terbiasa dengan pendekatan (mungkin kuno) ini dalam membuat permintaan GET.
Rick Riggs

1
Saya harus membuat API acara yang digunakan oleh aplikasi kalender pihak ketiga, yang menggunakan pendekatan ini. Saya senang saya menemukan jawaban ini!
clayRay


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");
            }
        }
    }
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.