asp.net core 实现支持自定义 Content-Type
asp.net core 实现支持自定义 Content-Type
Intro
我们最近有一个原本是内网的服务要上公网,在公网上有一层 Cloudflare
作为网站的公网流量提供者,CloudFlare 会有一层防火墙拦截掉一些非法的请求,我们有一些 API 会提交一些 html 内容,经过 Cloudflare
的时候会被 Cloudflare
拦截,导致某些功能不能够正常使用,于是就想对提交的数据进行一个编码之后再提交,服务器端针对需要解码的请求进行解码再解析,我们新加了一个 Content-Type
的支持,编码后的数据使用新的 Content-Type
,对于不编码的数据依然可以工作,目前我们做了一个简单的 base64 编码,如果需要的话也可以实现复杂一些的加密、压缩等。
Basis
asp.net core 默认支持 JSON 请求,因为内置了针对 JSON 内容的 Formatter
,.NET Core 2.x 使用的是 Newtonsoft.Json
作为默认 JSON formatter,从 .NET Core 3.0 开始引入了 System.Text.Json
作为默认的 JSON formatter,如果要支持 XML 需要引入针对 XML 的 formatter,相应的如果需要增加其他类型的请求实现自己的 formatter 就可以了
Formatter 分为 InputFormatter
和 OutputFormatter
InputFormatter
用来解析请求Body
的数据,将请求参数映射到强类型的 model,Request Body => ValueOutputFormatter
用来将强类型的数据序列化成响应输出,Value => Response Body
Formatter 需要指定支持的 MediaType
,可以理解为请求类型,体现在请求头上,对于 InputFormatter
对应的就是 Content-Type
,对于 OutputFormatter
对应的是 Accept
,asp.net core 会根据请求信息来选择注册的 formatter。
Sample
先来看一下实现效果吧,实现效果如下:
swagger 的支持也算比较好了,在增加了新的 Content-Type
支持之后在 swagger 上可以看得到,而且可以切换请求的 Content-Type
,上图中的 text/base64-json
就是我自定义的一个 Content-Type
默认请求:
对原始请求进行 base64 编码,再请求:
Implement
实现代码如下:
public class Base64EncodedJsonInputFormatter : TextInputFormatter
{
public Base64EncodedJsonInputFormatter()
{
// 注册支持的 Content-Type
SupportedMediaTypes.Add("text/base64-json");
SupportedEncodings.Add(Encoding.UTF8);
}
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
{
try
{
using var reader = context.ReaderFactory(context.HttpContext.Request.Body, encoding);
var rawContent = await reader.ReadToEndAsync();
if (string.IsNullOrEmpty(rawContent))
{
return await InputFormatterResult.NoValueAsync();
}
var bytes = Convert.FromBase64String(rawContent);
var services = context.HttpContext.RequestServices;
var modelValue = await GetModelValue(services, bytes);
return await InputFormatterResult.SuccessAsync(modelValue);
async ValueTask<object> GetModelValue(IServiceProvider serviceProvider, byte[] stringBytes)
{
var newtonJsonOption = serviceProvider.GetService<IOptions<MvcNewtonsoftJsonOptions>>()?.Value;
if (newtonJsonOption is null)
{
await using var stream = new MemoryStream(stringBytes);
var result = await System.Text.Json.JsonSerializer.DeserializeAsync(stream, context.ModelType,
services.GetRequiredService<IOptions<JsonOptions>>().Value.JsonSerializerOptions);
return result;
}
var stringContent = encoding.GetString(bytes);
return Newtonsoft.Json.JsonConvert.DeserializeObject(stringContent, context.ModelType, newtonJsonOption.SerializerSettings);
}
}
catch (Exception e)
{
context.ModelState.TryAddModelError(string.Empty, e.Message);
return await InputFormatterResult.FailureAsync();
}
}
}
上述代码兼容了使用 System.Text.Json
和 Newtonsoft.Json
,在发生异常时将错误信息添加一个 ModelError
以便在前端可以得到错误信息的反馈,例如传一个不合法的 base64 字符串就会像下面这样:
实际使用的时候,只需要在 Startup
里配置一下就可以了,如:
services.AddControllers(options =>
{
options.InputFormatters.Add(new Base64EncodedJsonInputFormatter());
});
More
通过自定义 Content-Type
的支持我们可以无侵入的实现不同的请求内容,上面的示例代码可以在 Github 上获取 https://github.com/WeihanLi/SamplesInPractice/tree/master/AspNetCoreSample,可以根据自己的需要进行自定义
References
- https://docs.microsoft.com/en-us/aspnet/core/web-api/advanced/custom-formatters?view=aspnetcore-5.0
- https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/web-api/advanced/custom-formatters/samples
- https://github.com/WeihanLi/SamplesInPractice/tree/master/AspNetCoreSample
asp.net core 实现支持自定义 Content-Type的更多相关文章
- WebAPI调用笔记 ASP.NET CORE 学习之自定义异常处理 MySQL数据库查询优化建议 .NET操作XML文件之泛型集合的序列化与反序列化 Asp.Net Core 轻松学-多线程之Task快速上手 Asp.Net Core 轻松学-多线程之Task(补充)
WebAPI调用笔记 前言 即时通信项目中初次调用OA接口遇到了一些问题,因为本人从业后几乎一直做CS端项目,一个简单的WebAPI调用居然浪费了不少时间,特此记录. 接口描述 首先说明一下,基于 ...
- Asp.Net Core入门之自定义服务注册
谈到服务注册,首先我们先了解一下服务注册时使用的三种方式,也代表了不同的服务生命周期: AddTransient AddScoped AddSingleton AddSingleton生命周期最长,其 ...
- asp.net core 3.1 自定义中间件实现jwt token认证
asp.net core 3.1 自定义中间件实现jwt token认证 话不多讲,也不知道咋讲!直接上代码 认证信息承载对象[user] /// <summary> /// 认证用户信息 ...
- asp.net core 实现支持多语言
asp.net core 实现支持多语言 Intro 最近有一个外国友人通过邮件联系我,想用我的活动室预约,但是还没支持多语言,基本上都是写死的中文,所以最近想支持一下更多语言,于是有了多语言方面的一 ...
- ASP.NET Core中显示自定义错误页面-增强版
之前的博文 ASP.NET Core中显示自定义错误页面 中的方法是在项目中硬编码实现的,当有多个项目时,就会造成不同项目之间的重复代码,不可取. 在这篇博文中改用middleware实现,并且放在独 ...
- 使Asp.net Core同时支持输出Json/Xml
我们知道Asp.net Core是支持输出为Json格式的.同时也支持输出为xml格式.只要我们正确的配置.并在Request时指定正确的Accept,即可根据不同的Header来输出不同的格式. 前 ...
- ASP.NET Core中使用自定义路由
上一篇文章<ASP.NET Core中使用默认MVC路由>提到了如何使用默认的MVC路由配置,通过这个配置,我们就可以把请求路由到Controller和Action,通常情况下我们使用默认 ...
- 在ASP.NET Core中创建自定义端点可视化图
在上篇文章中,我为构建自定义端点可视化图奠定了基础,正如我在第一篇文章中展示的那样.该图显示了端点路由的不同部分:文字值,参数,动词约束和产生结果的端点: 在本文中,我将展示如何通过创建一个自定义的D ...
- ASP.NET Core - 实现Http自定义请求头策略
前言 在正常的情况下,当我们系统用到JWT认证方式时,需要在Http请求头添加Authorization: XXX,这样在后台服务的控制器中打上[Authorize]授权标签,就限定所有的请求必须通过 ...
随机推荐
- OpenStack Train版-15.创建并挂载存储卷
1.创建并挂载存储卷 创建一个1GB的卷 source ~/demo-openrc openstack volume create --size 1 volume1 很短的时间后,卷状态应该从crea ...
- spring再学习之配置详解
applicationContext.xml文件配置: bean元素: <?xml version="1.0" encoding="UTF-8"?> ...
- C# 数据类型(3)
动态类型 dynamic types 动态类型是后来引进的,他其实是一个static type,但是不像其他的静态类型,编译器不会检查你到底是啥类型(也不会检查你能不能去call某个'method') ...
- spring-cloud-eureka-client-consumer
服务注册中心eureka-server已经搭好,并且SPRING-CLOUD-NETFLIX-EUREKA-CLIENT-APPLICATION提供一个hello服务 编写一个eureka-clien ...
- sql-libs(6) 双引号的报错注入
payload:http://192.168.48.130/sqli-laaess-6/?id=1" and updatexml(1,concat(0x7e,(SELECT schema_n ...
- 读写 LED 作业 台灯的 频闪研究 2 评测&对比!
0. 读写 LED 作业 台灯的 频闪研究 2 评测&对比! 评测&对比图: 1. 日光:(中午12点) 2. Philips: (天猫 15元 5w E27白) 3. FSL: ( ...
- Node.js & ES modules & .mjs
Node.js & ES modules & .mjs Node.js v13.9.0 https://nodejs.org/api/esm.html https://nodejs.o ...
- vue动态添加当前事件下的class
html部分<div class="star"> <span v-for="(item,index) in 5" @click="c ...
- Python爬虫_百度贴吧(title、url、image_url)
本爬虫以百度贴吧为例,爬取某个贴吧的[所有发言]以及对应发言详情中的[图片链接] 涉及: request 发送请求获取响应 html 取消注释 通过xpath提取数据 数据保存 思路: 由于各贴吧发言 ...
- VMware安装centos.6.8无法访问主机的问题
安装步骤 点击下一步,如下图: 接上图: 接上图: 接上图 接上图: 接上图: 接上图: 接上图 接上图: 接上图: 接上图: 接上图: 接上图: 接上图: 点击 完成: 启动虚拟机进行安装: 发现报 ...