发布于2024-11-02 12:01 阅读(522) 评论(0) 点赞(16) 收藏(2)
目录
Content-Type: application/json
最近做一个项目,需要给对方提供一个WebApi服务接收消息,服务已经写好了,对方调用多次,但我的webapi接收到的内容始终为空,于是就安装了Postman-win64测试工具进行调试,我的Postman-win64测试工具资源分享地址如下(不要积分,免费下载):https://download.csdn.net/download/martian665/89909226
经过调试,发现以body中Content-Type: application/json类型POST string数据时参数在使用 [FromBody]
特性时必须被双引号包裹。加上双引号后果然POST string数据正常了,如下:
这是为什么呢?本篇文章将进行详细讲解。
在ASP.NET Web API中,参数绑定是一个非常重要的机制,尤其是当你从HTTP请求中提取并处理数据时。以下是对ASP.NET Web API中接收和处理参数的机制进行深入讲解,并结合示例说明为什么字符串类型的参数在使用 [FromBody]
特性时必须被双引号包裹。
ASP.NET Web API的参数绑定机制可以分为以下几个部分:
int
、string
、bool
等,复杂类型包括自定义对象、数组、集合等。[FromUri]
、[FromBody]
。[FromBody]
特性和 JSON 格式当你使用 [FromBody]
特性时,ASP.NET Web API会从请求体中读取数据并绑定到该参数。此时,有几个关键点需要注意:
Content-Type: application/json
来告诉服务器请求体的格式是 JSON。例如,以下是一个有效的 JSON 请求体:
"yourStringValue"
而未被双引号包裹的字符串不是有效的 JSON 格式,解析器无法理解它。
假设你有以下控制器方法:
- [HttpPost]
- [Route("api/YourController/MessageProcess")]
- public IHttpActionResult MessageProcess([FromBody] string message)
- {
- if (message == null)
- {
- return BadRequest("Message is required.");
- }
-
- // 处理 message
- return Ok("Message received: " + message);
- }
为了使 message
参数正确绑定,客户端应该发送如下的请求:
- POST /api/YourController/MessageProcess HTTP/1.1
- Host: your-api-url
- Content-Type: application/json
- Content-Length: 17
-
- "yourStringValue"
在这种情况下,message
的值将是 "yourStringValue"
。
如果客户端发送未被双引号包裹的字符串:
- POST /api/YourController/MessageProcess HTTP/1.1
- Host: your-api-url
- Content-Type: application/json
- Content-Length: 14
-
- yourStringValue
由于 yourStringValue
不是有效的 JSON 格式字符串,ASP.NET Web API 解析器无法正确解析它,导致 message
参数的值为 null
。
为了处理未被双引号包裹的字符串,可以使用自定义模型绑定器,这样你可以控制如何解析请求体中的数据。
- public class RawStringModelBinder : IModelBinder
- {
- public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
- {
- if (bindingContext.ModelType != typeof(string))
- {
- return false;
- }
-
- var task = actionContext.Request.Content.ReadAsStringAsync();
- task.Wait();
- bindingContext.Model = task.Result;
- return true;
- }
- }
- public class FromRawStringAttribute : ModelBinderAttribute
- {
- public FromRawStringAttribute() : base(typeof(RawStringModelBinder)) { }
- }
3. 应用自定义属性:
- [HttpPost]
- [Route("api/YourController/MessageProcess")]
- public IHttpActionResult MessageProcess([FromRawString] string message)
- {
- if (message == null)
- {
- return BadRequest("Message is required.");
- }
-
- // 处理 message
- return Ok("Message received: " + message);
- }
客户端可以发送以下请求:
- POST /api/YourController/MessageProcess HTTP/1.1
- Host: your-api-url
- Content-Type: text/plain
- Content-Length: 14
-
- yourStringValue
在这种情况下,message
参数值将是 yourStringValue
,即使它未被双引号包裹。
在ASP.NET Web API中,使用 [FromBody]
特性绑定字符串参数时,必须确保传入的字符串是有效的 JSON 格式,即被双引号包裹。这是因为ASP.NET Web API依赖于 JSON 解析器来处理请求体数据。为了处理未被双引号包裹的字符串数据,可以使用自定义模型绑定器,从而更灵活地解析和绑定请求体数据。
如果Content-Type: text/plain和Content-Type: application/json都需要支持,怎么解决?
下面将进行讲解:
在ASP.NET Web API中,Content-Type
标头用于指示请求体的媒体类型。默认情况下,ASP.NET Web API对不同的 Content-Type
会有不同的解析方式。
Content-Type: application/json
当 Content-Type
设置为 application/json
时,ASP.NET Web API会使用JSON解析器来解析请求体。如果请求体不是有效的JSON格式(例如一个未被双引号包裹的字符串),解析将会失败,导致参数值为 null
。
例如:
- POST /api/YourController/MessageProcess HTTP/1.1
- Host: your-api-url
- Content-Type: application/json
- Content-Length: 14
-
- yourStringValue
在这种情况下,由于 yourStringValue
不是有效的JSON格式,ASP.NET Web API将无法正确解析和绑定该数据。
Content-Type: text/plain
当 Content-Type
设置为 text/plain
时,请求体将被视为纯文本数据。ASP.NET Web API将直接读取请求体的内容,而不会进行JSON解析,这样可以避免格式检查问题。
例如:
- POST /api/YourController/MessageProcess HTTP/1.1
- Host: your-api-url
- Content-Type: text/plain
- Content-Length: 14
-
- yourStringValue
在这种情况下,ASP.NET Web API将成功解析并绑定 yourStringValue
。
为了支持未被双引号包裹的字符串并且仍然使用 application/json
作为 Content-Type
,你可以继续使用自定义模型绑定器,但需要稍微调整逻辑以便处理不同的 Content-Type
。
- public class RawStringModelBinder : IModelBinder
- {
- public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
- {
- if (bindingContext.ModelType != typeof(string))
- {
- return false;
- }
-
- if (actionContext.Request.Content.Headers.ContentType.MediaType == "application/json")
- {
- var task = actionContext.Request.Content.ReadAsStringAsync();
- task.Wait();
- // 解析 JSON 内容并去除多余的引号
- var jsonString = task.Result.Trim('"');
- bindingContext.Model = jsonString;
- }
- else
- {
- var task = actionContext.Request.Content.ReadAsStringAsync();
- task.Wait();
- bindingContext.Model = task.Result;
- }
-
- return true;
- }
- }
属性定义保持不变:
- public class FromRawStringAttribute : ModelBinderAttribute
- {
- public FromRawStringAttribute() : base(typeof(RawStringModelBinder)) { }
- }
在你的控制器中使用自定义属性:
- [HttpPost]
- [Route("api/YourController/MessageProcess")]
- public IHttpActionResult MessageProcess([FromRawString] string message)
- {
- if (message == null)
- {
- return BadRequest("Message is required.");
- }
-
- // 处理 message
- return Ok("Message received: " + message);
- }
现在你可以发送以下请求:
- POST /api/YourController/MessageProcess HTTP/1.1
- Host: your-api-url
- Content-Type: application/json
- Content-Length: 14
-
- yourStringValue
或者:
- POST /api/YourController/MessageProcess HTTP/1.1
- Host: your-api-url
- Content-Type: text/plain
- Content-Length: 14
-
- yourStringValue
两种情况下,自定义模型绑定器都将正确解析和绑定 message
参数。
默认情况下,Content-Type: application/json
期望请求体是有效的JSON格式。如果请求体不是有效的JSON格式,解析将失败。为了支持未被双引号包裹的字符串,可以使用 Content-Type: text/plain
或者使用自定义模型绑定器来处理不同的 Content-Type
。通过自定义模型绑定器,你可以灵活地解析和绑定请求体数据,无论其 Content-Type
为何。
作者:代码搬运工
链接:http://www.qianduanheidong.com/blog/article/534360/639775f116949c95ba70/
来源:前端黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 前端黑洞网 All Rights Reserved 版权所有,并保留所有权利。 京ICP备18063182号-3
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!