日计不足涓滴成河-自定义响应结果格式化器

什么是响应结果

响应结果就是,在客户端向服务器发出请求后,服务器根据客户端的请求参数,给出的结果,这就是一个完整的响应结果过程。

响应的结果包含的内容非常多,主要的有 HTTP Status Code,Content-Type,Content 等等,在这里不再一一赘述。

一般情况下,在 .NET MVC 中,如果是 API 接口,默认使用 JsonOutputFormatter 对结果进行格式化。

但是也不排除某些情况下,我们需要对业务进行兼容化的设置,比如部分接口使用 xml,部分接口使用自定义的格式,需求的响应是第一要务。

常见响应结果格式化器

在 .NET(介于官方改名,咱也不叫 Core 了哈) MVC中,有几种内置的常见响应结果格式化器,他们分别是:

0、OutputFormatter(基类)
1、TextOutputFormatter(基类)
2、StringOutputFormatter
3、StreamOutputFormatter
4、JsonOutputFormatter
5、XmlSerializerOutputFormatter

由于这几种常见的格式化器的存在,我们可以放心的在 .NET MVC 中使用 请求-> 响应 过程,而不必关心他具体的实现。

来自天气预报的示例

默认的响应结果格式json

private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private IEnumerable<WeatherForecast> GetWeatherForecast()
{
var rng = new Random();
return Enumerable.Range(1, 3).Select(index => new WeatherForecast{Date = DateTime.Now.AddDays(index),TemperatureC = rng.Next(-20, 55),Summary = Summaries[rng.Next(Summaries.Length)]}).ToArray();
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
return GetWeatherForecast();
}

当我们请求上面的 API 接口,将得到下面的默认输出结果。

[{
"date": "2020-10-24T17:19:05.4638588+08:00",
"temperatureC": 2,
"temperatureF": 35,
"summary": "Cool"},{
"date": "2020-10-25T17:19:05.464602+08:00",
"temperatureC": 18,
"temperatureF": 64,
"summary": "Sweltering"},{
"date": "2020-10-26T17:19:05.4646057+08:00",
"temperatureC": -14,
"temperatureF": 7,
"summary": "Mild"}
]

这很好,是我们想要的结果。

Xml响应结果格式器

在上面的天气预报示例中,API接口默认使用了 json 格式输出响应结果。

在不改动业务代码的情况下,我们可以增加一种 xml 输出结果,具体做法就是增加一个 API 接口,然后在 startup.cs 中添加 xml 格式化器。

[Produces("application/xml")]
[HttpGet("xml")]
public IEnumerable<WeatherForecast> Xml()
{
return GetWeatherForecast();
}

配置 Xml 格式器 XmlDataContractSerializerOutputFormatter

public void ConfigureServices(IServiceCollection services)
{services.AddControllers(configure =>{configure.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());});
}

这个时候再请求 API 地址:/weatherforecast/xml ,我们将会得到的结果如下

<ArrayOfWeatherForecast xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/CustomBinder">
<WeatherForecast>
<Date>2020-10-24T17:24:19.1047116+08:00</Date>
<Summary>Scorching</Summary>
<TemperatureC>49</TemperatureC>
</WeatherForecast>
<WeatherForecast>
<Date>2020-10-25T17:24:19.1047219+08:00</Date>
<Summary>Cool</Summary>
<TemperatureC>6</TemperatureC>
</WeatherForecast>
<WeatherForecast>
<Date>2020-10-26T17:24:19.1047221+08:00</Date>
<Summary>Freezing</Summary>
<TemperatureC>-20</TemperatureC>
</WeatherForecast>
</ArrayOfWeatherForecast>

ProducesAttribute 特性(内容协定)

API 接口 /xml 的特性标注多了一个 [Produces("application/xml")]正是得益于 ProducesAttribute 特性,我们可以在 MVC 框架内随意的定制响应结果。

ProducesAttribute 和其它的特性类没有太多的区别,其基本原理就是使用用户指定的 contentType 参数(本例中为 application/xml) 到 OutputFormatters 中查找对应类型的 Formatters。

如果找到了,就使用该 Formatters 格式化响应结果,如果没有找到,就抛出 No output formatter was found for content types 的警告,同时,客户端会收到一个  406(Not Acceptable) 的响应结果。

我想要更多-自定义格式化器

