【问题标题】:How to receive json post data in a Webhook如何在 Webhook 中接收 json 发布数据
【发布时间】:2017-07-03 22:39:03
【问题描述】:

我们正在使用第 3 方 api kraken.io 来优化我们的图像。

优化图像的结果发布在Webhook

在他们的 api 文档中它指出:优化结束后,Kraken 将以JSON 格式application/json 向您的请求中指定的callback_url 发送消息POST

我正在使用ngrok 允许远程webhooks 将数据发送到我的开发机器,使用this 文章。

发布到回调 URL 的结果:

HTTP/1.1 200 OK

{
    "id": "18fede37617a787649c3f60b9f1f280d",
    "success": true,
    "file_name": "header.jpg",
    "original_size": 324520,
    "kraked_size": 165358,
    "saved_bytes": 159162,
    "kraked_url": "http://dl.kraken.io/18/fe/de/37617a787649c3f60b9f1f280d/header.jpg"
}

要映射的类

public class KrakenOptimizedResults
{
public string id { get; set; }
public bool success { get; set; }
public string file_name { get; set; }
public int original_size { get; set; }
public int kraked_size { get; set; }
public int saved_bytes { get; set; }
public string kraked_url { get; set; }
}

动作方法

[HttpPost]
public ActionResult OptimizedWebHook()
{

  Request.InputStream.Position = 0;

  string jsonString = new System.IO.StreamReader(Request.InputStream).ReadToEnd();

  KrakenOptimizedResults obj = new JavaScriptSerializer().Deserialize<KrakenOptimizedResults>
  (jsonString);


  return Json(obj);

 }     

但是当我在 Html Visualizer 中 debug 接收到的 jsonString 时,它看起来像 keyvalue 对而不是 Json 格式。

收到的结果不是 Json 格式:

file_name=header.jpeg&original_size=118066&kraked_size=102459&saved_bytes=15607

我猜content-type:收到的数据是application/x-www-form-urlencoded

为什么我收到 keyvalue 对而不是 Json 格式?如何在 asp.net mvc 中反序列化 Json 数据?

