6.1.1 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期间可能会阻塞线程。

6.1.2 创建媒体格式化器

以下示例演示了一个媒体类型格式化器,它可以将Product对象序列化成一个逗号分隔的值(CSV)格式。该示例使用了“创建支持CRUD操作的Web API”教程中定义的Product类型。以下是Product对象的定义:

    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的类:

    public class ProductCsvFormatter : BufferedMediaTypeFormatter
{
}

在其构造器中,要添加一个该格式化器所支持的媒体类型。在这个例子中,该格式化器只支持单一的媒体类型:“text/csv”:

public ProductCsvFormatter()
{
// 添加所支持的媒体类型
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();
} // 将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 添加媒体格式化器

为了将媒体类型格式化器添加到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();
// 添加Accept报头
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/csv"));
// 获取结果并将其写入文件
// (端口号9000只是一个示例端口号)
string result = client.GetStringAsync("http://localhost:9000/api/product/").Result;

Media Formatters(媒体格式化器)的更多相关文章

  1. Media Formatters媒体格式化器

    Media Formatters媒体格式化器 前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/344 ...

  2. Asp.Net Web API 2第十二课——Media Formatters媒体格式化器

    前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本教程演示如何在ASP.N ...

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

    http://www.cnblogs.com/r01cn/archive/2013/05/17/3083400.html 6.1 Media Formatters6.1 媒体格式化器 本文引自:htt ...

  4. CSS3 之 Media(媒体查询器)

    1.响应式Media(媒体查询器) (1)<link rel=“stylesheet” media=“screen and (max-width: 600px)” href=“small.css ...

  5. (原创)jQuery Media Plugin-jQuery的网页媒体播放器插件的使用心得

    jQuery Media Plugin是一款基于jQuery的网页媒体播放器插件,它支持大部分的网络多媒体播放器和多媒体格式,比如:Flash, Windows Media Player, Real ...

  6. 总结一下响应式设计的核心CSS技术Media(媒体查询器)的用法。(转)

    <meta http-equiv="X-UA-Compatible" content="IE=edge"><!--兼容ie-->< ...

  7. css3 media媒体查询器用法总结

    随着响应式设计模型的诞生,Web网站又要发生翻天腹地的改革浪潮,可能有些人会觉得在国内IE6用户居高不下的情况下,这些新的技术还不会广泛的蔓延下去,那你就错了,如今淘宝,凡客,携程等等公司都已经在大胆 ...

  8. 与众不同 windows phone (14) - Media(媒体)之音频播放器, 视频播放器, 与 Windows Phone 的音乐和视频中心集成

    原文:与众不同 windows phone (14) - Media(媒体)之音频播放器, 视频播放器, 与 Windows Phone 的音乐和视频中心集成 [索引页][源码下载] 与众不同 win ...

  9. css3 media媒体查询器用法总结 兼容ie8以下的方法

    总结一下响应式设计的核心CSS技术Media(媒体查询器)的用法. http://www.360doc.com/content/14/0704/06/10734150_391862769.shtml ...

随机推荐

  1. 洛谷P1283 平板涂色 &&一本通1445:平板涂色

    题目描述 CE数码公司开发了一种名为自动涂色机(APM)的产品.它能用预定的颜色给一块由不同尺寸且互不覆盖的矩形构成的平板涂色. 为了涂色,APM需要使用一组刷子.每个刷子涂一种不同的颜色C.APM拿 ...

  2. JavaScript计算日期前一天和后一天

    1.页面排版 <button onclick="before()">上一天</button> <button onclick="after( ...

  3. vscode10个必装的插件

    VSCode 必装的 10 个高效开发插件   本文介绍了目前前端开发最受欢迎的开发工具 VSCode 必装的 10 个开发插件,用于大大提高软件开发的效率. VSCode 的基本使用可以参考我的原创 ...

  4. resharper 8.2

    用户名:ronle注册码:ZoJzmeVBoAv9Sskw76emgksMMFiLn4NM

  5. golang基础之工程结构

    Golang 工作空间 编译工具对源码目录有严格要求,每个工作空间 (workspace) 必须由 bin.pkg.src 三个目录组成. workspace | +--- bin // go ins ...

  6. vuex 源码分析(五) action 详解

    action类似于mutation,不同的是Action提交的是mutation,而不是直接变更状态,而且action里可以包含任意异步操作,每个mutation的参数1是一个对象,可以包含如下六个属 ...

  7. WPF 中如何变相让 ListBox 宽度(Width) 100%,高度(Height) 100%,从而达到 Filled 的效果

    直接贴代码了: XAML: <Window x:Class="HelloWorld.MainWindow" xmlns="http://schemas.micros ...

  8. linux部署java命令

    启动: #!/bin/bash source /etc/profile log() { echo `date +[%Y-%m-%d" "%H:%M:%S]` $1 } log &q ...

  9. virsh console hangs at the escape character “^]”

    I am trying to kickstart a newly built VM. I am stuck with the following. Want to start with a conso ...

  10. Elasticsearch 7.x从入门到精通

    Elasticsearch是一个分布式.可扩展.近实时的搜索与数据分析引擎,它能从项目一开始就赋予你的数据以搜索.分析和探索的能力. 通过本专栏的学习,你可以了解到,Elasticsearch在互联网 ...