標籤:
前言
閱讀本文之前,您也可以到Asp.Net Web API 2 系列導航進行查看 http://www.cnblogs.com/aehyok/p/3446289.html
本教程示範如何在ASP.NET Web API中支援額外的媒體格式。
Internet Media Types——Internet的媒體類型
媒體類型,也叫做MIME類型,標識了一片資料的格式。在HTTP中,媒體類型描述了訊息體的格式。一個媒體類型由兩個字串組成:類型和子類型。例如:
- text/html
- image/png
- application/json
當一條HTTP訊息含有一個實體時,Content-Type(內容類型)前序指定訊息體的格式。這是告訴接收器如何解析訊息體的內容。
例如,如果一個HTTP響應含有一個PNG圖片,該響應可能會有以下前序。
HTTP/1.1 200 OKContent-Length: 95267Content-Type: image/png
當用戶端發送一條請求訊息時,它可能包括一個Accept前序。Accept前序是告訴伺服器,用戶端希望從伺服器得到哪種媒體類型。例如:
Accept: text/html,application/xhtml+xml,application/xml
該前序告訴伺服器,用戶端希望得到的是HTML、XHTML,或XML。
在Web API中,媒體類型決定了Web API如何對HTTP訊息體進行序列化和還原序列化。對於XML、JSON,以及URL編碼的表單資料,已有了內建的支援。而且,通過編寫媒體格式化器(Media Formatter),可以支援額外的媒體類型。
為了建立媒體格式化器,需從以下類進行派生:
- MediaTypeFormatter。這個類使用了非同步讀寫方法
- BufferedMediaTypeFormatter。這個類派生於MediaTypeFormatter,但將非同步讀寫方法封裝在同步方法之中。
從BufferedMediaTypeFormatter派生要更簡單些,因為沒有非同步代碼,但它也意味著在I/O期間可能會阻塞線程。
Creating a Media Formatter——建立媒體格式化器
以下樣本示範了一個媒體類型格式化器,它可以將Product對象序列化成一個逗號分隔的值(CSV)格式。該樣本使用了Asp.Net Web API 2第二課——CRUD操作 http://www.cnblogs.com/aehyok/p/3434578.html中定義的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格式化器,要定義一個派生於BufferedMediaTypeFormater的類:
namespace ProductStore.Formatters{ using System; using System.Collections.Generic; using System.IO; using System.Net.Http.Formatting; using System.Net.Http.Headers; using ProductStore.Models; 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。
protected override bool CanReadType(Type type){ return false;}
最後,重寫WriteToStream方法。通過將一種類型寫成一個流,該方法對該類型進行序列化。如果你的格式化器要支援還原序列化,也可以重寫ReadFromStream方法。
public override void WriteToStream( Type type, object value, Stream stream, HttpContentHeaders contentHeaders){ using (var writer = new StreamWriter(stream)) { 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); } } stream.Close();}// Helper methods for serializing Products to CSV format. // 將Product序列化成CSV格式的輔助器方法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) { return String.Format("\"{0}\"", field.Replace("\"", "\"\"")); } else return field;}
Adding the Media Formatter——添加媒體格式化器
為了將媒體類型格式化器添加到Web API管線,要使用HttpConfiguration對象上的Formatters屬性。
public static void ConfigureApis(HttpConfiguration config){ config.Formatters.Add(new ProductCsvFormatter()); }
對於ASP.NET託管,要將這個函數添加到Global.asax檔案,並通過Application_Start方法調用它。
protected void Application_Start(){ ConfigureApis(GlobalConfiguration.Configuration); // ...}
現在,如果用戶端在Accept前序指定“text/csv”,則伺服器將返回CSV格式的資料。
以下樣本使用HttpClient來擷取CSV資料,並將其寫入一個檔案:
HttpClient client = new HttpClient();// Add the Accept header// 添加Accept前序client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/csv"));// Get the result and write it to a file.// (Port 9000 is just an example port number.)// 擷取結果並將其寫入檔案// (連接埠號碼9000隻是一個樣本連接埠號碼)string result = client.GetStringAsync("http://localhost:9000/api/product/").Result;System.IO.File.WriteAllText("products.csv", result);
Asp.Net Web API 2第十二課——Media Formatters媒體格式化器