Bagikan melalui


Media Formatters di ASP.NET Web API 2

Tutorial ini menunjukkan cara mendukung format media tambahan di ASP.NET Web API.

Tipe Media Internet

Jenis media, juga disebut jenis MIME, mengidentifikasi format sepotong data. Di HTTP, jenis media menjelaskan format isi pesan. Jenis media terdiri dari dua string, jenis dan subjenis. Contohnya:

  • text/html
  • gambar/png
  • application/json

Saat pesan HTTP berisi isi entitas, header Content-Type menentukan format isi pesan. Ini memberi tahu penerima cara mengurai konten isi pesan.

Misalnya, jika respons HTTP berisi gambar PNG, respons mungkin memiliki header berikut.

HTTP/1.1 200 OK
Content-Length: 95267
Content-Type: image/png

Saat klien mengirim pesan permintaan, klien dapat menyertakan header Terima. Header Terima memberi tahu server jenis media mana yang diinginkan klien dari server. Contohnya:

Accept: text/html,application/xhtml+xml,application/xml

Header ini memberi tahu server bahwa klien menginginkan HTML, XHTML, atau XML.

Jenis media menentukan bagaimana Web API menserialisasikan dan mendeserialisasi isi pesan HTTP. Web API memiliki dukungan bawaan untuk data XML, JSON, BSON, dan form-urlencoded, dan Anda dapat mendukung jenis media tambahan dengan menulis pemformat media.

Untuk membuat pemformat media, berasal dari salah satu kelas berikut:

Berasal dari BufferedMediaTypeFormatter lebih sederhana, karena tidak ada kode asinkron, tetapi itu juga berarti utas panggilan dapat memblokir selama I/O.

Contoh: Membuat CSV Media Formatter

Contoh berikut menunjukkan pemformat jenis media yang dapat membuat serialisasi objek Produk ke format nilai yang dipisahkan koma (CSV). Contoh ini menggunakan Jenis produk yang ditentukan dalam tutorial Membuat API Web yang Mendukung Operasi CRUD. Berikut adalah definisi objek Produk:

namespace ProductStore.Models
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Category { get; set; }
        public decimal Price { get; set; }
    }
}

Untuk mengimplementasikan pemformat CSV, tentukan kelas yang berasal dari BufferedMediaTypeFormatter:

using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using ProductStore.Models;

namespace ProductStore.Formatters
{
    public class ProductCsvFormatter : BufferedMediaTypeFormatter
    {
    }
}

Di konstruktor, tambahkan jenis media yang didukung pemformat. Dalam contoh ini, formatter mendukung satu jenis media, "text/csv":

public ProductCsvFormatter()
{
    // Add the supported media type.
    SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/csv"));
}

Ambil alih metode CanWriteType untuk menunjukkan jenis pemformat mana yang dapat diserialisasikan:

public override bool CanWriteType(System.Type type)
{
    if (type == typeof(Product))
    {
        return true;
    }
    else
    {
        Type enumerableType = typeof(IEnumerable<Product>);
        return enumerableType.IsAssignableFrom(type);
    }
}

Dalam contoh ini, pemformat dapat membuat serialisasi objek tunggal Product serta koleksi Product objek.

Demikian pula, ganti metode CanReadType untuk menunjukkan jenis pemformat mana yang dapat mendeserialisasi. Dalam contoh ini, pemformat tidak mendukung deserialisasi, sehingga metode hanya mengembalikan false.

public override bool CanReadType(Type type)
{
    return false;
}

Terakhir, ganti metode WriteToStream . Metode ini menserialisasikan jenis dengan menuliskannya ke aliran. Jika pemformat Anda mendukung deserialisasi, ganti juga metode ReadFromStream .

public override void WriteToStream(Type type, object value, Stream writeStream, HttpContent content)
{
    using (var writer = new StreamWriter(writeStream))
    {
        var products = value as IEnumerable<Product>;
        if (products != null)
        {
            foreach (var product in products)
            {
                WriteItem(product, writer);
            }
        }
        else
        {
            var singleProduct = value as Product;
            if (singleProduct == null)
            {
                throw new InvalidOperationException("Cannot serialize type");
            }
            WriteItem(singleProduct, writer);
        }
    }
}

// Helper methods for serializing Products to CSV format. 
private void WriteItem(Product product, StreamWriter writer)
{
    writer.WriteLine("{0},{1},{2},{3}", Escape(product.Id),
        Escape(product.Name), Escape(product.Category), Escape(product.Price));
}

static char[] _specialChars = new char[] { ',', '\n', '\r', '"' };

private string Escape(object o)
{
    if (o == null)
    {
        return "";
    }
    string field = o.ToString();
    if (field.IndexOfAny(_specialChars) != -1)
    {
        // Delimit the entire field with quotes and replace embedded quotes with "".
        return String.Format("\"{0}\"", field.Replace("\"", "\"\""));
    }
    else return field;
}

Menambahkan Media Formatter ke Alur API Web

Untuk menambahkan pemformat jenis media ke alur API Web, gunakan properti Formatters pada objek HttpConfiguration .

public static void ConfigureApis(HttpConfiguration config)
{
    config.Formatters.Add(new ProductCsvFormatter()); 
}

Pengodean Karakter

Secara opsional, pemformat media dapat mendukung beberapa pengodean karakter, seperti UTF-8 atau ISO 8859-1.

Di konstruktor, tambahkan satu atau beberapa jenis System.Text.Encoding ke koleksi SupportedEncodings . Letakkan pengodean default terlebih dahulu.

public ProductCsvFormatter()
{
    SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/csv"));

    // New code:
    SupportedEncodings.Add(new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
    SupportedEncodings.Add(Encoding.GetEncoding("iso-8859-1"));
}

Dalam metode WriteToStream dan ReadFromStream , panggil MediaTypeFormatter.SelectCharacterEncoding untuk memilih pengodean karakter pilihan. Metode ini cocok dengan header permintaan dengan daftar pengodean yang didukung. Gunakan Pengodean yang dikembalikan saat Anda membaca atau menulis dari aliran:

public override void WriteToStream(Type type, object value, Stream writeStream, HttpContent content)
{
    Encoding effectiveEncoding = SelectCharacterEncoding(content.Headers);

    using (var writer = new StreamWriter(writeStream, effectiveEncoding))
    {
        // Write the object (code not shown)
    }
}