Obsługa formatu BSON w internetowym interfejsie API ASP.NET 2.1

W tym temacie pokazano, jak używać formatu BSON w kontrolerze internetowego interfejsu API (po stronie serwera) i w aplikacji klienckiej platformy .NET. Internetowy interfejs API 2.1 wprowadza obsługę formatu BSON.

Co to jest BSON?

BSON to binarny format serializacji. "BSON" oznacza "Binary JSON", ale dane BSON i JSON są serializowane bardzo inaczej. Format BSON to "JSON-like", ponieważ obiekty są reprezentowane jako pary nazwa-wartość, podobnie jak w formacie JSON. W przeciwieństwie do formatu JSON typy danych liczbowych są przechowywane jako bajty, a nie ciągi

Kod BSON został zaprojektowany tak, aby był lekki, łatwy do skanowania i szybki do kodowania/dekodowania.

  • Format BSON jest porównywalny z rozmiarem JSON. W zależności od danych ładunek BSON może być mniejszy lub większy od ładunku JSON. W przypadku serializacji danych binarnych, takich jak plik obrazu, dane BSON są mniejsze niż JSON, ponieważ dane binarne nie są zakodowane w formacie Base64.
  • Dokumenty BSON można łatwo skanować, ponieważ elementy są poprzedzone polem długości, więc analizator może pominąć elementy bez dekodowania ich.
  • Kodowanie i dekodowanie są wydajne, ponieważ typy danych liczbowych są przechowywane jako liczby, a nie ciągi.

Klienci natywni, tacy jak aplikacje klienckie platformy .NET, mogą korzystać z formatu BSON zamiast formatów tekstowych, takich jak JSON lub XML. W przypadku klientów przeglądarki prawdopodobnie zechcesz trzymać się formatu JSON, ponieważ język JavaScript może bezpośrednio przekonwertować ładunek JSON.

Na szczęście internetowy interfejs API korzysta z negocjacji zawartości, więc interfejs API może obsługiwać zarówno formaty, jak i pozwolić klientowi na wybór.

Włączanie formatu BSON na serwerze

W konfiguracji internetowego interfejsu API dodaj element BsonMediaTypeFormatter do kolekcji formaterów.

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

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

Teraz, jeśli klient żąda ciągu "application/bson", internetowy interfejs API będzie używać formatatora BSON.

Aby skojarzyć kod BSON z innymi typami multimediów, dodaj je do kolekcji SupportedMediaTypes. Poniższy kod dodaje ciąg "application/vnd.contoso" do obsługiwanych typów nośników:

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

Przykładowa sesja HTTP

W tym przykładzie użyjemy następującej klasy modelu oraz prostego kontrolera internetowego interfejsu API:

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

Klient może wysłać następujące żądanie HTTP:

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

Oto odpowiedź:

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

Tutaj zamieniłem dane binarne na znaki ".". Poniższy zrzut ekranu z programu Fiddler przedstawia nieprzetworzone wartości szesnastkowe.

Zrzut ekranu przedstawiający okienko okna z nieprzetworzonymi wartościami szesnastkowym danych binarnych w kolorach zielonym u góry i środkowej oraz czarnym u dołu.

Używanie formatu BSON z klientem HttpClient

Aplikacje klienckie platformy .NET mogą używać programu formatującego BSON z klientem HttpClient. Aby uzyskać więcej informacji na temat klienta HttpClient, zobacz Wywoływanie internetowego interfejsu API z klienta platformy .NET.

Poniższy kod wysyła żądanie GET, które akceptuje kod BSON, a następnie deserializuje ładunek BSON w odpowiedzi.

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

Aby zażądać formatu BSON z serwera, ustaw nagłówek Accept na wartość "application/bson":

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

Aby wykonać deserializowanie treści odpowiedzi, użyj klasy BsonMediaTypeFormatter. Ten formater nie znajduje się w domyślnej kolekcji formaterów, dlatego należy określić ją podczas odczytywania treści odpowiedzi:

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

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

W następnym przykładzie pokazano, jak wysłać żądanie POST zawierające dane 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();
    }
}

Większość tego kodu jest taka sama jak w poprzednim przykładzie. Jednak w metodzie PostAsync określ parametr BsonMediaTypeFormatter jako formater:

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

Serializowanie typów pierwotnych Top-Level

Każdy dokument BSON jest listą par klucz/wartość. Specyfikacja BSON nie definiuje składni służącej do serializacji pojedynczej nieprzetworzonej wartości, takiej jak liczba całkowita lub ciąg.

Aby obejść to ograniczenie, BsonMediaTypeFormatter traktuje typy pierwotne jako szczególny przypadek. Przed serializacji konwertuje wartość na parę klucz/wartość z kluczem "Wartość". Załóżmy na przykład, że kontroler interfejsu API zwraca liczbę całkowitą:

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

Przed serializacji formater BSON konwertuje go na następującą parę klucz/wartość:

{ "Value": 42 }

Podczas deserializacji program formatujący konwertuje dane z powrotem na oryginalną wartość. Jednak klienci korzystający z innego analizatora BSON będą musieli obsłużyć ten przypadek, jeśli internetowy interfejs API zwróci nieprzetworzone wartości. Ogólnie rzecz biorąc, należy rozważyć zwrócenie danych strukturalnych, a nie wartości pierwotnych.

Dodatkowe zasoby

Przykładowy kod BSON internetowego interfejsu API

Programy formatujące multimedia