手机版

Asp.Net核心控制器如何接收原始请求正文内容的详细说明

时间:2021-08-30 来源:互联网 编辑:宝哥软件园 浏览:

主要目标

在Asp.net核心控制器中,自定义处理控制器中的“未知”内容由自定义格式化程序映射。本文将详细介绍Asp.Net酷睿控制器收到的原始请求体的内容,并分享给大家参考。下面的话就不多说了,我们来看看详细的介绍。

简单案例

为了演示这个问题,我们使用VS2017来创建一个默认的Asp.net核心网络应用编程接口项目。

[Route(' API/[controller]')][API controller]公共类值controller : controller base {[HttpGet]public ActionResultstring Get(){ return ' ok ';}[httpset][Route(' PostX ')]public ActionResultstring Post([from body]字符串值){返回值;} }Json请求

让我们从最常见的json输入请求开始。

用户代理: fiddlerhost : localhost :5000内容类型:应用程序/JSON内容长度: 16请求正文:

{'123456'}我们可以通过后台调试和提琴手抓取看到请求输入和返回。

后台调试,查看请求输入结果

提琴手视图请求标题

Fiddler查看返回的结果

注意!

不要忘记[FromBody],有时候你会忘记。当后台操作的接收类型是字符串时,请求体只能是字符串,不能是json对象。当我演示这个例子时,我被这个愚弄了。如果接收对象是一个类,可以传递json对象。

没有JSON

虽然json数据传输是最常用的,但有时我们需要支持普通的文本或二进制信息。我们将内容类型更改为文本/纯文本

用户代理: fiddler主机: localhost :5000内容类型:文本/纯内容长度: 16请求正文:

{'123456'}悲惨事件来了,报告404!

不支持文本/纯文本

此时事情变得有点复杂,因为asp.netcore只处理它知道的类型,比如json和formdata。默认情况下,原始数据不能直接映射到控制器参数。这是一个小坑。我想知道你是否踩了它。你仔细想想,这是有道理的。MVC具有特定内容类型的映射,如果您传递的数据不符合这些内容类型,则数据无法转换,因此它假设没有匹配的端点可以处理该请求。那么如何支持原始请求映射呢?

支持原始文本请求

不幸的是,ASP.NET核心不允许您仅通过方法参数以任何有意义的方式捕获“原始”数据。无论如何,您都需要对它进行一些自定义处理,即请求。主体,以获取原始数据,然后对其进行反序列化。

您可以捕获原始数据请求。正文,并直接从中读取原始缓冲区。

最简单、侵入性最小但不太明显的方法是使用一种方法来接受不带参数的POST或PUT数据,然后从Request的以下位置读取原始数据。正文:

读取字符串缓冲区

[HttpSet][Route(' PostText ')]公共异步任务字符串PostText() {使用(stream reader reader=new stream reader(Request。正文,编码。UTF8)) {返回等待阅读器。ReadToEndAsync();}}这适用于Http和文本

用户代理: fiddlerhost : localhost :5000内容类型:文本/纯内容长度: 6要读取二进制数据,可以使用以下内容:

读取字节缓冲区