没错,上面的几种常见的格式化器虽然非常好用。但是,我现在要对接一个旧的第三方客户端,该客户端采用的是 url 参数请求协议包,很明显,由于这个客户端过于年长(假装找不到维护人员),只能在服务器端进行兼容了。

不过也不用过于担心,开发一个自定义的格式化器还是非常简单的。我们只需要定义一个继承自 TextOutputFormatter 的子类即可,其中有小部分需要编写的代码。

需求

我们接到的需求是兼容 url 方式的请求参数响应结果,经过调研,确认格式如下

key=value&key=value&key=value

需求调研清楚后,编码的速度就得跟上了

定义格式化器 WeatherOutputFormatter

public class WeatherOutputFormatter : TextOutputFormatter
{
private readonly static Type WeatherForecastType = typeof(WeatherForecast);
public WeatherOutputFormatter(){SupportedEncodings.Add(Encoding.UTF8);SupportedEncodings.Add(Encoding.Unicode);SupportedMediaTypes.Add("text/weather");}
public override bool CanWriteResult(OutputFormatterCanWriteContext context){
if (context == null){
throw new ArgumentNullException(nameof(context));}
if (context.ObjectType == WeatherForecastType || context.Object is WeatherForecast || context.ObjectType.GenericTypeArguments[0] == WeatherForecastType){
return base.CanWriteResult(context);}
return false;}
private string WriterText(IEnumerable<WeatherForecast> weathers){StringBuilder builder = new StringBuilder();
foreach (var wealther in weathers){builder.Append(WriterText(wealther));}
return builder.ToString();}
private string WriterText(WeatherForecast weather) => $"date={WebUtility.UrlEncode(weather.Date.ToString())}&temperatureC={weather.TemperatureC}&temperatureF={weather.TemperatureF}&summary={WebUtility.UrlEncode(weather.Summary)}";
public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding){
if (context == null){
throw new ArgumentNullException(nameof(context));}
if (selectedEncoding == null){
throw new ArgumentNullException(nameof(selectedEncoding));}
string text = string.Empty;
if (context.ObjectType == WeatherForecastType)text = WriterText(context.Object as WeatherForecast);
else if (context.ObjectType.GenericTypeArguments[0] == WeatherForecastType)text = WriterText(context.Object as IEnumerable<WeatherForecast>);
if (string.IsNullOrEmpty(text)){
await Task.CompletedTask;}
var response = context.HttpContext.Response;
await response.WriteAsync(text, selectedEncoding);}
}

正所谓一图胜千言,所以我给大家画了一张图,方便理解

从图中可以看出,我们只需要重写两个方法,同时编写一个自定义格式化逻辑即可完成,看起来还是非常简单的。

细心的同学可能发现了,在 WriterText 方法中,考虑到兼容性的问题,我们还将 url 中的 value 进行转义,可以说还是非常贴心的哈。

编写测试方法

[Produces("text/weather")]
[HttpGet("weather")]
public IEnumerable<WeatherForecast> Weather()
{
return GetWeatherForecast();
}

测试方法中定义 Produces("text/weather"),指定需要的 ContentType,同时,还需要将 WeatherOutputFormatter 添加到 OutputFormatters 中使用。

public void ConfigureServices(IServiceCollection services)
{services.AddControllers(configure =>{configure.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());configure.OutputFormatters.Add(new WeatherOutputFormatter());});
}

调用接口进行测试

请求 API 地址 /weather,得到结果如下

date=2020%2F10%2F27+10%3A35%3A36&temperatureC=42&temperatureF=107&summary=Scorchingdate=2020%2F10%2F28+10%3A35%3A36&temperatureC=28&temperatureF=82&summary=Freezingdate=2020%2F10%2F29+10%3A35%3A36&temperatureC=17&temperatureF=62&summary=Sweltering

结束语

至此,自定义格式化器已经完成,本文通过一个简单的示例实现,帮助大家理解如何在 MVC 中使用自定义格式化器,文章篇幅不长,做图花了点心思,欢迎您的关注。

示例代码托管在:

https://github.com/lianggx/EasyAspNetCoreDemo/tree/master/CustomBinder

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/307155.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

docker 容器启动顺序_Docker容器启动时初始化Mysql数据库

