【问题标题】:FromBody string parameter is giving nullFromBody 字符串参数给出 null
【发布时间】:2017-04-12 16:47:47
【问题描述】:

这可能是非常基本的事情,但我无法弄清楚我哪里出错了。

我试图从 POST 正文中获取一个字符串,但“jsonString”只显示为空。我也想避免使用模型,但也许这是不可能的。我用 PostMan 打的代码就是这个块:

[Route("Edit/Test")]
[HttpPost]
public void Test(int id, [FromBody] string jsonString)
{
    ...
}

也许这是我对邮递员的错误处理,但我一直在尝试在正文的值部分使用“=test”(如有关此主题的其他问题中所见) - x-www-form- urlencoded 部分,键为 jsonString,什么都没有。我也尝试过使用 raw - text 和 raw - text/plain。我得到了 id,所以我知道 url 是正确的。对此的任何帮助将不胜感激。

PostMan 目前是这样设置的:

POST http://localhost:8000/Edit/Test?id=111
key = id  value = 111
Body - x-www-form-urlencoded
key = jsonString  value = "=test"

【问题讨论】:

  • 能否提供完整的 http 请求,包括问题中的 URL 和正文。
  • 至少Request.Content.ReadAsStringAsync() 应该可以工作。
  • 我相信这是可能的。设置您的标题Content-Type: application/x-www-form-urlencoded。正文应该是=test(没有别的)。
  • Asp.Net Core 相关问题stackoverflow.com/questions/31952002/…
  • 我已经为此奋斗了两天,在阅读了我能找到的每一篇文章之后,结果证明它就像在 WebRequest 中正确格式化 JSON 字符串一样简单:数据必须开始并且以双引号结尾(即在 json 数据周围的数据字符串中添加双引号),然后如果您在整个 json 数据中使用单引号,一切都会很好。

标签: c# asp.net-web-api asp.net-web-api2 postman asp.net-web-api-routing


【解决方案1】:

通过使用[FromBody] 声明 jsonString 参数,您告诉 ASP.NET Core 使用输入格式化程序将提供的 JSON(或 XML)绑定到模型。所以你的测试应该可以工作,如果你提供一个简单的模型类

public class MyModel
{
    public string Key {get; set;}
}

[Route("Edit/Test")]
[HttpPost]
public void Test(int id, [FromBody] MyModel model)
{
    ... model.Key....
}

和发送的 JSON 格式

{
    key: "value"
}

当然,您可以通过在控制器中访问HttpContext.Request 来跳过模型绑定并直接检索提供的数据。 HttpContext.Request.Body 属性为您提供内容流,或者您可以通过 HttpContext.Request.Forms 访问表单数据。

由于类型安全,我个人更喜欢模型绑定。

【讨论】:

  • @Fabio - 那么 [FromBody] 将不起作用,因为它告诉框架您要将数据绑定到模型类。为了避免绑定,请跳过此参数并按照上一段中的提示直接访问发送的数据。希望这会有所帮助。
  • 这对我有用——你只需要在 POSTMan 的 POST 选项中使用 RAW 而不是 FORM。
  • 工作就像一个魅力,谢谢。不知道为什么我们不能只从 body 传递一个字符串,但是……嗯……呵呵,谢谢
  • 如果它只是一个单一的字符串那么你不需要创建一个模型 - 你只需要传递一个 JSON 字符串,它用双引号引起来,即“测试”而不是仅仅测试.
【解决方案2】:

你在正确的轨道上。

在您的标题集上

Content-Type: application/x-www-form-urlencoded

POST 请求的正文应该是=test,没有其他内容。对于未知/变量字符串,您必须对值进行 URL 编码,这样您就不会意外地因输入字符而转义。


另见POST string to ASP.NET Web Api application - returns null

