BSON-Unterstützung in ASP.NET-Web-API 2.1

In diesem Thema wird gezeigt, wie Sie BSON in Ihrem Web-API-Controller (serverseitig) und in einer .NET-Client-App verwenden. Die Web-API 2.1 bietet Unterstützung für BSON.

Was ist BSON?

BSON ist ein binäres Serialisierungsformat. "BSON" steht für "Binary JSON", aber BSON und JSON werden sehr unterschiedlich serialisiert. BSON ist "JSON-like", da Objekte als Name-Wert-Paare dargestellt werden, ähnlich wie JSON. Im Gegensatz zu JSON werden numerische Datentypen als Bytes und nicht als Zeichenfolgen gespeichert.

BSON wurde entwickelt, um leicht zu sein, einfach zu scannen und schnell zu codieren/decodieren.

  • BSON ist in der Größe mit JSON vergleichbar. Je nach den Daten kann eine BSON-Nutzlast kleiner oder größer als eine JSON-Nutzlast sein. Zum Serialisieren von Binärdaten, z. B. einer Bilddatei, ist BSON kleiner als JSON, da die Binärdaten nicht base64-codiert sind.
  • BSON-Dokumente sind einfach zu scannen, da Elementen ein Längenfeld vorangestellt ist, sodass ein Parser Elemente überspringen kann, ohne sie zu decodieren.
  • Codierung und Decodierung sind effizient, da numerische Datentypen als Zahlen und nicht als Zeichenfolgen gespeichert werden.

Native Clients, z. B. .NET-Client-Apps, können von der Verwendung von BSON anstelle textbasierter Formate wie JSON oder XML profitieren. Bei Browserclients sollten Sie wahrscheinlich bei JSON bleiben, da JavaScript die JSON-Nutzlast direkt konvertieren kann.

Glücklicherweise verwendet die Web-API Inhaltsverhandlung, sodass Ihre API beide Formate unterstützen und dem Client die Auswahl überlassen kann.

Aktivieren von BSON auf dem Server

Fügen Sie in Ihrer Web-API-Konfiguration den BsonMediaTypeFormatter der Formatter-Auflistung hinzu.

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

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

Wenn der Client nun "application/bson" anfordert, verwendet die Web-API den BSON-Formatierer.

Um BSON anderen Medientypen zuzuordnen, fügen Sie sie der SupportedMediaTypes-Auflistung hinzu. Der folgende Code fügt den unterstützten Medientypen "application/vnd.contoso" hinzu:

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

HTTP-Beispielsitzung

In diesem Beispiel verwenden wir die folgende Modellklasse sowie einen einfachen Web-API-Controller:

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

Ein Client kann die folgende HTTP-Anforderung senden:

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

Hier ist die Antwort:

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

Hier habe ich die Binärdaten durch "." Zeichen ersetzt. Der folgende Screenshot von Fiddler zeigt die unformatierten Sechskantwerte.

Screenshot eines Fensterbereichs mit den unformatierten Hexwerten der Binärdaten in den Farben Grün oben und Mitte und schwarz am unteren Rand.

Verwenden von BSON mit HttpClient

.NET-Client-Apps können den BSON-Formatierer mit HttpClient verwenden. Weitere Informationen zu HttpClient finden Sie unter Aufrufen einer Web-API über einen .NET-Client.

Der folgende Code sendet eine GET-Anforderung, die BSON akzeptiert, und deserialisiert dann die BSON-Nutzlast in der Antwort.

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

Um BSON vom Server anzufordern, legen Sie den Accept-Header auf "application/bson" fest:

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

Verwenden Sie zum Deserialisieren des Antworttexts den BsonMediaTypeFormatter. Dieser Formatierer befindet sich nicht in der Standardformatierersammlung, daher müssen Sie ihn angeben, wenn Sie den Antworttext lesen:

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

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

Das nächste Beispiel zeigt, wie eine POST-Anforderung gesendet wird, die BSON enthält.

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

Ein Großteil dieses Codes ist mit dem vorherigen Beispiel identisch. Geben Sie in der PostAsync-Methode jedoch BsonMediaTypeFormatter als Formatierer an:

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

Serialisieren Top-Level primitiver Typen

Jedes BSON-Dokument ist eine Liste von Schlüssel-Wert-Paaren. Die BSON-Spezifikation definiert keine Syntax zum Serialisieren eines einzelnen Rohwerts, z. B. einer ganzen Zahl oder einer Zeichenfolge.

Um diese Einschränkung zu umgehen, behandelt der BsonMediaTypeFormatter primitive Typen als Sonderfall. Vor dem Serialisieren konvertiert er den Wert in ein Schlüssel-Wert-Paar mit dem Schlüssel "Value". Angenommen, Ihr API-Controller gibt eine ganze Zahl zurück:

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

Vor dem Serialisieren konvertiert der BSON-Formatierer dies in das folgende Schlüssel-Wert-Paar:

{ "Value": 42 }

Beim Deserialisieren konvertiert der Formatierer die Daten zurück in den ursprünglichen Wert. Clients, die einen anderen BSON-Parser verwenden, müssen diesen Fall jedoch behandeln, wenn Ihre Web-API Unformatierte Werte zurückgibt. Im Allgemeinen sollten Sie die Rückgabe strukturierter Daten anstelle von Rohwerten in Erwägung ziehen.

Zusätzliche Ressourcen

BSON-Beispiel für web-API

Medienformatierer