1. 前言 Docker在开发中使用的越来越多了&#xff0c;最近搞了一个Spring Boot应用&#xff0c;为了方便部署将Mysql也放在Docker中运行。那么怎么初始化 SQL脚本以及数据呢&#xff1f; 我这里有两个传统方案。 第一种方案是在容器启动后手动导入&#xff0c;太low了不行。第二…

后端学习 - JVM(上)内存与垃圾回收

JVM 架构图 文章目录一 JVM 简介二 类加载子系统&#xff1a;1 作用2 类的三个加载过程3 类加载器的分类4 双亲委派机制 & Tomcat为何不遵循5 两个 class 对象为同一个类的必要条件三 运行时数据区&#xff1a;PC寄存器&#xff08;Program Counter Register&#xff09;四…

SM2 国密算法被 Linux 内核社区接受

喜欢就关注我们吧&#xff01;10 月 25 日&#xff0c;有开发者发文称&#xff0c;SM2 国密算法终于被 Linux 内核社区接受了。该作者表示&#xff0c;SM2 的补丁已经更新到了 v7 版本&#xff0c;这个版本的补丁最终被社区接受&#xff0c;目前已经合并到了 Linux 主线的 5.10…

后端学习 - MyBatis

MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的 持久层框架 文章目录一 基于配置文件的 MyBatis 搭建1 搭建过程&#xff08;增删改&#xff09;2 查询操作3 特殊操作二 MyBatis 获取参数值的方式1 单个字面量类型的参数2 多个字面量类型的参数3 Map 类型的参数4 实体…

国产操作系统发展离不开人才和市场

日前&#xff0c;中国 1024 程序员节盛大举行&#xff0c;一大批开源大咖齐聚千年岳麓&#xff0c;围绕开源标准、生态、人才发展等主题分享&#xff0c;共议开源软件与操作系统未来。其中&#xff0c;统信软件总经理刘闻欢表示&#xff0c;“有了市场才会被真正的用起来”&…

后端学习 - Redis

文章目录一 Redis 概述Redis 为什么是单线程&#xff0c;单线程为什么这么快&#xff1f;数据存储结构二 常用数据类型1 String2 HashHash 的扩容机制&#xff1a;渐进式 rehash*3 List4 Set5 Zset三 Redis 事务1 乐观锁与 watch 命令2 事务的三个特性四 Redis 持久化1 RDB(Red…

再被补刀!Flash又遭抛弃,你会怀念它吗?

喜欢就关注我们吧&#xff01;微软近日发布通知&#xff0c;称更新了关于 Adobe Flash Player 的删除。微软更新目录站点可下载更新 KB4577586&#xff0c;用于删除 Flash Player。此更新适用于所有受支持的操作系统版本。重要版本 Windows 10 和 Windows 8.1 的可选更新也将在…

4位加法器的设计代码verilog_HDLBits:在线学习Verilog(六 · Problem 25-29)

本系列文章将和读者一起巡礼数字逻辑在线学习网站 HDLBits 的教程与习题&#xff0c;并附上解答和一些作者个人的理解&#xff0c;相信无论是想 7 分钟精通 Verilog&#xff0c;还是对 Verilog 和数电知识查漏补缺的同学&#xff0c;都能从中有所收获。附上传送门&#xff1a;M…

译 | 将数据从Cosmos DB迁移到本地JSON文件

点击上方蓝字关注“汪宇杰博客”原文&#xff1a;Azure Tips and Tricks翻译&#xff1a;汪宇杰在Cosmos DB中使用数据迁移工具有一项重复的任务是将数据从一种数据库格式迁移到另一种数据库格式。我最近使用Cosmos DB作为数据库来存储Ignite大会发出的所有推文。然而一旦获得了…

在线教育后端开发项目总结

文章目录一 数据库访问接口1 MyBatis2 Spring Data JPA3 Spring Data MongoDB二 数据库1 MySQL2 MongoDB3 Redis三 开发规范化、响应格式与异常处理1 开发规范2 响应格式3 异常处理四 RabbitMQ五 Spring Cloud 相关工具1 Eureka2 Ribbon3 Feign4 Zuul 网关六 搜索服务1 Elastic…

通讯故障_掌握PLC必备知识,人机界面和 PLC 出现通讯故障如何分析解决

