ASP.NET Web API 2 中的媒體格式器
本教學課程說明如何在 ASP.NET Web API 中支援其他媒體格式。
網際網路媒體類型
媒體類型也稱為 MIME 類型,可識別資料片段的格式。 在 HTTP 中,媒體類型會描述訊息本文的格式。 媒體類型是由兩個字串所組成:類型與子類型。 例如:
- text/html
- image/png
- application/json
當 HTTP 訊息包含實體本文時,Content-Type 標頭會指定訊息本文的格式。 這會告訴接收者如何剖析訊息本文的內容。
例如,如果 HTTP 回應包含 PNG 映射,回應可能會有下列標頭。
HTTP/1.1 200 OK
Content-Length: 95267
Content-Type: image/png
當用戶端傳送要求訊息時,它可以包含 Accept 標頭。 Accept 標頭會告訴伺服器 (用戶端想要從伺服器) 媒體類型。 例如:
Accept: text/html,application/xhtml+xml,application/xml
此標頭會告訴伺服器用戶端想要 HTML、XHTML 或 XML。
媒體類型會決定 Web API 如何序列化和還原序列化 HTTP 訊息本文。 Web API 具有 XML、JSON、BSON 和表單 URL 編碼資料的內建支援,而且您可以撰寫 媒體格式器來支援其他媒體類型。
若要建立媒體格式器,請衍生自下列其中一個類別:
- MediaTypeFormatter。 這個類別會使用非同步讀取和寫入方法。
- BufferedMediaTypeFormatter。 這個類別衍生自 MediaTypeFormatter ,但使用同步讀取/寫入方法。
衍生自 BufferedMediaTypeFormatter 比較簡單,因為沒有非同步程式碼,但也表示呼叫執行緒可以在 I/O 期間封鎖。
範例:建立 CSV 媒體格式器
下列範例顯示可將 Product 物件序列化為逗號分隔值的媒體類型格式器, (CSV) 格式。 此範例會使用建立 支援 CRUD 作業的 Web API教學課程中定義的 Product 類型。 以下是 Product 物件的定義:
namespace ProductStore.Models
{
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public decimal Price { get; set; }
}
}
若要實作 CSV 格式器,請定義衍生自 BufferedMediaTypeFormatter 的類別:
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using ProductStore.Models;
namespace ProductStore.Formatters
{
public class ProductCsvFormatter : BufferedMediaTypeFormatter
{
}
}
在建構函式中,新增格式器支援的媒體類型。 在此範例中,格式器支援單一媒體類型 「text/csv」:
public ProductCsvFormatter()
{
// Add the supported media type.
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/csv"));
}
覆寫 CanWriteType 方法,以指出格式器可以序列化的類型:
public override bool CanWriteType(System.Type type)
{
if (type == typeof(Product))
{
return true;
}
else
{
Type enumerableType = typeof(IEnumerable<Product>);
return enumerableType.IsAssignableFrom(type);
}
}
在此範例中,格式器可以序列化單一 Product
物件以及 物件的集合 Product
。
同樣地,請覆寫 CanReadType 方法,以指出格式器可以還原序列化的類型。 在此範例中,格式器不支援還原序列化,因此方法只會傳回 false。
public override bool CanReadType(Type type)
{
return false;
}
最後,覆 寫 WriteToStream 方法。 這個方法會將類型寫入資料流程,以序列化類型。 如果您的格式子支援還原序列化,也請覆寫 ReadFromStream 方法。
public override void WriteToStream(Type type, object value, Stream writeStream, HttpContent content)
{
using (var writer = new StreamWriter(writeStream))
{
var products = value as IEnumerable<Product>;
if (products != null)
{
foreach (var product in products)
{
WriteItem(product, writer);
}
}
else
{
var singleProduct = value as Product;
if (singleProduct == null)
{
throw new InvalidOperationException("Cannot serialize type");
}
WriteItem(singleProduct, writer);
}
}
}
// Helper methods for serializing Products to CSV format.
private void WriteItem(Product product, StreamWriter writer)
{
writer.WriteLine("{0},{1},{2},{3}", Escape(product.Id),
Escape(product.Name), Escape(product.Category), Escape(product.Price));
}
static char[] _specialChars = new char[] { ',', '\n', '\r', '"' };
private string Escape(object o)
{
if (o == null)
{
return "";
}
string field = o.ToString();
if (field.IndexOfAny(_specialChars) != -1)
{
// Delimit the entire field with quotes and replace embedded quotes with "".
return String.Format("\"{0}\"", field.Replace("\"", "\"\""));
}
else return field;
}
將媒體格式器新增至 Web API 管線
若要將媒體類型格式器新增至 Web API 管線,請使用HttpConfiguration物件的Formatters屬性。
public static void ConfigureApis(HttpConfiguration config)
{
config.Formatters.Add(new ProductCsvFormatter());
}
字元編碼
或者,媒體格式器可以支援多個字元編碼,例如 UTF-8 或 ISO 8859-1。
在建構函式中,將一或多個 System.Text.Encoding 類型新增至 SupportedEncodings 集合。 先放置預設編碼。
public ProductCsvFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/csv"));
// New code:
SupportedEncodings.Add(new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
SupportedEncodings.Add(Encoding.GetEncoding("iso-8859-1"));
}
在 WriteToStream 和 ReadFromStream 方法中,呼叫 MediaTypeFormatter.SelectCharacterEncoding 以選取慣用字元編碼。 這個方法會比對支援編碼清單的要求標頭。 當您從資料流程讀取或寫入時,請使用傳回的 編碼 :
public override void WriteToStream(Type type, object value, Stream writeStream, HttpContent content)
{
Encoding effectiveEncoding = SelectCharacterEncoding(content.Headers);
using (var writer = new StreamWriter(writeStream, effectiveEncoding))
{
// Write the object (code not shown)
}
}
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應