Prise en charge de BSON dans API Web ASP.NET 2.1

Cette rubrique montre comment utiliser BSON dans votre contrôleur d’API web (côté serveur) et dans une application cliente .NET. Web API 2.1 introduit la prise en charge de BSON.

Qu’est-ce que BSON ?

BSON est un format de sérialisation binaire. « BSON » signifie « Binary JSON », mais BSON et JSON sont sérialisés très différemment. BSON est « de type JSON », car les objets sont représentés sous forme de paires nom-valeur, similaires à JSON. Contrairement à JSON, les types de données numériques sont stockés sous forme d’octets, et non de chaînes

BSON a été conçu pour être léger, facile à analyser et rapide à encoder/décoder.

  • La taille de BSON est comparable à JSON. Selon les données, une charge utile BSON peut être plus modeste ou plus volumineuse qu’une charge utile JSON. Pour sérialiser des données binaires, telles qu’un fichier image, BSON est plus petit que JSON, car les données binaires ne sont pas encodées en base64.
  • Les documents BSON sont faciles à analyser, car les éléments sont préfixés avec un champ de longueur, de sorte qu’un analyseur peut ignorer des éléments sans les décoder.
  • L’encodage et le décodage sont efficaces, car les types de données numériques sont stockés sous forme de nombres, et non de chaînes.

Les clients natifs, tels que les applications clientes .NET, peuvent tirer parti de l’utilisation de BSON à la place de formats textuels tels que JSON ou XML. Pour les clients de navigateur, vous voudrez probablement vous en tenir à JSON, car JavaScript peut convertir directement la charge utile JSON.

Heureusement, l’API web utilise la négociation de contenu, de sorte que votre API peut prendre en charge les deux formats et laisser le client choisir.

Activation de BSON sur le serveur

Dans votre configuration d’API web, ajoutez BsonMediaTypeFormatter à la collection des formateurs.

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

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

Maintenant, si le client demande « application/bson », l’API web utilise le formateur BSON.

Pour associer BSON à d’autres types de médias, ajoutez-les à la collection SupportedMediaTypes. Le code suivant ajoute « application/vnd.contoso » aux types de médias pris en charge :

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

Exemple de session HTTP

Pour cet exemple, nous allons utiliser la classe de modèle suivante ainsi qu’un contrôleur d’API web simple :

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 peut envoyer la requête HTTP suivante :

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

Voici la réponse :

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

Ici, j’ai remplacé les données binaires par les caractères « ». La capture d’écran suivante de Fiddler montre les valeurs hexadécimal brutes.

Capture d’écran d’un volet de fenêtre montrant les valeurs hexadécimal brutes des données binaires dans les couleurs vertes en haut et au milieu, et en noir en bas.

Utilisation de BSON avec HttpClient

Les applications clientes .NET peuvent utiliser le formateur BSON avec HttpClient. Pour plus d’informations sur HttpClient, consultez Appel d’une API web à partir d’un client .NET.

Le code suivant envoie une requête GET qui accepte BSON, puis désérialise la charge utile BSON dans la réponse.

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

Pour demander BSON à partir du serveur, définissez l’en-tête Accepter sur « application/bson » :

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

Pour désérialiser le corps de la réponse, utilisez le BsonMediaTypeFormatter. Ce formateur ne se trouve pas dans la collection des formateurs par défaut. Vous devez donc le spécifier lorsque vous lisez le corps de la réponse :

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

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

L’exemple suivant montre comment envoyer une requête POST qui contient 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();
    }
}

Une grande partie de ce code est identique à l’exemple précédent. Mais dans la méthode PostAsync , spécifiez BsonMediaTypeFormatter comme formateur :

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

Sérialisation Top-Level types primitifs

Chaque document BSON est une liste de paires clé/valeur. La spécification BSON ne définit pas de syntaxe pour sérialiser une valeur brute unique, telle qu’un entier ou une chaîne.

Pour contourner cette limitation, BsonMediaTypeFormatter traite les types primitifs comme un cas spécial. Avant de sérialiser, elle convertit la valeur en paire clé/valeur avec la clé « Value ». Par exemple, supposons que votre contrôleur d’API retourne un entier :

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

Avant de sérialiser, le formateur BSON le convertit en la paire clé/valeur suivante :

{ "Value": 42 }

Lorsque vous désérialisez, le formateur reconvertit les données en valeur d’origine. Toutefois, les clients utilisant un autre analyseur BSON devront gérer ce cas, si votre API web retourne des valeurs brutes. En général, vous devez envisager de retourner des données structurées, plutôt que des valeurs brutes.

Ressources supplémentaires

Exemple BSON de l’API web

Formateurs multimédias