【问题讨论】:

    标签: json asp.net-mvc asp.net-mvc-4 json.net kraken-image-optimizer


    【解决方案1】:

    https://kraken.io 的联合创始人在这里。

    我们的文档中有一个明显的遗漏,我今天将修复它。要取回 JSON,您需要在请求中设置 "json": true 标志。省略该标志或设置 "json": false 将返回 URLEncoded。示例 cURL 请求:

    curl http://api.kraken.io/v1/upload -X POST --form data='{"auth":{"api_key":"YOUR_KEY", "api_secret":"YOUR_SECRET"}, "wait": true, "lossy": true, "callback_url": "http://requestb.in/wbhi63wb", "json": true}' --form upload=@test.jpg
    

    很抱歉给您带来不便:-(

    【讨论】:

    • 感谢您提及,我无法使用您的.Net/C# SDK 设置 json: true 请求,因此我扩展了基类,here 是我的解决方案。如果方法Optimize 接受imageUricallbackUrloptimizeRequest 参数也会很有帮助。目前它只接受imageUricallbackUrl
    【解决方案2】:

    我能够使用 thisthis 帖子将查询字符串 KeyValue 对转换为 Json 格式,将表单 Dictionary 转换为 Json 会有一些延迟,所以如果有更好的答案,然后发帖和建议,下面是我的解决方案。

    动作方法

    [HttpPost]
    public ActionResult OptimizedWebHook()
    {
    
     Request.InputStream.Position = 0;
    
     string data = new System.IO.StreamReader(Request.InputStream).ReadToEnd();
     var dict = HttpUtility.ParseQueryString(data);
     var json = new JavaScriptSerializer().Serialize(dict.AllKeys.ToDictionary(k => k, k =>
                dict[k]));
    
     KrakenOptimizedResults obj = new JavaScriptSerializer().Deserialize<KrakenOptimizedResults>
                                 (json);
    
      return Json(obj);
    
    }
    

    从 kraken API 接收 JSON 格式的优化结果。

    正如@karim79 所说,要获取 JSON,您需要在请求中设置一个 "json": true 标志。

    由于 Kraken .Net/C# SDK 没有设置“json”的选项:true,所以我必须扩展它们的基类。

    扩展基类:

    public class OptimizeRequestBaseExtended : OptimizeRequestBase,
    IOptimizeUploadRequest, IRequest
    {
    
        public OptimizeRequestBaseExtended(Uri callbackUrl)
        {
            CallbackUrl = callbackUrl;
        }
    
       [JsonProperty("callback_url")]
       public Uri CallbackUrl { get; set; }
    
       [JsonProperty("json")]
       public bool JsonFormat { get; set; }
    
    }
    

    请求 Kraken API:

    var callbackUrl = new Uri("http://localhost:0000/Home/OptimizedWebHook");
    
    OptimizeRequestBaseExtended settings = new OptimizeRequestBaseExtended(callbackUrl);
    
    settings.Lossy = true;
    settings.JsonFormat = true;
    
    var response = client.Optimize(image: image, filename: filename, optimizeRequest: settings);
    

    动作方法

    [HttpPost]
    public ActionResult OptimizedWebHook()
    {
    
    Request.InputStream.Position = 0;
    
    string jsonString = new System.IO.StreamReader(Request.InputStream).ReadToEnd();
    
    
    KrakenOptimizedResults obj = JsonConvert.DeserializeObject<KrakenOptimizedResults>
    (jsonString);
    
      return Json(obj);
    
    }
    

    【讨论】:

      【解决方案3】:

      第 1 步: 创建一个 aspx 页面。此页面必须能够接受 HTTP POST 请求。 第2步: 添加此代码以获取 HTTP POST 数据。文件:default.aspx.cs 文件:default.aspx.cs

      var reader = new StreamReader(Request.InputStream);
      var json = reader.ReadToEnd();
      
      FileStream ostrm;
      StreamWriter writer;
      TextWriter oldOut = Console.Out;
      
      ostrm = new FileStream(@"C:\logfile4webhook.txt", FileMode.Append, FileAccess.Write);
      writer = new StreamWriter(ostrm);
      Console.SetOut(writer);
      Console.Write(DateTime.Now + " ");
      Console.WriteLine(json.ToString() + " ");
      Console.SetOut(oldOut);
      writer.Close();
      ostrm.Close();
      

      第 3 步: 创建网络挂钩。此代码可以链接到单击事件上的按钮。文件:default.aspx.cs

      AuthenticationDetails auth = new ApiKeyAuthenticationDetails("your api key");
      string listID = "";
      listID = "your list id";
      List list = new List(auth, listID);
      List<string> events = new List<string>();
      events.Add("Update");
      
      string postback = list.CreateWebhook(events, "URL", "json");
      
      FileStream ostrm;
      StreamWriter writer;
      TextWriter oldOut = Console.Out;
      
      ostrm = new FileStream(@"C:\logfile4webhook.txt", FileMode.Append, FileAccess.Write);
      writer = new StreamWriter(ostrm);
      Console.SetOut(writer);
      Console.Write(DateTime.Now + " ");
      Console.WriteLine(postback + " ");
      Console.SetOut(oldOut);
      writer.Close();
      ostrm.Close();
      

      第 4 步: 激活网络钩子。从文本文件中复制该 webhook id 并将其粘贴到下面的代码中。 文件:default.aspx.cs

      AuthenticationDetails auth = new ApiKeyAuthenticationDetails("your api key");
      string listID = "";
      listID = "your list id";
      List list = new List(auth, listID);
      list.ActivateWebhook("webhook id");
      

      第 5 步: 测试weebhook.File:default.aspx.cs

      AuthenticationDetails auth = new ApiKeyAuthenticationDetails("your api key");
      string listID = "";
      listID = "your list id";
      List list = new List(auth, listID);
      string postback = list.TestWebhook("webhook id").ToString();
      FileStream ostrm;
      StreamWriter writer;
      TextWriter oldOut = Console.Out;
      
      ostrm = new FileStream(@"C:\logfile4webhook.txt", FileMode.Append, FileAccess.Write);
      writer = new StreamWriter(ostrm);
      Console.SetOut(writer);
      Console.Write(DateTime.Now + " ");
      Console.WriteLine(postback + " ");
      Console.SetOut(oldOut);
      writer.Close();
      ostrm.Close();
      

      第 6 步: 反序列化 JSON 对象的主体。我们需要基于 JSON 数据创建类结构。我将示例 json 放在这里,它创建了所需的类

      public class CustomField
      {
          public string Key { get; set; }
          public string Value { get; set; }
      }
      
      public class Event
      {
          public List<CustomField> CustomFields { get; set; }
          public string Date { get; set; }
          public string EmailAddress { get; set; }
          public string Name { get; set; }
          public string SignupIPAddress { get; set; }
          public string Type { get; set; }
      }
      
      public class RootObject
      {
          public List<Event> Events { get; set; }
          public string ListID { get; set; }
      }
      

      创建类后,将步骤 2 中的代码附加到之后

      var json = reader.ReadToEnd();
      

      反序列化和解析json。

      RootObject myClass = JsonConvert.DeserializeObject(json);

      if (myClass != null)
      {
          List<Event> t = myClass.Events;
      
          string old_email = "", new_email = "";
          old_email = t[0].OldEmailAddress;
          new_email = t[0].EmailAddress;
      
          //now you can do your logic with old_email and new_email
      }
      

      【讨论】:

      • 谢谢,我已经编辑了我的问题并添加了asp.net mvc 它不是网络表单以明确,以及为什么您发布了大而无关的答案?
      猜你喜欢
      • 1970-01-01
      • 2017-04-07
      • 1970-01-01
      • 1970-01-01
      • 2018-06-23
      • 2022-01-02
      • 2019-02-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多