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

原文:Asp.Net Web API 2第十二课——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);

 

时间: 2024-10-21 18:05:23

Asp.Net Web API 2第十二课——Media Formatters媒体格式化器的相关文章

Asp.Net Web API 2第十四课——Content Negotiation(内容协商)

原文:Asp.Net Web API 2第十四课--Content Negotiation(内容协商) 前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本文描述ASP.NET Web API如何实现内容协商. HTTP规范(RFC 2616)将内容协商定义为"在有多个表现可用时,为一个给定的响应选择最佳表现的过程".在HTTP中内容协商的主要机制是以下请求报头:

Asp.Net Web API 2第十五课——Model Validation(模型验证)

原文:Asp.Net Web API 2第十五课--Model Validation(模型验证) 前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本文参考链接文章地址http://www.asp.net/web-api/overview/formats-and-model-binding/model-validation-in-aspnet-web-api 当客户端发送数

Asp.Net Web API 2第十课——使用OWIN自承载Web API

原文:Asp.Net Web API 2第十课--使用OWIN自承载Web API 前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本教程主要来展示在控制台应用程序中如何通过OWIN来承载Web API. Open Web Interface for .NET (OWIN)在Web服务器和Web应用程序之间建立一个抽象层.OWIN将网页应用程序从网页服务器分离出来,然后将

ASP.NET Web API路由规则(二)

默认的规则 在ASP.NET MVC4中 global.asax.cs代码中并无注册默认路由规则的代码 代码如下: public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters

Asp.Net Web API 2 官网菜鸟学习系列导航[持续更新中]

原文:Asp.Net Web API 2 官网菜鸟学习系列导航[持续更新中] 前言 本来一直参见于微软官网进行学习的, 官网网址http://www.asp.net/web-api.出于自己想锻炼一下学习阅读英文文章的目的,又可以学习下微软新发布的技术,其实也很久了,但自己菜鸟一枚,对自己来说都是新技术了.鉴于以上两个原因,本人打算借助google翻译和有道词典,来翻译学习这个系列,并通过博客园来记录自己的翻译学习过程.由于自己阅读水平的确太菜,在借助工具的情况下,有时候搞出来的也是蹩脚的语句,

【ASP.NET Web API教程】6.3 内容协商

原文:[ASP.NET Web API教程]6.3 内容协商 本文是Web API系列教程的第6.3小节 6.3 Content Negotiation 6.3 内容协商 摘自:http://www.asp.net/web-api/overview/formats-and-model-binding/content-negotiation By Mike Wasson|May 20, 2012 作者:Mike Wasson | 日期:2012-3-20 This article describe

使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【十】——使用CacheCow和ETag缓存资源

原文:使用ASP.NET Web Api构建基于REST风格的服务实战系列教程[十]--使用CacheCow和ETag缓存资源 系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 本文将使用一个开源框架CacheCow来实现针对Http请求资源缓存,本文主要介绍服务器端的缓存. 使用缓存技术可以很好的提高Web Api的性能,减小服务器的开销.我们把这种缓存形式称之为:条件化请求(Conditional Requests).具体表现为:客户

ASP.NET Web API(二) 安全验证之使用HTTP基本认证

在前一篇文章ASP.NET Web API(一):使用初探,GET和POST数据中,我们初步接触了微软的REST API: Web API. 我们在接触了Web API的后就立马发现了有安全验证的需求,所以这篇文章我们先来讨论下 安全验证一个最简单的方法:使用HTTP基本认证. HTTP基本认证原理 在HTTP协议进行通信的过 程中,HTTP协议定义了基本认证过程以允许HTTP服务器对WEB浏览器进行用户身份认证的方法,当一个客户端 向HTTP服务器进行数据请求时,如果客户端未被认证,则HTTP

使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【开篇】【持续更新中。。。】

原文:使用ASP.NET Web Api构建基于REST风格的服务实战系列教程[开篇][持续更新中...] 最近发现web api很火,园内也有各种大神已经在研究,本人在asp.net官网上看到一个系列教程,原文地址:http://bitoftech.net/2013/11/25/detailed-tutorial-building-asp-net-web-api-restful-service/.于是打算跟着学一下,把学习过程记录在博客园的同时也分享给大家. 每一篇结束后我都会把代码共享 由于