Media Formatters媒体格式化器

Media Formatters媒体格式化器

前言

阅读本文之前,您也可以到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 OK

Content-Length: 95267

Content-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
标签:  Asp.Net Web API 2

你可能感兴趣的:(Media Formatters媒体格式化器)