Elementy formatujące multimedia w ASP.NET Web API 2

według Jan Wasson

W tym samouczku pokazano, jak obsługiwać dodatkowe formaty multimediów w interfejsie Web API ASP.NET.

Typy multimediów internetowych

Typ nośnika, nazywany również typem MIME, identyfikuje format fragmentu danych. W przypadku protokołu HTTP typy nośników opisują format treści wiadomości. Typ nośnika składa się z dwóch ciągów, typu i podtypu. Na przykład:

  • tekst/HTML
  • image/png
  • application/json

Gdy komunikat HTTP zawiera treść jednostki, nagłówek Content-Type określa format treści komunikatu. To nakazuje odbiorcy analizowanie zawartości treści wiadomości.

Na przykład, jeśli odpowiedź HTTP zawiera obraz PNG, odpowiedzi mogą mieć następujące nagłówki.

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

Gdy klient wysyła komunikat żądania, może zawierać nagłówek Accept. Nagłówek Accept informuje serwer, które typy nośników, których klient chce wykonać z serwera. Na przykład:

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

Ten nagłówek nakazuje serwerowi, że klient chce wykonać kod HTML, XHTML lub XML.

Typ nośnika określa, jak interfejs API sieci Web serializować i deserializacji Treść wiadomości HTTP. Interfejs API sieci Web ma wbudowaną obsługę danych XML, JSON, BSON i form-urlencoded, a także obsługuje dodatkowe typy nośników, pisząc program formatujący multimedia.

Aby utworzyć program formatujący multimedia, należy uzyskać od jednej z następujących klas:

Wyprowadzanie z BufferedMediaTypeFormatter jest prostsze, ponieważ nie istnieje kod asynchroniczny, ale oznacza to również, że wątek wywołujący może blokować podczas operacji we/wy.

Przykład: Tworzenie programu formatującego multimedia w formacie CSV

Poniższy przykład przedstawia program formatujący typ nośnika, który może serializować obiekt produktu do formatu wartości rozdzielanych przecinkami (CSV). W tym przykładzie zastosowano typ produktu zdefiniowany w samouczku Tworzenie interfejsu API sieci Web obsługującego operacje CRUD. Oto Definicja obiektu produkt:

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

Aby zaimplementować program formatujący CSV, zdefiniuj klasę, która pochodzi od 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
    {
    }
}

W konstruktorze Dodaj typy nośników obsługiwane przez program formatujący. W tym przykładzie program formatujący obsługuje pojedynczy typ nośnika, ""tekstu/CSV:

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

Zastąp metodę Nowritetype , aby wskazać, które typy mogą serializować elementy formatującego:

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

W tym przykładzie program formatujący może serializować pojedyncze Product obiekty, a także kolekcje obiektów Product.

Analogicznie Zastąp metodę Unreadtype , aby wskazać, które typy mogą deserializować program formatujący. W tym przykładzie program formatujący nie obsługuje deserializacji, dlatego metoda po prostu zwraca wartość false.

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

Na koniec Zastąp metodę WriteToStream . Ta metoda serializacji typ przez zapisanie go do strumienia. Jeśli program formatujący obsługuje deserializacji, należy również zastąpić metodę 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;
}

Dodawanie programu formatującego multimedia do potoku interfejsu API sieci Web

Aby dodać program formatujący typ nośnika do potoku interfejsu API sieci Web, należy użyć właściwości program formatującegos w obiekcie HttpConfiguration .

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

Kodowania znaków

Opcjonalnie program formatujący multimedia może obsługiwać wiele kodowań znaków, takich jak UTF-8 lub ISO 8859-1.

W konstruktorze Dodaj co najmniej jeden typ System. Text. Encoding do kolekcji SupportedEncodings . Najpierw umieść kodowanie domyślne.

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

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

W metodach WriteToStream i readFromStream Wywołaj MediaTypeFormatter. SelectCharacterEncoding , aby wybrać preferowane kodowanie znaków. Ta metoda dopasowuje nagłówki żądania do listy obsługiwanych kodowań. Podczas odczytu lub zapisu ze strumienia używaj zwracanego kodowania :

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