Formátovací moduly médií ve webovém rozhraní API ASP.NET 2

V tomto kurzu se dozvíte, jak ve webovém rozhraní API ASP.NET podporovat další formáty médií.

Typy internetových médií

Typ média, označovaný také jako typ MIME, identifikuje formát části dat. V protokolu HTTP typy médií popisují formát textu zprávy. Typ média se skládá ze dvou řetězců, typu a podtypu. Příklad:

  • text/html
  • image/png
  • application/json

Pokud zpráva HTTP obsahuje entity-body, hlavička Content-Type určuje formát textu zprávy. Tím sdělíte příjemci, jak analyzovat obsah textu zprávy.

Pokud například odpověď HTTP obsahuje obrázek PNG, může mít odpověď následující hlavičky.

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

Když klient odešle zprávu požadavku, může obsahovat hlavičku Accept. Hlavička Accept informuje server o tom, jaké typy médií klient od serveru požaduje. Příklad:

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

Tato hlavička říká serveru, že klient chce html, XHTML nebo XML.

Typ média určuje, jak webové rozhraní API serializuje a deserializuje tělo zprávy HTTP. Webové rozhraní API má integrovanou podporu dat XML, JSON, BSON a form-urlencoded a další typy médií můžete podporovat zápisem formátovače médií.

Chcete-li vytvořit formátovací médium, odvodit z jedné z těchto tříd:

Odvození z BufferedMediaTypeFormatter je jednodušší, protože neexistuje žádný asynchronní kód, ale také to znamená, že volající vlákno může blokovat během V/V.

Příklad: Vytvoření media formatteru CSV

Následující příklad ukazuje formátovací typ média, který může serializovat product objekt do formátu hodnot oddělených čárkami (CSV). V tomto příkladu se používá typ produktu definovaný v kurzu Vytvoření webového rozhraní API, které podporuje operace CRUD. Tady je definice objektu Product:

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

Pokud chcete implementovat formát CSV, definujte třídu, která je odvozená z 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
    {
    }
}

V konstruktoru přidejte typy médií, které formátovací nástroj podporuje. V tomto příkladu formátovací nástroj podporuje jeden typ média, "text/csv":

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

Přepište metodu CanWriteType a označte, které typy může formátovací modul serializovat:

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

V tomto příkladu může formátovací modul serializovat jednotlivé Product objekty i kolekce Product objektů.

Podobně přepsat CanReadType metoda označit, které typy formatter může deserializovat. V tomto příkladu formátovací nástroj nepodporuje deserializaci, takže metoda jednoduše vrátí hodnotu false.

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

Nakonec přepište metodu WriteToStream . Tato metoda serializuje typ zápisem do datového proudu. Pokud váš formátovací nástroj podporuje deserializaci, přepsat také ReadFromStream metoda.

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

Přidání media Formatteru do kanálu webového rozhraní API

Pokud chcete přidat formátovací typ média do kanálu webového rozhraní API, použijte vlastnost Formatters u objektu HttpConfiguration .

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

Kódování znaků

Volitelně může formátovač médií podporovat více kódování znaků, například UTF-8 nebo ISO 8859-1.

V konstruktoru přidejte jeden nebo více typů System.Text.Encoding do supportedEncodings kolekce. Jako první dejte výchozí kódování.

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

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

V WriteToStream a ReadFromStream metody volání MediaTypeFormatter.SelectCharacterEncoding vybrat upřednostňované kódování znaků. Tato metoda porovnává hlavičky požadavku se seznamem podporovaných kódování. Vrácené kódování použijte při čtení nebo zápisu z datového proudu:

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