Suporte a BSON no ASP.NET Web API 2.1

Este tópico mostra como usar o BSON em seu controlador de API Web (lado do servidor) e em um aplicativo cliente .NET. A API Web 2.1 apresenta suporte para BSON.

O que é BSON?

BSON é um formato de serialização binária. "BSON" significa "JSON binário", mas BSON e JSON são serializados de maneira muito diferente. BSON é "semelhante a JSON", porque os objetos são representados como pares nome-valor, semelhantes ao JSON. Ao contrário do JSON, os tipos de dados numéricos são armazenados como bytes, não cadeias de caracteres

O BSON foi projetado para ser leve, fácil de examinar e rápido para codificar/decodificar.

  • O BSON é comparável em tamanho ao JSON. Dependendo dos dados, uma carga BSON pode ser menor ou maior do que uma carga JSON. Para serializar dados binários, como um arquivo de imagem, o BSON é menor que o JSON, pois os dados binários não são codificados em base64.
  • Documentos BSON são fáceis de examinar porque os elementos são prefixados com um campo de comprimento, portanto, um analisador pode ignorar elementos sem decodificar.
  • A codificação e a decodificação são eficientes, pois os tipos de dados numéricos são armazenados como números, não cadeias de caracteres.

Clientes nativos, como aplicativos cliente .NET, podem se beneficiar do uso de BSON no lugar de formatos baseados em texto, como JSON ou XML. Para clientes de navegador, você provavelmente desejará manter o JSON, pois o JavaScript pode converter diretamente o conteúdo JSON.

Felizmente, a API Web usa a negociação de conteúdo, para que sua API possa dar suporte a ambos os formatos e permitir que o cliente escolha.

Habilitando o BSON no servidor

Na configuração da API Web, adicione o BsonMediaTypeFormatter à coleção formatadores.

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

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

Agora, se o cliente solicitar "application/bson", a API Web usará o formatador BSON.

Para associar o BSON a outros tipos de mídia, adicione-os à coleção SupportedMediaTypes. O código a seguir adiciona "application/vnd.contoso" aos tipos de mídia com suporte:

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

Exemplo de sessão HTTP

Para este exemplo, usaremos a seguinte classe de modelo mais um controlador de API Web simples:

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

Um cliente pode enviar a seguinte solicitação HTTP:

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

Esta é a resposta:

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.........

Aqui, substituí os dados binários por caracteres ".". A captura de tela a seguir do Fiddler mostra os valores hexadecimais brutos.

Captura de tela de um painel de janela mostrando os valores hexadecimais brutos dos dados binários nas cores verde na parte superior e no meio e preto na parte inferior.

Usando BSON com HttpClient

Os aplicativos de clientes .NET podem usar o formatador BSON com HttpClient. Para obter mais informações sobre HttpClient, consulte Chamando uma API Web de um cliente .NET.

O código a seguir envia uma solicitação GET que aceita BSON e desserializa o conteúdo BSON na resposta.

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

Para solicitar o BSON do servidor, defina o cabeçalho Accept como "application/bson":

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

Para desserializar o corpo da resposta, use o BsonMediaTypeFormatter. Esse formatador não está na coleção de formatadores padrão, portanto, você precisa especificá-lo ao ler o corpo da resposta:

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

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

O exemplo a seguir mostra como enviar uma solicitação POST que contém 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();
    }
}

Grande parte desse código é igual ao exemplo anterior. Mas no método PostAsync , especifique BsonMediaTypeFormatter como o formatador:

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

Serializando tipos primitivos Top-Level

Cada documento BSON é uma lista de pares chave/valor. A especificação BSON não define uma sintaxe para serializar um único valor bruto, como um inteiro ou uma cadeia de caracteres.

Para contornar essa limitação, o BsonMediaTypeFormatter trata tipos primitivos como um caso especial. Antes de serializar, ele converte o valor em um par chave/valor com a chave "Value". Por exemplo, suponha que o controlador de API retorne um inteiro:

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

Antes de serializar, o formatador BSON converte isso no seguinte par chave/valor:

{ "Value": 42 }

Quando você desserializa, o formatador converte os dados de volta para o valor original. No entanto, os clientes que usam um analisador BSON diferente precisarão lidar com esse caso, se a API Web retornar valores brutos. Em geral, você deve considerar o retorno de dados estruturados, em vez de valores brutos.

Recursos adicionais

Exemplo de BSON da API Web

Formatadores de mídia