【讨论】:

    【解决方案3】:

    引用Parameter Binding in ASP.NET Web API

    使用 [FromBody]

    要强制 Web API 从请求正文中读取简单类型,请添加 [FromBody] 属性到参数:

    [Route("Edit/Test")]
    [HttpPost]
    public IHttpActionResult Test(int id, [FromBody] string jsonString) { ... }
    

    在本例中,Web API 将使用媒体类型格式化程序来读取 请求正文中 jsonString 的值。这是一个示例客户端 请求。

    POST http://localhost:8000/Edit/Test?id=111 HTTP/1.1
    User-Agent: Fiddler
    Host: localhost:8000
    Content-Type: application/json
    Content-Length: 6
    
    "test"
    

    当参数有 [FromBody] 时,Web API 使用 Content-Type 标头 选择格式化程序。在此示例中,内容类型为 "application/json" 并且请求正文是原始 JSON 字符串(不是 JSON 对象)。

    在上面的示例中,如果数据以正确的格式在正文中提供,则不需要模型。

    对于 URL 编码的请求将如下所示

    POST http://localhost:8000/Edit/Test?id=111 HTTP/1.1
    User-Agent: Fiddler
    Host: localhost:8000
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 5
    
    =test
    

    【讨论】:

    • 有没有办法通过multipart/form-data 实现这一点? AFAIK 这个不允许无钥匙进入。
    【解决方案4】:

    当具有 [FromBody] 属性时,发送的字符串不应是原始字符串,而是 JSON 字符串,因为它包含换行引号:

    "test"
    

    基于https://weblog.west-wind.com/posts/2017/Sep/14/Accepting-Raw-Request-Body-Content-in-ASPNET-Core-API-Controllers

    类似的答案string value is Empty when using FromBody in asp.net web api

     

    【讨论】:

    • 有点小技巧,但效果很好。如果不需要丰富的对象,这也是一个更好的解决方案。
    【解决方案5】:

    我知道这个答案有点老了,有一些非常好的答案已经解决了这个问题。为了扩展这个问题,我想再提一件事,让我在过去的 4 或 5 个小时里发疯。

    您的模型类中的属性启用 set 属性非常非常非常非常重要。

    不会工作(参数仍然为空):

    /* Action code */
    [HttpPost]
    public Weird NOURLAuthenticate([FromBody] Weird form) {
        return form;
    }
    /* Model class code */
    public class Weird {
        public string UserId {get;}
        public string UserPwd {get;}
    }
    

    工作:

    /* Action code */
    [HttpPost]
    public Weird NOURLAuthenticate([FromBody] Weird form) {
        return form;
    }
    /* Model class code */
    public class Weird {
        public string UserId {get; set;}
        public string UserPwd {get; set;}
    }
    

    【讨论】:

    • 谢谢!离开两者得到;并设置;也不起作用(空参数)。
    【解决方案6】:

    就我而言,我忘了使用

    JSON.stringify(bodyStuff).
    

    【讨论】:

    • 谢谢!对于任何使用 Axios 的人来说,这可能是您正在寻找的解决方案。 Axios 以一种非常具体的方式处理请求正文字符串,即使您对 "test" 这样的文字进行硬编码,请求正文也会反映 test ... 这不是有效的 json 文字。感谢 Eugene 为我节省了时间!
    【解决方案7】:

    经过 1 小时的努力,终于成功了。

    这将消除 null 问题,还以通用方式(无模型绑定)获取 JSON key1value1 值。

    对于一个新的 WebApi 2 应用示例:

    邮递员(看起来完全一样,如下所示):

    POST    http://localhost:61402/api/values   [Send]
    Body
         (*) raw             JSON (application/json) v
             "{  \"key1\": \"value1\" }"
    

    上面的端口61402或url/api/values,对你来说可能不同。

    ValuesController.cs

    using Newtonsoft.Json;
    // ..
    
    // POST api/values
    [HttpPost]
    public object Post([FromBody]string jsonString)
    {
        // add reference to Newtonsoft.Json
        //  using Newtonsoft.Json;
    
        // jsonString to myJsonObj
        var myJsonObj = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(jsonString);
    
        // value1 is myJsonObj[key1]
        var valueOfkey1 = myJsonObj["key1"];
    
        return myJsonObj;
    }
    

    现在一切都很好,不确定如果我有子键是否需要模型绑定到类,或者子键上的 DeserializeObject 可能会起作用。

    【讨论】:

      【解决方案8】:

      在与 Google 打交道并在 Stack Overflow 中尝试错误代码的漫长噩梦之后,我发现将 ([FromBody] 字符串模型) 更改为 ([FromBody] 对象模型) 确实很奇怪,我使用的是 .NET 4.0 是的我知道它很旧,但是......

      【讨论】:

        【解决方案9】:

        使用原始 JSON 发布字符串,不要忘记双引号!

        【讨论】:

          【解决方案10】:

          试试下面的代码:

          [Route("/test")]
          [HttpPost]
          public async Task Test()
          {
             using (var reader = new StreamReader(Request.Body, Encoding.UTF8))
             {
                var textFromBody = await reader.ReadToEndAsync();                    
             }            
          }
          

          【讨论】:

            【解决方案11】:

            如果您不想/不需要绑定到具体类,可以将 JSON 直接传递给 WebAPI 控制器。控制器能够通过使用 ExpandoObject 类型来接受 JSON。下面是方法示例:

            public void Post([FromBody]ExpandoObject json)
            {
                var keyValuePairs = ((System.Collections.Generic.IDictionary<string, object>)json);
            }
            

            Content-Type 标头设置为 application/json 并将 JSON 作为正文发送。 keyValuePairs 对象将包含 JSON 键/值对。

            或者您可以让方法接受传入的 JSON 作为 JObject 类型(来自 Newtonsoft JSON 库),并将其设置为 dynamic 类型,您可以访问点表示法的属性。

            public void Post([FromBody]JObject _json)
            {
                dynamic json = _json;
            }
            

            【讨论】:

              【解决方案12】:

              对于 .net core 3.1 post(url, JSON.stringify(yourVariable)) 像魅力一样工作 在控制器 MyMethod([FromBody] string yourVariable)

              【讨论】:

                【解决方案13】:

                我刚遇到这个,很沮丧。我的设置:标头设置为 Content-Type: application/JSON 并以 JSON 格式从正文传递信息,并在控制器上读取 [FromBody]。

                一切都设置得很好,我希望它可以工作,但问题在于发送过来的 JSON。由于它是一个复杂的结构,我的一个定义为“抽象”的类没有被初始化,因此没有正确地将值分配给模型。我删除了 abstract 关键字,它只是工作..!!!

                一个提示,我可以解决这个问题的方法是将数据部分发送到我的控制器并检查它何时变为空......因为它是一个复杂的模型,我一次将一个模型附加到我的请求参数。希望它对遇到这个愚蠢问题的人有所帮助。

                【讨论】:

                  【解决方案14】:

                  我花了一整天的时间来解决类似的问题。

                  您必须知道内置序列化器和 Newtonsoft 的工作方式不同。 我的内置案例无法将 JSON 编号解析为 System.String。 但我没有明显的例外或细节,只是数据为空。

                  我是在这样记录 ModelState 时才发现的:

                  logger.LogInformation($"ModelState = {ModelState.IsValid}");
                  string messages = string.Join("; ", ModelState.Values
                                      .SelectMany(x => x.Errors)
                                      .Select(x => x.ErrorMessage));
                  logger.LogInformation($"ModelMessages = {messages}");
                  

                  然后我在日志中看到了特定的异常:

                  The JSON value could not be converted to System.String
                  

                  我做了一个修复:

                  1. 安装Microsoft.AspNetCore.Mvc.NewtonsoftJson 预览 版本。
                  2. 更改为services.AddControllers().AddNewtonsoftJson();

                  解决方案取自https://stackoverflow.com/a/57652537/4871693

                  【讨论】:

                  • 正在从 asp.net core 2.x 更新,并在使用 Newtonsoft 时遇到了类似的问题。你为我节省了很多时间!
                  • @didge 很高兴能帮到你。 :)
                  • 这对解决我的问题也是非常有用的信息
                  【解决方案15】:

                  此外,如果您使用的是 Postman“环境”,请确保在运行使用该环境的 API 脚本之前选择该环境。否则,它只会发送变量字符串 -- {{varname}} -- 而不是它们的关联值,API 会适当地拒绝这些值。

                  【讨论】:

                  • 我认为您应该将此添加为评论,因为这并不能真正回答问题。
                  【解决方案16】:

                  这也可能派上用场。 我需要将 JSON 字符串传递给我的 API 控制器。但该模型是未知的。使用 JObject 作为对象类型非常有效。 您可以稍后序列化以获取字符串。

                  [FromBody] JObject unknownStringJsonObject
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2016-09-07
                    相关资源
                    最近更新 更多