[httpset][Route(' post binary ')]public async Taskbyte[]PostBinary(){使用(var ms=new memory stream(2048)){ wait Request。Body . CopyToAsync(毫秒);返回ms . ToArray();//返回base64编码字符串JSON结果}}查看执行结果

接收文本内容

接收二进制数据

HttpRequest静态扩展

如果为了方便而编写大量的HttpRequest扩展,那么在接收参数时可以看起来更简洁。

公共静态类http request extension {///summary///////summary///param name=' http request '/param///param name=' encoding '/param///返回/返回公共静态异步taskstring GetRawBodyStringformatter(此对象为Httprequest,编码编码){ if(编码==null){编码=编码.{ UTF8 }使用(流阅读器=新的流阅读器(Httprequest .正文,编码)){返回等待读者ReadToEndAsync();} } ///摘要///二进制////summary///param name=' HttpRequest '/param///param name=' Encoding '/param///返回/返回公共静态async Taskbyte[]GetRawBodyBinaryformatter(此对象为Httprequest,Encoding){ if(Encoding==null){ Encoding=Encoding .{ UTF8 }使用(流阅读器=新的流阅读器(Httprequest .身体,编码)){使用(var ms=new memory stream(2048)){ 0等待httpRequest .尸体。复制同步(毫秒);返回ToArray女士();//返回base64编码字符串数据结果} } } }[HttpSet][Route(' PostTextX ')]公共异步tasksstring PostTextX(){ 0返回等待请求getrawbodystringsyn();} ///摘要///接收////summary///returns/returns[httpset][Route(' PostBinaryX ')]public async Taskbyte[]PostBinaryX(){ return wait Request .GetRawBodyBinaryAsyn();}自动转换文本和二进制值

上面虽然解决了原始参数转换问题,但不够友好。如果你打算像原生手动音量调节那样自动映射参数的话,你需要做一些自定义格式化适配。

创建一个Asp.net最有价值球员输入格式器

ASP .净核心使用一种干净且更通用的方式来处理内容的自定义格式输入格式器。输入格式化程序挂钩到请求处理管道,让您查看特定类型的内容以确定是否要处理它。然后,您可以阅读请求正文并对入站内容执行自己的反序列化。

输入格式器有几个要求

您需要使用[FromBody]去获取您必须能够查看请求并确定是否以及如何处理内容。在这个例子中,对于"原始内容",我想查看具有以下类型的请求:

文本/纯文本(文本)应用/八位字节流(字节[])没有内容类型(字符串)要创建格式化程序,你可以实现输入格式化程序或者从输入格式器继承。

公共类RawRequestBodyFormatter : IInputFormatter { public RawRequestBodyFormatter()} { public bool CanRead(InputFormatterContext){ if(context==Null)引发新的ArgumentNullException(“”参数为null’);var contentType=context .请求内容类型;如果(字符串IsNullOrEmpty(内容类型)| |内容类型==' text/plain ' | |内容类型==' application/octet-stream ')返回真实的返回false}公共异步任务输入格式结果读取异步(输入格式上下文上下文){ var request=context .请求;var contentType=context .请求内容类型;如果(字符串IsNullOrEmpty(内容类型)| |内容类型.toLower()==' text/plain '){ 0使用(流阅读器=新的流阅读器(请求。正文,编码{ var content=wait reader .ReadToEndAsync();返回等待输入格式结果。成功异步(内容);} } if(内容类型==' application/octet-stream '){ 0使用(流阅读器=新的流阅读器(请求。正文,编码. UTF8){ }使用(var ms=new memory stream(2048)){ 0等待请求身体。复制同步(毫秒);var content=ms to array();返回等待输入格式结果。成功异步(内容);} } }返回等待输入格式结果失败同步();} }格式化程序用于CanRead()检查对内容类型的请求以支持,然后将ReadRequestBodyAsync()内容读取和反序列化为应在控制器方法的参数中返回的结果类型。

输入格式器必须在配置服务()启动代码中注册MVC:

public void ConfigureServices(IServiceCollection services){ services .AddMvc(o=o . inputformatters。插入(0,新的RawRequestBodyFormatter()).SetCompatibilityVersion(兼容性版本.版本_ 2 _ 1);}接受原始输入

[httpset][Route(' post text plus ')]公共字符串PostTextPlus([FromBody]字符串值){返回值;}然后你就可以发送邮政请求,像这样:

用户代理:虚拟主机:本地主机:5000内容长度: 6或者

用户代理:虚拟主机:本地主机:5000内容类型:文本/普通内容长度: 6请注意,您可以使用内容类型调用相同的控制器方法应用程序/json并传递数据字符串,这也将起作用。在RawRequestBodyFormatter简单地增加它支持的附加内容类型的支持。

二进制数据

[httpset][Route(' PostBinaryPlus ')]公共字节[] PostBinaryPlus([FromBody]字节[]值){返回值;}请求内容如下:

用户代理:虚拟主机:本地主机:5000内容长度: 6内容类型:应用程序/八位字节流源代码

示例代码已上传到CsharpFanDemo(本地下载)

参考链接

本文包含翻译和自己实践。主要思路和代码来源于以下链接:接受ASP。网核心应用编程接口控制器中的原始请求正文内容

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

版权声明:Asp.Net核心控制器如何接收原始请求正文内容的详细说明是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。