Media Formatters(媒体格式化器)
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;
原文地址:https://www.cnblogs.com/fanfan-90/p/12050976.html
- 零基础学编程007:FOR循环
- 零基础学编程006:赋值语句
- 零基础学编程005:打印一行复利数据
- 使用Keras集成卷积神经网络的入门级教程
- 零基础学编程003:在游戏中学JAVA和C#
- 在机器学习中处理缺失数据的方法
- 零基础学编程002:Hello World
- php随机数怎么获取?一个简单的函数就能生成
- 零基础学编程009:只显示2位小数
- .Net实现Windows服务安装完成后自动启动的两种方法
- 【教程】OpenCV—Node.js教程系列:Node.js+OpenCV面部脸识别
- 学会10多种语言是种什么样的体验?
- Spring Data 最佳实践
- Prodigy,从根本上有效的自主学习驱动的注释工具
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- matlab导出csv文件多种方法实现
- matlab面向对象编程基础
- Octave数据运算基础教程-ML Note29
- Octave中数据的可视化—ML Note 30
- matplotlib animation FuncAnimation画2D线图
- 坚持一下只需要一个理由就够了
- IGD反转世代距离-多目标优化评价指标概念及实现
- webpack实战——样式文件分离
- matlab绘图工具
- python批量移动文件&重命名代码分享
- [DeeplearningAI 笔记]第一章2.11-2.16 向量化与 python/numpy 向量说明
- 自己动手作图深入理解二叉树、满二叉树及完全二叉树
- Matlab矩阵加入新元素
- 每个Python程序员都应该知道的10个缩写
- 《剑指offer》第九天:斐波那契数列