【问题标题】:Post parameter is always nullPost 参数始终为空
【发布时间】:2012-06-11 16:29:19
【问题描述】:

自从升级到 RC for WebAPI 后,在我的 WebAPI 上调用 POST 时遇到了一些真正奇怪的问题。 我什至回到了新项目中生成的基本版本。所以:

public void Post(string value)
{
}

并从 Fiddler 调用:

Header:
User-Agent: Fiddler
Host: localhost:60725
Content-Type: application/json
Content-Length: 29

Body:
{
    "value": "test"
}

当我调试时,永远不会分配字符串“value”。它总是空的。 有人遇到这个问题吗?

(我第一次看到更复杂类型的问题)

该问题不仅与 ASP.NET MVC 4 绑定,RC 安装后的全新 ASP.NET MVC 3 项目也会出现同样的问题

【问题讨论】:

  • 只是为了增加问题 - 它不是 JSON 独有的,XML 也会发生。
  • 我已经为此奋斗了两天,在阅读了我能找到的每一篇文章之后,结果证明它就像在 WebRequest 中正确格式化 JSON 字符串一样简单:数据必须开始并且以双引号结尾,如果你在整个 json 数据中使用单引号,一切都会很好。

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


【解决方案1】:

将正文中的单个参数正确传递给 WebAPI 可以使用此代码 $.post(url, { '': productId }

并在行动中抓住它[HttpPost] public ShoppingCartAddRemoveViewModel Delete([FromBody]string value)

关键是使用魔术字'价值'。它也可能是 int 或一些原始类型。 无论是内容类型还是标题更正 麻烦的是这段代码在 mvc post action 中不起作用。

【讨论】:

    【解决方案2】:

    问题是您的操作方法需要一个简单的类型,即字符串参数值。你提供的是一个对象。

    您的问题有 2 个解决方案。

    1. 使用“value”属性创建一个简单的类,然后将该类用作参数,在这种情况下,Web API 模型绑定将从请求中读取 JSON 对象并将其绑定到您的参数对象“值”属性。

    2. 只要传递字符串值“test”,就可以了。

    【讨论】:

      【解决方案3】:

      API:

      [HttpPost]
      public bool UpdateTicketStatus(Ticket t)
      {    
          string Id=t.Id;
      }
      

      型号:

      public class Ticket
      {
          public int Id { get; set; }
          public string AssignedTo { get; set; }
          public string State { get; set; }
          public string History { get; set; }
      }
      

      使用 Post man 工具将内容作为带有原始数据的 json 发送,如下所示。有效

      { "id":"169248", "分配给":"xxxx", “状态”:“承诺”, “历史”:“test1” }

      请确保您已启用 Cors。

      [EnableCors(origins: "*", headers: "*", methods: "*")]
          public class TicketController : ApiController
          {
      }
      

      【讨论】:

        【解决方案4】:

        在我的例子中,使用 Newtonsoft 的 [JsonObject(MemberSerialization.OptOut)] 属性装饰参数类就可以了。

        例如:

        [HttpPost]
        [Route("MyRoute")]
        public IHttpActionResult DoWork(MyClass args)
        {
           ...
        }
        
        [JsonObject(MemberSerialization.OptOut)]
        public Class MyClass
        {
            ...
        }
        

        【讨论】:

          【解决方案5】:

          如果您在 Postman 中的 json 查询中有此字符 '\',如果您需要 json 字符串值中的字符 '\',则应将其转义。

          例子:

          {
              "path": "C:\\Users\\Test\\Documents\\test.txt"
          }
          

          【讨论】:

            【解决方案6】:

            希望这会有所帮助。

            查看不同的 cmets 和其他论坛,我混合了一些 sn-ps,对我来说,此代码有效...

            ...在控制器中

            public HttpResponseMessage Post([FromBody] string jsonData)
                {
                    HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, jsonData);            
            
                    try 
                    {
                        string jsonString = jsonData.ToString();
                        JArray jsonVal = JArray.Parse(jsonString) as JArray;
                        dynamic mylist= jsonVal;
                        foreach (dynamic myitem in mylist)
                        {
                            string strClave=string.Empty;
                            string strNum=string.Empty;
                            string strStatus=string.Empty;
            
                            strClave = myitem.clave;
                            strNum=myitem.num;
                            strStatus = myitem.status; 
                        }
            

            ... 在 WebApiConfig.cs 中包含此行以避免 [FromBody] 变量中的空值 var jsonFormatter = config.Formatters.OfType().First();

            public static void Register(HttpConfiguration config)
                { 
                        config.Routes.MapHttpRoute(
                                        name: "DefaultApi",
                                        routeTemplate: "api/{controller}/{id}",
                                        defaults: new { id = RouteParameter.Optional }
                                    );
                        var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();  /*this line makes no more null when use [FromBody]*/
            }
            

            ....在客户端,最重要的是在序列化数据之前连接等号(string json = "=" + SerialData;)

            我使用的是seralize

            System.Web.Script.Serialization.JavaScriptSerializer serializer = new 
            System.Web.Script.Serialization.JavaScriptSerializer();
            
                    List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
                    Dictionary<string, object> row;
                    foreach (DataRow dr in DsCnx.Tables[0].Rows)
                    {
                        row = new Dictionary<string, object>();
                        foreach (DataColumn col in DsCnx.Tables[0].Columns)
                        {
                            row.Add(col.ColumnName, dr[col]);
                        }
                        rows.Add(row);
                    }
                    SerialData= serializer.Serialize(rows);
                   PostRequest("http://localhost:53922/api/Demo", SerialData);
            

            这是我的 PostRequest 函数,这里我使用的 Content Type 是 httpWebRequest.ContentType = "application/x-www-form-urlencoded; charset=utf-8";

            private static string PostRequest(string url, string SerialData)
                {         
                    string result = String.Empty;
                    HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
                    httpWebRequest.ContentType = "application/x-www-form-urlencoded; charset=utf-8";
                    httpWebRequest.Method = "POST";
            
                    using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
                    {
                        string json = "=" + SerialData;  
                        streamWriter.Write(json);
                        streamWriter.Flush();
                        streamWriter.Close();
                    }
                    try
                    {
                        using (var response = httpWebRequest.GetResponse() as HttpWebResponse)
                        {
                            if (httpWebRequest.HaveResponse && response != null)
                            {
                                using (var reader = new StreamReader(response.GetResponseStream()))
                                {
                                    result = reader.ReadToEnd();
                                }
                            }
                        }
                    }
                    catch (WebException e)
                    {
                        if (e.Response != null)
                        {
                            using (var errorResponse = (HttpWebResponse)e.Response)
                            {
                                using (var reader = new StreamReader(errorResponse.GetResponseStream()))
                                {
                                    string error = reader.ReadToEnd();
                                    result = error;
                                }
                            }
            
                        }
                    }
            
                    return result.ToString();
            
                }
            

            这是我找到一个代码示例供参考的链接:

            https://weblog.west-wind.com/posts/2012/Aug/30/Using-JSONNET-for-dynamic-JSON-parsing#jobject-and-jarray-in-aspnet-web-api

            https://blog.codenamed.nl/2015/05/12/why-your-frombody-parameter-is-always-null/

            【讨论】:

              【解决方案7】:

              我知道 OP 最初发送的是单个字符串,但为了将来参考,还值得注意的是,格式错误的 JSON 也将作为 null 到达 post 方法。就我而言,两个属性之间缺少逗号会导致原本没问题的东西中断。

              【讨论】:

                【解决方案8】:

                我尝试了这个帖子中的许多答案,但没有一个对我有用。然后我发现了一个类似帖子的答案:https://stackoverflow.com/a/40853424/2120023,他提到了HttpContext.Request.Body,所以又进行了一次搜索,我发现了这个https://stackoverflow.com/a/1302851/2120023,它给了我HttpContext.Current,所以我终于用它来工作了:

                HttpContext.Current.Request.Form.Get("value");
                

                我对邮递员的要求:

                curl --location --request POST 'https://example.com/token' --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'value=test'
                

                【讨论】:

                  【解决方案9】:

                  有一天我遇到了和你一样的问题,就我而言,问题是,我用作 json 容器的类没有 get 和 set 定义,所以 API 不知道如何将 JSON 数据填充到实例中。

                  我的示例 json 类是 .

                  public class Usuario
                  {
                      public int id { get; set; }
                      public string nombre { get; set; }
                  }
                  

                  如您所见,您分别拥有 get 和 set,所以它会被填满。

                  如果您删除它们,您将获得创建该类的空实例的帖子。

                  【讨论】:

                    【解决方案10】:

                    通过 AJAX 调用发送原始数据上传图像时,我遇到了类似的问题,无论是否带有 [FromBody] 标签。当 请求太大 控制器将其转储(变量 = null),因此解决方案是增加最大请求大小、调整图像大小或类似方法。

                    这里描述了增加请求大小的方法:https://stackoverflow.com/a/16403447

                    【讨论】:

                      【解决方案11】:

                      这个链接帮助了我:http://encosia.com/using-jquery-to-post-frombody-parameters-to-web-api/

                      基本上它说你应该为参数使用一个空名称:

                      public string Post([FromBody]string myParameter){ 
                      ...
                      }  
                      
                      $.post("/api/dosomething", { '' : "myvalue" });
                      

                      【讨论】:

                      • 仅供参考:chrome 在该 url 上发出红色火警警报,说它是恶意软件。不确定这是否是误报,但请注意
                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 2016-11-22
                      • 2017-08-09
                      • 2017-06-07
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2017-02-06
                      相关资源
                      最近更新 更多