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-TypeSupportedMediaTypes.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相关推荐
- asp.net core 自定义基于 HttpContext 的 Serilog Enricher
asp.net core 自定义基于 HttpContext 的 Serilog Enricher Intro 通过 HttpContext 我们可以拿到很多有用的信息,比如 Path/QuerySt ...
- asp.net core 自定义 Policy 替换 AllowAnonymous 的行为
asp.net core 自定义 Policy 替换 AllowAnonymous 的行为 Intro 最近对我们的服务进行了改造,原本内部服务在内部可以匿名调用,现在增加了限制,通过 identit ...
- ASP.NET Core 改变 content 和 web root(wwwroot) 目录路径
ASP.NET Core 改变 content 和 web root 根目录路径 先说方法: 方法一: 添加环境变量 ASPNETCORE_CONTENTROOT 与 ASPNETCORE_WEBRO ...
- 解决 ASP.NET Core 自定义错误页面对 Middleware 异常无效的问题
我们基于 Razor Class Library 实现了自定义错误页面的公用类库(详见之前的随笔),但是在实际使用时发现如果在 middleware 中发生了异常,则不能显示自定义错误页面,而是返回默 ...
- asp.net core自定义依赖注入容器,替换自带容器
依赖注入 在asp.net core程序中,众所周知,依赖注入基本上贯穿了整个项目,以通用的结构来讲解,控制器层(Controller层)依赖业务层(Service层),业务层依赖于仓储层(Repos ...
- asp.net core 自定义401和异常显示内容(JWT认证、Cookie Base认证失败显示内容)
asp.net core 2.0使用JWT认证园子里已经有挺多帖子了,但开发中发现认证未授权情况下返回的401状态码是没有任何信息的,业务中可能有需要返回一串错误的Json信息.在这里我分享一个自定义 ...
- ASP.NET Core自定义响应内容
问题 在业务开发中,对Web API的返回格式有一定要求,需要是定制化的Json结构,用于前端统一处理: {Status : 0,Message: "",Info : xxx } ...
- asp.net core 自定义异常处理中间件
Intro 在 asp.net core 中全局异常处理,有时候可能不能满足我们的需要,可能就需要自己自定义一个中间件处理了,最近遇到一个问题,有一些异常,不希望记录错误日志,目前主要是用户请求取消导 ...
- ASP.NET Core 自定义认证方式--请求头认证
Intro 最近开始真正的实践了一些网关的东西,最近写几篇文章分享一下我的实践以及遇到的问题. 本文主要介绍网关后面的服务如何进行认证. 解决思路 网关可以做一部分的认证和授权,服务内部有时候也会需要 ...
最新文章
- Goldman Sachs 2020校招 Engineer岗
- 1.httpClient和ScrollView
- C#调用vbs脚本实现Windows版Siri
- [react] 为什么建议setState的第一个参数是callback而不是一个对象呢?
- 使用data()方法缓存数据
- 设置和开通freebsd远程登录
- openstack horizon dashboard_OpenStack最新版本:Ussuri发布亮点
- 如何在恢复模式下启动 Mac?
- Elasticsearch5.x 升级
- 自建服务器选择标准,自建CDN如何选择服务器
- 亲测可用sqlyog激活注册码
- ubuntuv20启动界面美化_小米任务栏美化软件下载-小米任务栏美化官方版软件下载v1.0...
- 计算机网络-3-局域网数据链路层原理与技术
- appfuse mysql_AppFuse 2.1的安装运行步骤
- 段码超低功耗LCD液晶显示驱动芯片(IC)-VKL系列-VKL128/060/076/144A/144B,VKL144A兼容MCP144
- 月入万元或不需缴税!九张图带你看懂个税新规
- 过滤:sql、敏感词、html、js、css
- postgresql常用命令和执行sql脚本
- 创建自己的ERC20加密货币(可管理、增发、兑换、冻结等高级功能的代币)
- 遥感数据下载——FIRM:VIIRS火点数据、MODIS火点数据简介及下载
热门文章
- QCustomplot(一) 能做什么事
- ubuntu linux下建立stm32开发环境: 程序烧录 openocd+openjtag
- 数据库_7_SQL基本操作——表操作
- Java 打飞机(小游戏)[版权非本人 本人制作收藏整理]
- HTTPS协议开通,Apache服务器CSR签名申请
- 社交网络图中结点的“重要性“计算(Dijkstra + SPFA + Floyd + 模板)
- BFS HDOJ 2102 A计划
- NOI导刊模拟2—电话网络 解题报告
- android 设备名称_如何更改您的Android TV的设备名称
- 学习韩立刚老师IT运维课程,成为韩立刚老师正式学生,在全国范围为你就近推荐工作。...