ASP.NET Web API 2.1 中的 BSON 支援
本主題示範如何在 Web API 控制器 (伺服器端) 和 .NET 用戶端應用程式中使用 BSON。 Web API 2.1 引進了對 BSON 的支援。
什麼是 BSON?
BSON 是一種二進位序列化格式。 「BSON」代表「二進位 JSON」,但 BSON 和 JSON 的序列化方式非常不同。 BSON 類似 JSON,因為物件會以名稱/值組表示,與 JSON 相似。 與 JSON 不同,數字資料類型儲存為位元組,而不是字串
BSON 是專為輕量級、易於掃描、快速編碼/解碼而設計。
- BSON 的大小與 JSON 相當。 根據資料的不同,BSON 酬載可能比 JSON 酬載更小或更大。 對於序列化二進位資料 (例如影像檔案),BSON 比 JSON 小,因為二進位資料不是 Base64 編碼的。
- BSON 文件易於掃描,因為元素前面有一個長度欄位,因此解析器可以在不解碼的情況下跳過元素。
- 編碼和解碼效率高,因為數字資料類型以數字形式儲存,而不是字串。
原生用戶端 (例如 .NET 用戶端應用程式) 可以從使用 BSON 取代文字型格式 (如 JSON 或 XML) 中受益。 對於瀏覽器用戶端,您可能希望使用 JSON,因為 JavaScript 可以直接轉換 JSON 酬載。
幸運的是,Web API 使用內容協商,因此您的 API 可以支援這兩種格式並讓用戶端進行選擇。
在伺服器上啟用 BSON
在您的 Web API 設定中,將 BsonMediaTypeFormatter 新增至格式器集合中。
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Formatters.Add(new BsonMediaTypeFormatter());
// Other Web API configuration not shown...
}
}
現在,如果用戶端請求「application/bson」,Web API 將使用 BSON 格式器。
若要將 BSON 與其他媒體類型關聯,請將它們新增至 SupportedMediaTypes 集合中。 以下程式碼將「application/vnd.contoso」新增至支援的媒體類型:
var bson = new BsonMediaTypeFormatter();
bson.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/vnd.contoso"));
config.Formatters.Add(bson);
HTTP 工作階段範例
對於此範例,我們將使用以下模型類別以及一個簡單的 Web 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);
}
}
用戶端可能會傳送以下 HTTP 請求:
GET http://localhost:15192/api/books/1 HTTP/1.1
User-Agent: Fiddler
Host: localhost:15192
Accept: application/bson
以下是回應:
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.........
在這裡,我將二進位資料替換為「.」字元。 以下來自 Fiddler 的螢幕擷取畫面顯示了原始十六進位值。
將 BSON 與 HttpClient 結合使用
.NET 用戶端應用程式可以將 BSON 格式器與 HttpClient 結合使用。 有關 HttpClient 的更多資訊,請參閱「從 .NET 用戶端呼叫 Web API」。
以下程式碼傳送接受 BSON 的 GET 請求,然後還原序列化回應中的 BSON 酬載。
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);
}
}
若要從伺服器請求 BSON,請將 Accept 標頭設定為「application/bson」:
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/bson"));
若要還原序列化回應本文,請使用 BsonMediaTypeFormatter。 此格式器不在預設格式器集合中,因此您必須在讀取回應本文時指定它:
MediaTypeFormatter[] formatters = new MediaTypeFormatter[] {
new BsonMediaTypeFormatter()
};
var book = await result.Content.ReadAsAsync<Book>(formatters);
下一個範例顯示如何傳送包含 BSON 的 POST 請求。
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();
}
}
此程式碼的大部分內容與前面的範例相同。 但在 PostAsync 方法中,將格式器指定為 BsonMediaTypeFormatter:
MediaTypeFormatter bsonFormatter = new BsonMediaTypeFormatter();
var result = await client.PostAsync("api/books", book, bsonFormatter);
序列化頂層基本類型
每個 BSON 文件都是索引鍵/值組的清單。BSON 規範並未定義序列化單個原始值 (如整數或字串) 的語法。
為了解決此限制,BsonMediaTypeFormatter 會將基本類型視為特殊情況。 在序列化之前,它將值轉換為索引鍵/值組,其中索引鍵為「Value」。 例如,假設您的 API 控制器傳回一個整數:
public class ValuesController : ApiController
{
public IHttpActionResult Get()
{
return Ok(42);
}
}
在序列化之前,BSON 格式器會將其轉換為以下索引鍵/值組:
{ "Value": 42 }
還原序列化時,格式器會將資料轉換回原始值。 但是,如果您的 Web API 傳回原始值,則使用不同 BSON 解析器的用戶端將需要處理這種情況。 一般來說,您應該考慮傳回結構化資料,而不是原始值。