此次主要在阐述人机界面和 PLC 通讯时的模式状态&#xff0c;并列举了通讯故障实例。帮助大伙加深对这俩者的了解&#xff0c;掌握起来也不再是难题&#xff0c;解决掉拦路虎。一 台数 显 四 辊 卷 板 机PLC 控 制 系 统 核 心 与 人机界面在使用过程中&#xff0c;出现人机界面…

后端学习 - 设计模式与设计原则

文章目录设计原则1 单一职责原则2 开闭原则3 Liskov 替换原则4 依赖倒置原则5 接口隔离原则6 迪米特法则设计模式&#xff1a;创建型模式1 工厂模式2 抽象工厂模式3 单例模式设计模式&#xff1a;行为型模式1 观察者模式2 模板模式3 备忘录模式设计模式&#xff1a;结构型模式1…

ai的预览模式切换_AI字体制作,用AI制作创意阶梯式文字

本篇教程通过AI制作一款创意阶梯式文字&#xff0c;教程中有很多知识点需要掌握&#xff0c;比如路径分割为网络&#xff0c;3D效果应用等&#xff0c;我们要利用他们创造出我们需要的文字出来&#xff0c;具体是如何制作的&#xff0c;我们通过教程一起来学习一下吧。效果图&a…

新版本 Swashbuckle swagger 组件中的 坑

新版本 Swashbuckle swagger 组件中的 Servers 坑Intro上周做了公司的项目升级&#xff0c;从 2.2 更新到 3.1&#xff0c; swagger 直接更新到了最新&#xff0c;swagger 用的组件是 Swashbuckle.AspNetCore&#xff0c;然后遇到一个 swagger 的问题&#xff0c; 在本地测试是…

后端学习 - MySQL存储引擎、索引与事务

文章目录一 存储引擎1 MyISAM 与 InnoDB 的差异二 索引1 主键索引与二级索引、索引覆盖、延迟关联2 聚簇索引与非聚簇索引3 数据结构3.1 哈希表3.2 B树3.3 B树3.4 跳表3.5 为什么不使用红黑树3.6 为什么不使用B树**4 索引下推 ICP **5 索引失效&#xff08;索引不命中&#xff…

. NET5正式版本月来袭,为什么说gRPC大有可为?

当前企业正在慢慢改用微服务架构来构建面向未来的应用程序&#xff0c;微服务使企业能够有效管理基础架构&#xff0c;轻松部署更新或改进&#xff0c;并帮助IT团队的创新和学习。它还可以帮助企业能够设计出可以轻松按需扩展的应用程序&#xff0c;此外&#xff0c;随着企业转…

后端学习 - 操作系统

文章目录一 基本概念1 操作系统的特征2 操作系统的位置3 计算机的硬件组成4 中断与异常5 系统调用二 进程管理1 进程控制块 PCB&#xff08;Process Control Block&#xff09;2 进程的状态与转换3 进程间的通信4 线程5 调度算法6 死锁7 PV 操作三 内存管理1 内存的非连续分配2…

西门子触摸屏脚本程序_通过驿唐PLC501远程下载Smart Line触摸屏

通过驿唐PLC-501远程下载Smart Line触摸屏一、触摸屏设置将PLC-501和Smart 700 IE V3通过网线连到一起。触摸屏上电后&#xff0c;点击Control Panel进入控制面板界面。进入控制面板后&#xff0c;点击Ethernet设置IP地址&#xff0c;与PLC-501联网宝在同一个网段。联网宝的IP地…

.NET for Apache Spark 1.0 版本发布

.NET for Apache Spark 1.0 现已发布&#xff0c;这是一个用于 Spark 大数据的 .NET 框架&#xff0c;可以让 .NET 开发者轻松地使用 Apache Spark。该软件包由微软和 .NET Foundation 牵头&#xff0c;经过大约两年的开发。在 2019 年的 Spark AI 峰会上&#xff0c;微软曾宣…

fillrect不填充被覆盖的区域 mfc_quot;条带覆盖quot;猜想的中二证明:quot;球面条线覆盖或点覆盖quot;积分π...

注销&#xff1a;“黎曼猜想”复平面质数单向“虚”圆柱螺旋&#xff1a;几何法证明&#xff0c;技术应用​zhuanlan.zhihu.com假设有这样一部针点打印机从球心对球面打印&#xff0c;外部有一台蓝牙打印&#xff0c;球面打印蓝牙条带打印同步&#xff0c;球面被覆盖&#xff0…