【ASP.NET Web API教程】6.1 媒体格式化器

6.1 Media Formatters
6.1 媒体格式化器

本文引自:http://www.asp.net/web-api/overview/formats-and-model-binding/media-formatters

By Mike Wasson|March 8, 2012
作者:Mike Wasson|日期:2012-3-8

This tutorial shows how support additional media formats in ASP.NET Web API.
本教程演示如何在ASP.NET Web API中支持额外的媒体格式。

6.1.1 Internet Media Types
6.1.1 Internet的媒体类型

A media type, also called a MIME type, identifies the format of a piece of data. In HTTP, media types describe the format of the message body. A media type consists of two strings, a type and a subtype. For example:
媒体类型,也叫做MIME类型,标识了一片数据的格式。在HTTP中,媒体类型描述了消息体的格式。一个媒体类型由两个字符串组成:类型和子类型。例如:

  • text/html
  • image/png
  • application/json

When an HTTP message contains an entity-body, the Content-Type header specifies the format of the message body. This tells the receiver how to parse the contents of the message body.
当一条HTTP消息含有一个实体时,Content-Type(内容类型)报头指定消息体的格式。这是告诉接收器如何解析消息体的内容。

For example, if an HTTP response contains a PNG image, the response might have the following headers.
例如,如果一个HTTP响应含有一个PNG图片,该响应可能会有以下报头。

HTTP/1.1 200 OK
Content-Length: 95267
Content-Type: image/png

When the client sends a request message, it can include an Accept header. The Accept header tells the server which media type(s) the client wants from the server. For example:
当客户端发送一条请求消息时,它可能包括一个Accept报头。Accept报头是告诉服务器,客户端希望从服务器得到哪种媒体类型。例如:

Accept: text/html,application/xhtml+xml,application/xml

This header tells the server that the client wants either HTML, XHTML, or XML.
该报头告诉服务器,客户端希望得到的是HTML、XHTML,或XML。

In Web API, the media type determines how Web API serializes and deserializes the HTTP message body. There is built-in support for XML, JSON, and form-urlencoded data, and you can support additional media types by writing a media formatter.
在Web API中,媒体类型决定了Web API如何对HTTP消息体进行序列化和解序列化。对于XML、JSON,以及URL编码的表单数据,已有了内建的支持。而且,通过编写媒体格式化器(Media Formatter),可以支持额外的媒体类型。

To create a media formatter, derive from one of these classes:
为了创建媒体格式化器,需从以下类进行派生:

  • MediaTypeFormatter. This class uses asynchronous read and write methods.
    MediaTypeFormatter。这个类使用了异步读写方法
  • BufferedMediaTypeFormatter. This class derives from MediaTypeFormatter but wraps the asynchronous read/write methods inside synchronous methods.
    BufferedMediaTypeFormatter。这个类派生于MediaTypeFormatter,但将异步读写方法封装在同步方法之中。

Deriving from BufferedMediaTypeFormatter is simpler, because there is no asynchronous code, but it also means the calling thread can block during I/O.
从BufferedMediaTypeFormatter派生要更简单些,因为没有异步代码,但它也意味着在I/O期间可能会阻塞线程。

6.1.2 Creating a Media Formatter
6.1.2 创建媒体格式化器

The following example shows a media type formatter that can serialize a Product object to a comma-separated values (CSV) format. This example uses the Product type defined in the tutorial Creating a Web API that Supports CRUD Operations. Here is the definition of the Product object:
以下示例演示了一个媒体类型格式化器,它可以将Product对象序列化成一个逗号分隔的值(CSV)格式。该示例使用了“创建支持CRUD操作的Web API”教程(本系列教程的第2.1小节)中定义的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; }
    }
}

To implement a CSV formatter, define a class that derives from BufferedMediaTypeFormater:
为了实现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 { } }

In the constructor, add the media types that the formatter supports. In this example, the formatter supports a single media type, "text/csv":
在其构造器中,要添加一个该格式化器所支持的媒体类型。在这个例子中,该格式化器只支持单一的媒体类型:“text/csv”:

public ProductCsvFormatter()
{
    // Add the supported media type.
    // 添加所支持的媒体类型
    SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/csv"));
}

Override the CanWriteType method to indicate which types the formatter can serialize:
重写这个CanWriteType方法,以指示该格式化器可以序列化哪种类型:

public override bool CanWriteType(System.Type type)
{
    if (type == typeof(Product))
    {
        return true;
    }
    else
    {
        Type enumerableType = typeof(IEnumerable<Product>);
        return enumerableType.IsAssignableFrom(type);
    }
}

In this example, the formatter can serialize single Product objects as well as collections of Product objects.
在这个例子中,格式化器可以序列化单个Product对象,以及Product对象集合。

Similarly, override the CanReadType method to indicate which types the formatter can deserialize. In this example, the formatter does not support deserialization, so the method simply returns false.
相应地,重写CanReadType方法,以指示该格式化器可以解序列化哪种类型。在此例中,格式化器不支持解序列化,因此该方法简单地返回false。

protected override bool CanReadType(Type type)
{
    return false;
}

Finally, override the WriteToStream method. This method serializes a type by writing it to a stream. If your formatter supports deserialization, also override the ReadFromStream method.
最后,重写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; }

6.1.4 Adding the Media Formatter
6.1.4 添加媒体格式化器

To add a media type formatter to the Web API pipeline, use the Formatters property on the HttpConfiguration object.
为了将媒体类型格式化器添加到Web API管线,要使用HttpConfiguration对象上的Formatters属性。

public static void ConfigureApis(HttpConfiguration config)
{
    config.Formatters.Add(new ProductCsvFormatter()); 
}

For ASP.NET hosting, add this function to the Global.asax file and call it from the Application_Start method.
对于ASP.NET托管,要将这个函数添加到Global.asax文件,并通过Application_Start方法调用它。

protected void Application_Start()
{
    ConfigureApis(GlobalConfiguration.Configuration);
// ... }

Now if a client specifies "text/csv" in the Accept header, the server will return the data in CSV format.
现在,如果客户端在Accept报头指定“text/csv”,则服务器将返回CSV格式的数据。

The following example uses HttpClient to get the CSV data and write it to a file:
以下示例使用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);

看完此文如果觉得有所收获,请给个推荐

posted @ 2013-05-17 11:54 r01cn 阅读(...) 评论(...) 编辑 收藏