本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2024-11(6)

webapi [FromBody]string获取入参为null, asp.net webapi [FromBody]string 获取不到POST数据的解决方法

发布于2024-11-02 12:01     阅读(522)     评论(0)     点赞(16)     收藏(2)


目录

引言

参数绑定机制

[FromBody] 特性和 JSON 格式

示例说明

正确的请求

错误的请求

解决方案

自定义模型绑定器

测试自定义模型绑定器

总结

问题扩展

Content-Type: application/json

Content-Type: text/plain

自定义模型绑定器(继续)

更新自定义模型绑定器

更新自定义属性

应用自定义属性

测试新的绑定器

总结


引言

最近做一个项目,需要给对方提供一个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的参数绑定机制可以分为以下几个部分:

  1. 简单类型与复杂类型:简单类型包括 intstringbool 等,复杂类型包括自定义对象、数组、集合等。
  2. 绑定源:参数可以从不同的地方绑定,如查询字符串、路由数据、表单数据和请求体等。
  3. 特性标注ASP.NET Web API使用特性(Attributes)来明确指定参数绑定的源,例如 [FromUri][FromBody]
  4. 内容类型:请求的内容类型(Content-Type)也会影响参数的绑定和解析。

[FromBody] 特性和 JSON 格式

当你使用 [FromBody] 特性时,ASP.NET Web API会从请求体中读取数据并绑定到该参数。此时,有几个关键点需要注意:

  1. 内容类型(Content-Type):通常,客户端会发送 Content-Type: application/json 来告诉服务器请求体的格式是 JSON。
  2. JSON 格式:按照 JSON 标准,字符串类型的值必须使用双引号包裹。

例如,以下是一个有效的 JSON 请求体:

"yourStringValue"

而未被双引号包裹的字符串不是有效的 JSON 格式,解析器无法理解它。

示例说明

假设你有以下控制器方法:

  1. [HttpPost]
  2. [Route("api/YourController/MessageProcess")]
  3. public IHttpActionResult MessageProcess([FromBody] string message)
  4. {
  5. if (message == null)
  6. {
  7. return BadRequest("Message is required.");
  8. }
  9. // 处理 message
  10. return Ok("Message received: " + message);
  11. }
正确的请求

为了使 message 参数正确绑定,客户端应该发送如下的请求:

  1. POST /api/YourController/MessageProcess HTTP/1.1
  2. Host: your-api-url
  3. Content-Type: application/json
  4. Content-Length: 17
  5. "yourStringValue"

在这种情况下,message 的值将是 "yourStringValue"

错误的请求

如果客户端发送未被双引号包裹的字符串:

  1. POST /api/YourController/MessageProcess HTTP/1.1
  2. Host: your-api-url
  3. Content-Type: application/json
  4. Content-Length: 14
  5. yourStringValue

由于 yourStringValue 不是有效的 JSON 格式字符串,ASP.NET Web API 解析器无法正确解析它,导致 message 参数的值为 null

解决方案

为了处理未被双引号包裹的字符串,可以使用自定义模型绑定器,这样你可以控制如何解析请求体中的数据。

自定义模型绑定器
  1. 创建自定义模型绑定器类
    1. public class RawStringModelBinder : IModelBinder
    2. {
    3. public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
    4. {
    5. if (bindingContext.ModelType != typeof(string))
    6. {
    7. return false;
    8. }
    9. var task = actionContext.Request.Content.ReadAsStringAsync();
    10. task.Wait();
    11. bindingContext.Model = task.Result;
    12. return true;
    13. }
    14. }

  2. 创建自定义属性
    1. public class FromRawStringAttribute : ModelBinderAttribute
    2. {
    3. public FromRawStringAttribute() : base(typeof(RawStringModelBinder)) { }
    4. }

 3. 应用自定义属性:

  1. [HttpPost]
  2. [Route("api/YourController/MessageProcess")]
  3. public IHttpActionResult MessageProcess([FromRawString] string message)
  4. {
  5. if (message == null)
  6. {
  7. return BadRequest("Message is required.");
  8. }
  9. // 处理 message
  10. return Ok("Message received: " + message);
  11. }

