• 【ASP.NET Core】设置Web API 响应的数据格式——Produces 特性篇


    开春首文,今天老周就跟各位大伙伴们聊一个很简单的话题:怎么设定API响应的数据格式。

    说本质一点,就是设置所返回内容的 MIME 类型(Content-Type 头)。当然了,咱们不会使用在HTTP管道中插入中间件的方式来解决,因为:

    A、这样做会导致所有传入传出的HTTP消息都被修改;

    B、这样会毁坏API应用的设计规范,弄得不伦不类、礼崩乐坏、不堪入目。

    所以,今天的主角是一个特性类(Attribute),它的大名叫 ProducesAttribute,位于 Microsoft.AspNetCore.Mvc 命名空间下。这么一介绍,你肯定能找到它。

    根据定义,该特性类可用于:类、方法。说得再直接一点,就是用于 Controller类 和 Action方法。

    这个特性类用于 设置API返回数据的MIME类型,嗯,也就是所谓的格式了。最人性化最简单的使用方法就是这样:

        [Produces("text/html")]
        [Produces("audio/wav")]
        [Produces("image/png")]
        [Produces("application/octet-stream")]

    就是这样,你希望返回的是啥东西,就用 Content-Type 字符串来指定。

    马上,立刻,现在,就给大伙儿演示一个例子,让 API 返回 text/json 类型的数据。因为默认情况下,API 返回数据使用 application/json 格式,所以,咱们要改为 text/json,就得用 Produces 特性。

    首先,新建一个空的 ASP.NET Core 应用项目。老周喜欢空模板,易于 DIY,可折腾性强。

    然后,在 Program.cs 文件中注册与 MVC 控制器有关的服务,以及Map一下相关中间件。

    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddControllers();
    var app = builder.Build();
    
    app.MapControllers();   //这一句不要忘了
    
    app.Run();

    接着,新建一个类,或者在“新建项”中选择空的 API 控制器。

        [Route("api/[controller]")]
        [ApiController]
        public class Demo : ControllerBase
        {
            ……
        }

    Route 特性指定访问这个控制器的 URL,[controller] 是个占位符,访问时用实际的控制器名来替换。比如,这里的控制器的名字是 Demo,访问时的URL就是 http://somehost/api/demo/xxxx。不过,这里老周的命名不太规范,规范的命名应该是 DemoController。只是老周嫌它的后缀太长。

    其实 API 和 MVC 的控制器实现起来一样,但 API 没有视图,所以类继承时,基类可以用 ControllerBase 类而不是 Controller 类。另外,在类上面加一个 ApiController 特性,表明这个 Demo 类是作为 API 控制器用的,并且它的派生类都作为 API 控制器。

    好,我们先实现两个 Action。

            [Route("getbt")]
            [HttpGet]
            public string GetWTF() => "What the bitch";
    
            [Route("getak")]
            [HttpGet]
            public IDictionary<string, int> GetAK()
            {
                // 返回一个类实例和返回字典对象
                // 其JSON结构差不多
                // 此处为了简单,直接用字典
                return new Dictionary<string, int>
                {
                    ["item1"] = 10,
                    ["item2"] = 49
                };
            }

    Action 方法上指定的 Route 是相对于控制器类的 Route 的,即 /api/demo/getbt、/api/demo/getak。

    这个相信各位看得懂,不用过多解释,看不懂的肯定是因为你太谦虚了。

    运行一下这个示例,直接通过浏览器的开发人员工具查看,得知:

    第一个 action 返回的 string 类型,因此默认选用 text/plain 格式(普通文本)。

    第二个 action 返回的是字典对象,默认选择 application/json 格式。

    现在,把 Produces 特性用上,使其返回的数据变为 text/json 格式。

        [Route("api/[controller]")]
        [ApiController]
        [Produces("text/json")]
        public class Demo : ControllerBase
        {
            ……
        }

    再次运行,从浏览器的开发人员工具中查看HTTP消息。

    不过,你得小心!如果你指定的格式与 API 所返回的对象无法兼容,就会崩盘。比如,把上面的 getak 改成这样:

            [Route("getak")]
            [HttpGet]
            [Produces("text/plain")]
            public IDictionary<string, int> GetAK()
            {
                ……
            }

    虽然 Demo 控制器类上应用了 Produces 特性指定了 text/json 格式,但这个方法上也应用了此特性,依据就近原则,程序会优先选用 text/plain 格式。在内部的处理机制中,这是不匹配的,除非方法的返回值类型是 string。

    一旦执行,就会得到错误状态码。

    下面演示一个返回 jpg 图像格式(即 image/jpeg)的例子。在刚才的 Demo 控制器类上增加一个方法,名为 GetImage。

            [Route("getpic")]
            [HttpGet]
            [Produces("image/jpeg")]
            public Stream GetImage()
            {
                // 因为应用程序目录和内容目录相同
                // 所以直接获取Current即可
                string dirpath = Directory.GetCurrentDirectory();
                // 直接返回文件流
                return System.IO.File.OpenRead(Path.Combine(dirpath, "505.jpg"));
            }

    方法的返回类型为 Stream 对象,套用 image/jpeg 格式是没问题的,毕竟图像是以二进制的方式响应的。

    老周事先从网上找了一张图片,命名为 505.jpg,放在项目根目录下。你在测试时可以随便找个图片,或者拍一张妹子的照片(前提是妹子不会报警),放到项目目录下即可,文件名自己改。

    在浏览器中访问后得到结果如下图所示。

    --------------------------------------------------- 异次元分界线 -----------------------------------------------------------

    既然数据可以以 JSON 格式返回,那能不能返回 XML 格式呢?当然是可以的。

        public class 帅哥
        {
            public string Name { get; set; }
            public int Age { get; set; }
            public decimal Weight { get; set; }
        }
    ----------------------------------------------------------- [Route(
    "getxml")] [HttpGet] [Produces("application/xml")] public 帅哥 GetXML() { return new 帅哥 { Name = "老周", Age = 93, Weight = 203.77M }; }

    先是定义了一个新类,叫“帅哥”,接着,GetXML 方法返回一个“帅哥”类型的实例。注意此方法应用了 Produces 特性,指定返回的数据格式为 application/xml。

    Web API 控制器默认是不启用 XML 输出支持的,所以在 Program.cs 文件中,在注册MVC功能到服务容器时,需要手动开启对XML输出的支持。

    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddControllers().AddXmlSerializerFormatters();
    var app = builder.Build();
    
    ……

    这样一来,访问 /api/demo/getxml 就能得到 XML 数据了。

    好了,今天的文章就水到这里了,下一篇咱们聊聊 FormatFilter 特性类。

  • 相关阅读:
    python的lambda使用
    python的timedelta
    ptyhon读文件一行长度len为1022,出现\x00
    eclipse生成jar包
    linux 文件的软链接与硬链接(看着写的不错就转发了)
    各种VBA excel 命令、属性、方法
    键盘鼠标共享 Synergy
    关于 range 区域 excel
    php mssql几条常见的数据库分页 SQL 语句
    Get the Degree of Angle Between Hour and Minute Hand of a Clock at Anytime
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/15865531.html
Copyright © 2020-2023  润新知