Condividi tramite


Supporto BSON nell'API Web ASP.NET 2.1

Questo argomento illustra come usare BSON nel controller API Web (lato server) e in un'app client .NET. L'API Web 2.1 introduce il supporto per BSON.

Che cos'è BSON?

BSON è un formato di serializzazione binaria. "BSON" è l'acronimo di "Binary JSON", ma BSON e JSON vengono serializzati in modo molto diverso. BSON è simile a JSON, perché gli oggetti sono rappresentati come coppie nome-valore, simili a JSON. A differenza di JSON, i tipi di dati numerici vengono archiviati come byte, non come stringhe

BSON è stato progettato per essere leggero, facile da analizzare e veloce da codificare/decodificare.

  • BSON è paragonabile alle dimensioni di JSON. A seconda dei dati, un payload BSON può essere minore o maggiore di un payload JSON. Per la serializzazione dei dati binari, ad esempio un file di immagine, BSON è minore di JSON, perché i dati binari non sono codificati in base64.
  • I documenti BSON sono facili da analizzare perché gli elementi sono preceduti da un campo di lunghezza, quindi un parser può ignorare gli elementi senza decodificarli.
  • La codifica e la decodifica sono efficienti, perché i tipi di dati numerici vengono archiviati come numeri, non stringhe.

I client nativi, ad esempio le app client .NET, possono trarre vantaggio dall'uso di BSON al posto di formati basati su testo, ad esempio JSON o XML. Per i client browser, è probabile che si voglia usare JSON, perché JavaScript può convertire direttamente il payload JSON.

Fortunatamente, l'API Web usa la negoziazione del contenuto, in modo che l'API possa supportare entrambi i formati e consentire al client di scegliere.

Abilitazione di BSON nel server

Nella configurazione dell'API Web aggiungere BsonMediaTypeFormatter alla raccolta di formattatori.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Formatters.Add(new BsonMediaTypeFormatter());

        // Other Web API configuration not shown...
    }
}

A questo punto, se il client richiede "application/bson", l'API Web userà il formattatore BSON.

Per associare BSON ad altri tipi di media, aggiungerli all'insieme SupportedMediaTypes. Il codice seguente aggiunge "application/vnd.contoso" ai tipi di media supportati.

var bson = new BsonMediaTypeFormatter();
bson.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/vnd.contoso"));
config.Formatters.Add(bson);

Esempio di sessione HTTP

Per questo esempio si userà la classe di modello seguente e un semplice controller API Web:

public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Author { get; set; }
    public decimal Price { get; set; }
    public DateTime PublicationDate { get; set; }
}

public class BooksController : ApiController
{
    public IHttpActionResult GetBook(int id)
    {
        var book = new Book()
        {
            Id = id,
            Author = "Charles Dickens",
            Title = "Great Expectations",
            Price = 9.95M,
            PublicationDate = new DateTime(2014, 1, 20)
        };

        return Ok(book);
    }
}

Un client potrebbe inviare la richiesta HTTP seguente:

GET http://localhost:15192/api/books/1 HTTP/1.1
User-Agent: Fiddler
Host: localhost:15192
Accept: application/bson

Ecco la risposta:

HTTP/1.1 200 OK
Content-Type: application/bson; charset=utf-8
Date: Fri, 17 Jan 2014 01:05:40 GMT
Content-Length: 111

.....Id......Title.....Great Expectations..Author.....Charles Dickens..Price..........PublicationDate.........

Qui ho sostituito i dati binari con caratteri ".". La schermata seguente di Fiddler mostra i valori esadecimali non elaborati.

Screenshot di un riquadro della finestra che mostra i valori esadecimali non elaborati dei dati binari nei colori verdi nella parte superiore e centrale e nero nella parte inferiore.

Uso di BSON con HttpClient

Le app client .NET possono usare il formattatore BSON con HttpClient. Per altre informazioni su HttpClient, vedere Chiamata di un'API Web da un client .NET.

Il codice seguente invia una richiesta GET che accetta BSON e quindi deserializza il payload BSON nella risposta.

static async Task RunAsync()
{
    using (HttpClient client = new HttpClient())
    {
        client.BaseAddress = new Uri("http://localhost");

        // Set the Accept header for BSON.
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/bson"));

        // Send GET request.
        result = await client.GetAsync("api/books/1");
        result.EnsureSuccessStatusCode();

        // Use BSON formatter to deserialize the result.
        MediaTypeFormatter[] formatters = new MediaTypeFormatter[] {
            new BsonMediaTypeFormatter()
        };

        var book = await result.Content.ReadAsAsync<Book>(formatters);
    }
}

Per richiedere BSON dal server, impostare l'intestazione Accept su "application/bson":

client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new  
    MediaTypeWithQualityHeaderValue("application/bson"));

Per deserializzare il corpo della risposta, usare BsonMediaTypeFormatter. Questo formattatore non si trova nell'insieme dei formattatori predefiniti, quindi è necessario specificarlo quando si legge il corpo della risposta:

MediaTypeFormatter[] formatters = new MediaTypeFormatter[] {
    new BsonMediaTypeFormatter()
};

var book = await result.Content.ReadAsAsync<Book>(formatters);

L'esempio seguente illustra come inviare una richiesta POST contenente BSON.

static async Task RunAsync()
{
    using (HttpClient client = new HttpClient())
    {
        client.BaseAddress = new Uri("http://localhost:15192");

        // Set the Accept header for BSON.
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/bson"));

        var book = new Book()
        {
            Author = "Jane Austen",
            Title = "Emma",
            Price = 9.95M,
            PublicationDate = new DateTime(1815, 1, 1)
        };

        // POST using the BSON formatter.
        MediaTypeFormatter bsonFormatter = new BsonMediaTypeFormatter();
        var result = await client.PostAsync("api/books", book, bsonFormatter);
        result.EnsureSuccessStatusCode();
    }
}

Gran parte di questo codice è uguale all'esempio precedente. Ma nel metodo PostAsync specificare BsonMediaTypeFormatter come formattatore:

MediaTypeFormatter bsonFormatter = new BsonMediaTypeFormatter();
var result = await client.PostAsync("api/books", book, bsonFormatter);

Serializzazione dei tipi primitivi di alto livello

Ogni documento BSON è un elenco di coppie chiave/valore. La specifica BSON non definisce una sintassi per la serializzazione di un singolo valore non elaborato, ad esempio un numero intero o una stringa.

Per ovviare a questa limitazione, BsonMediaTypeFormatter considera i tipi primitivi come un caso speciale. Prima della serializzazione, converte il valore in una coppia chiave/valore con la chiave "Value". Si supponga, ad esempio, che il controller API restituisca un numero intero:

public class ValuesController : ApiController
{
    public IHttpActionResult Get()
    {
        return Ok(42);
    }
}

Prima della serializzazione, il formattatore BSON converte questo valore nella coppia chiave/valore seguente:

{ "Value": 42 }

Quando si deserializza, il formattatore converte nuovamente i dati nel valore originale. Tuttavia, i client che usano un parser BSON diverso dovranno gestire questo caso, se l'API Web restituisce valori non elaborati. In generale, è consigliabile restituire dati strutturati anziché valori non elaborati.

Risorse aggiuntive

Esempio BSON dell'API Web

Formattatori multimediali