测试自定义模型绑定器

客户端可以发送以下请求:

  1. POST /api/YourController/MessageProcess HTTP/1.1
  2. Host: your-api-url
  3. Content-Type: text/plain
  4. Content-Length: 14
  5. 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

例如:

  1. POST /api/YourController/MessageProcess HTTP/1.1
  2. Host: your-api-url
  3. Content-Type: application/json
  4. Content-Length: 14
  5. yourStringValue

在这种情况下,由于 yourStringValue 不是有效的JSON格式,ASP.NET Web API将无法正确解析和绑定该数据。

Content-Type: text/plain

Content-Type 设置为 text/plain 时,请求体将被视为纯文本数据。ASP.NET Web API将直接读取请求体的内容,而不会进行JSON解析,这样可以避免格式检查问题。

例如:

  1. POST /api/YourController/MessageProcess HTTP/1.1
  2. Host: your-api-url
  3. Content-Type: text/plain
  4. Content-Length: 14
  5. yourStringValue

在这种情况下,ASP.NET Web API将成功解析并绑定 yourStringValue

自定义模型绑定器(继续)

为了支持未被双引号包裹的字符串并且仍然使用 application/json 作为 Content-Type,你可以继续使用自定义模型绑定器,但需要稍微调整逻辑以便处理不同的 Content-Type

更新自定义模型绑定器
  1. public class RawStringModelBinder : IModelBinder
  2. {
  3. public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
  4. {
  5. if (bindingContext.ModelType != typeof(string))
  6. {
  7. return false;
  8. }
  9. if (actionContext.Request.Content.Headers.ContentType.MediaType == "application/json")
  10. {
  11. var task = actionContext.Request.Content.ReadAsStringAsync();
  12. task.Wait();
  13. // 解析 JSON 内容并去除多余的引号
  14. var jsonString = task.Result.Trim('"');
  15. bindingContext.Model = jsonString;
  16. }
  17. else
  18. {
  19. var task = actionContext.Request.Content.ReadAsStringAsync();
  20. task.Wait();
  21. bindingContext.Model = task.Result;
  22. }
  23. return true;
  24. }
  25. }
更新自定义属性

属性定义保持不变:

  1. public class FromRawStringAttribute : ModelBinderAttribute
  2. {
  3. public FromRawStringAttribute() : base(typeof(RawStringModelBinder)) { }
  4. }
应用自定义属性

在你的控制器中使用自定义属性:

  1. [HttpPost]
  2. [Route("api/YourController/MessageProcess")]
  3. public IHttpActionResult MessageProcess([FromRawString] string message)
  4. {
  5. if (message == null)
  6. {
  7. return BadRequest("Message is required.");
  8. }
  9. // 处理 message
  10. return Ok("Message received: " + message);
  11. }

测试新的绑定器

现在你可以发送以下请求:

  1. POST /api/YourController/MessageProcess HTTP/1.1
  2. Host: your-api-url
  3. Content-Type: application/json
  4. Content-Length: 14
  5. yourStringValue

或者:

  1. POST /api/YourController/MessageProcess HTTP/1.1
  2. Host: your-api-url
  3. Content-Type: text/plain
  4. Content-Length: 14
  5. yourStringValue

两种情况下,自定义模型绑定器都将正确解析和绑定 message 参数。

总结

默认情况下,Content-Type: application/json 期望请求体是有效的JSON格式。如果请求体不是有效的JSON格式,解析将失败。为了支持未被双引号包裹的字符串,可以使用 Content-Type: text/plain 或者使用自定义模型绑定器来处理不同的 Content-Type。通过自定义模型绑定器,你可以灵活地解析和绑定请求体数据,无论其 Content-Type 为何。




所属网站分类: 技术文章 > 博客

作者:代码搬运工

链接:http://www.qianduanheidong.com/blog/article/534360/639775f116949c95ba70/

来源:前端黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

16 0
收藏该文
已收藏

评论内容:(最多支持255个字符)