Condividi tramite


Formati multimediali in API Web ASP.NET 2

Questa esercitazione illustra come supportare formati multimediali aggiuntivi in API Web ASP.NET.

Tipi di supporti Internet

Un tipo di supporto, denominato anche tipo MIME, identifica il formato di un pezzo di dati. In HTTP, i tipi di supporti descrivono il formato del corpo del messaggio. Un tipo di supporto è costituito da due stringhe, un tipo e un sottotipo. Ad esempio:

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

Quando un messaggio HTTP contiene un corpo dell'entità, l'intestazione Content-Type specifica il formato del corpo del messaggio. Questo indica al ricevitore come analizzare il contenuto del corpo del messaggio.

Ad esempio, se una risposta HTTP contiene un'immagine PNG, la risposta potrebbe avere le intestazioni seguenti.

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

Quando il client invia un messaggio di richiesta, può includere un'intestazione Accept. L'intestazione Accept indica al server quali tipi di supporti desiderano dal server. Ad esempio:

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

Questa intestazione indica al server che il client vuole html, XHTML o XML.

Il tipo di supporto determina il modo in cui l'API Web serializza e deserializza il corpo del messaggio HTTP. L'API Web include il supporto predefinito per i dati XML, JSON, BSON e form-urlencoded e è possibile supportare altri tipi di supporto scrivendo un formattatore multimediale.

Per creare un formattatore multimediale, derivare da una di queste classi:

La derivazione da BufferedMediaTypeFormatter è più semplice, perché non esiste codice asincrono, ma significa anche che il thread chiamante può bloccare durante L/O.

Esempio: Creazione di un formattatore multimediale CSV

Nell'esempio seguente viene illustrato un formattatore di tipo multimediale che può serializzare un oggetto Product in un formato con valori delimitati da virgole (CSV). In questo esempio viene usato il tipo Di prodotto definito nell'esercitazione Creazione di un'API Web che supporta operazioni CRUD. Ecco la definizione dell'oggetto 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; }
    }
}

Per implementare un formattatore CSV, definire una classe che deriva da 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
    {
    }
}

Nel costruttore aggiungere i tipi di supporto supportati dal formattatore. In questo esempio il formattatore supporta un singolo tipo di supporto, "text/csv":

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

Eseguire l'override del metodo CanWriteType per indicare quali tipi il formattatore può serializzare:

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

In questo esempio il formattatore può serializzare singoli Product oggetti e raccolte di Product oggetti.

Analogamente, eseguire l'override del metodo CanReadType per indicare quali tipi il formattatore può deserializzare. In questo esempio il formattatore non supporta la deserializzazione, quindi il metodo restituisce semplicemente false.

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

Infine, eseguire l'override del metodo WriteToStream . Questo metodo serializza un tipo scrivendolo in un flusso. Se il formattatore supporta la deserializzazione, eseguire anche l'override del metodo 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;
}

Aggiunta di un formattatore multimediale alla pipeline api Web

Per aggiungere un formattatore di tipo multimediale alla pipeline API Web, usare la proprietà Formatters nell'oggetto HttpConfiguration .

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

Codifica dei caratteri

Facoltativamente, un formattatore multimediale può supportare più codifica di caratteri, ad esempio UTF-8 o ISO 8859-1.

Nel costruttore aggiungere uno o più tipi System.Text.Encoding all'insieme SupportedEncodings . Inserire prima la codifica predefinita.

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

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

Nei metodi WriteToStream e ReadFromStream chiamare MediaTypeFormatter.SelectCharacterEncoding per selezionare la codifica dei caratteri preferita. Questo metodo corrisponde alle intestazioni della richiesta rispetto all'elenco delle codifiche supportate. Usare la codifica restituita quando si legge o si scrive dal flusso:

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