Bagikan melalui


Negosiasi Konten di API Web ASP.NET

Artikel ini menjelaskan bagaimana ASP.NET Web API menerapkan negosiasi konten untuk ASP.NET 4.x.

Spesifikasi HTTP (RFC 2616) mendefinisikan negosiasi konten sebagai "proses memilih representasi terbaik untuk respons tertentu ketika ada beberapa representasi yang tersedia." Mekanisme utama untuk negosiasi konten di HTTP adalah header permintaan ini:

  • Menerima: Jenis media mana yang dapat diterima untuk respons, seperti "application/json," "application/xml," atau jenis media kustom seperti "application/vnd.example+xml"
  • Accept-Charset: Set karakter mana yang dapat diterima, seperti UTF-8 atau ISO 8859-1.
  • Accept-Encoding: Pengodean konten mana yang dapat diterima, seperti gzip.
  • Terima-Bahasa: Bahasa alami pilihan, seperti "en-us".

Server juga dapat melihat bagian lain dari permintaan HTTP. Misalnya, jika permintaan berisi header X-Requested-With, yang menunjukkan permintaan AJAX, server mungkin default ke JSON jika tidak ada header Terima.

Dalam artikel ini, kita akan melihat bagaimana Api Web menggunakan header Terima dan Accept-Charset. (Saat ini, tidak ada dukungan bawaan untuk Accept-Encoding atau Accept-Language.)

Serialisasi

Jika pengontrol Api Web mengembalikan sumber daya sebagai jenis CLR, alur akan membuat serialisasi nilai pengembalian dan menulisnya ke dalam isi respons HTTP.

Misalnya, pertimbangkan tindakan pengontrol berikut:

public Product GetProduct(int id)
{
    var item = _products.FirstOrDefault(p => p.ID == id);
    if (item == null)
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }
    return item; 
}

Klien mungkin mengirim permintaan HTTP ini:

GET http://localhost.:21069/api/products/1 HTTP/1.1
Host: localhost.:21069
Accept: application/json, text/javascript, */*; q=0.01

Sebagai tanggapan, server mungkin mengirim:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 57
Connection: Close

{"Id":1,"Name":"Gizmo","Category":"Widgets","Price":1.99}

Dalam contoh ini, klien meminta JSON, Javascript, atau "apa pun" (*/*). Server merespons dengan representasi JSON dari Product objek . Perhatikan bahwa header Jenis Konten dalam respons diatur ke "application/json".

Pengontrol juga dapat mengembalikan objek HttpResponseMessage . Untuk menentukan objek CLR untuk isi respons, panggil metode ekstensi CreateResponse :

public HttpResponseMessage GetProduct(int id)
{
    var item = _products.FirstOrDefault(p => p.ID == id);
    if (item == null)
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }
    return Request.CreateResponse(HttpStatusCode.OK, item);
}

Opsi ini memberi Anda lebih banyak kontrol atas detail respons. Anda dapat mengatur kode status, menambahkan header HTTP, dan sebagainya.

Objek yang menserialisasikan sumber daya disebut pemformat media. Pemformat media berasal dari kelas MediaTypeFormatter . API Web menyediakan pemformat media untuk XML dan JSON, dan Anda dapat membuat pemformat kustom untuk mendukung jenis media lainnya. Untuk informasi tentang menulis pemformat kustom, lihat Media Formatters.

Cara Kerja Negosiasi Konten

Pertama, alur mendapatkan layanan IContentNegotiator dari objek HttpConfiguration . Ini juga mendapatkan daftar pemformat media dari koleksi HttpConfiguration.Formatters .

Selanjutnya, alur memanggil IContentNegotiator.Negotiate, meneruskan:

  • Jenis objek yang akan diserialisasikan
  • Kumpulan pemformat media
  • Permintaan HTTP

Metode Negosiasi mengembalikan dua informasi:

  • Pemformat mana yang akan digunakan
  • Jenis media untuk respons

Jika tidak ada pemformat yang ditemukan, metode Negosiasi mengembalikan null, dan klien menerima kesalahan HTTP 406 (Tidak Dapat Diterima).

Kode berikut menunjukkan bagaimana pengontrol dapat langsung memanggil negosiasi konten:

public HttpResponseMessage GetProduct(int id)
{
    var product = new Product() 
        { Id = id, Name = "Gizmo", Category = "Widgets", Price = 1.99M };

    IContentNegotiator negotiator = this.Configuration.Services.GetContentNegotiator();

    ContentNegotiationResult result = negotiator.Negotiate(
        typeof(Product), this.Request, this.Configuration.Formatters);
    if (result == null)
    {
        var response = new HttpResponseMessage(HttpStatusCode.NotAcceptable);
        throw new HttpResponseException(response));
    }

    return new HttpResponseMessage()
    {
        Content = new ObjectContent<Product>(
            product,		        // What we are serializing 
            result.Formatter,           // The media formatter
            result.MediaType.MediaType  // The MIME type
        )
    };
}

Kode ini setara dengan apa yang dilakukan alur secara otomatis.

Negosiator Konten Default

Kelas DefaultContentNegotiator menyediakan implementasi default IContentNegotiator. Ini menggunakan beberapa kriteria untuk memilih pemformat.

Pertama, pemformat harus dapat membuat serialisasi jenis. Ini diverifikasi dengan memanggil MediaTypeFormatter.CanWriteType.

Selanjutnya, negosiator konten melihat setiap pemformat dan mengevaluasi seberapa baik cocok dengan permintaan HTTP. Untuk mengevaluasi kecocokan, negosiator konten melihat dua hal pada pemformat:

  • Kumpulan SupportedMediaTypes , yang berisi daftar jenis media yang didukung. Negosiator konten mencoba mencocokkan daftar ini dengan header Terima permintaan. Perhatikan bahwa header Terima dapat menyertakan rentang. Misalnya, "text/plain" adalah kecocokan untuk teks/* atau */*.
  • Koleksi MediaTypeMappings , yang berisi daftar objek MediaTypeMapping . Kelas MediaTypeMapping menyediakan cara umum untuk mencocokkan permintaan HTTP dengan jenis media. Misalnya, dapat memetakan header HTTP kustom ke jenis media tertentu.

Jika ada beberapa pertandingan, pertandingan dengan faktor kualitas tertinggi menang. Contohnya:

Accept: application/json, application/xml; q=0.9, */*; q=0.1

Dalam contoh ini, aplikasi/json memiliki faktor kualitas tersirat 1.0, sehingga lebih disukai daripada aplikasi/xml.

Jika tidak ada kecocokan yang ditemukan, negosiator konten mencoba mencocokkan pada jenis media isi permintaan, jika ada. Misalnya, jika permintaan berisi data JSON, negosiator konten mencari pemformat JSON.

Jika masih tidak ada kecocokan, negosiator konten hanya memilih formatter pertama yang dapat menserialisasikan jenis.

Memilih Pengodean Karakter

Setelah pemformat dipilih, negosiator konten memilih pengodean karakter terbaik dengan melihat properti SupportedEncodings pada pemformat, dan mencocokkannya dengan header Accept-Charset dalam permintaan (jika ada).