Shaiju T
Shaiju T

Reputation: 6609

How to receive json post data in a Webhook

We are using 3rd party api kraken.io to optimize our images.

The results of optimized image is posted in a Webhook.

In their api document it states: After the optimization is over Kraken will POST a message to the callback_url specified in your request in a JSON format application/json.

I am using ngrok to allow remote webhooks to send data to my development machine, using this article.

Results posted to the Callback 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"
}

Class to Map

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; }
}

Action Method

[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);

 }     

But When I debug the received jsonString in Html Visualizer it looks like key and value pairs instead of Json format.

Received Results not Json Formatted:

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

I guess the received data content-type: is application/x-www-form-urlencoded.

Why i am receiving key and value pairs instead of Json format ? how can I deserialize Json data in asp.net mvc ?

Upvotes: 4

Views: 9135

Answers (3)

Shaiju T
Shaiju T

Reputation: 6609

I was able to convert Query String Key and Value pairs to Json Format using this and this post ,there is some delay to convert form Dictionary to Json, so If there is better answers, then do post and advice, below is my solution.

Action Method

[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);

}

Recieving JSON formated optimized results from kraken API.

As mentioned by @karim79, To get JSON back, you need to set a "json": true flag in the request.

As Kraken .Net/C# SDK didn't have option to set "json": true, so i have to extend their base class.

Extended Base Class:

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; }

}

Request 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);

Action Method

[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);

}

Upvotes: 1

karim79
karim79

Reputation: 342635

Co-founder of https://kraken.io here.

There is a glaring omission in our documentation which I will fix today. To get JSON back, you need to set a "json": true flag in the request. Omitting that flag or setting "json": false will return URLEncoded. Example cURL request:

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 [email protected]

Sorry for the inconvenience :-(

Upvotes: 6

methababu
methababu

Reputation: 13

Step 1: Create an aspx page. This page must be able to accept HTTP POST request. Step 2: Add this code to get HTTP POST data.File: default.aspx.cs File: 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();

Step 3: Create webhook. This code can be linked to a button on click event.File: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();

Step 4: Activate webhook. Copy that webhook id from the text file and past it to the code below. File: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");

Step 5: Test 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();

Step 6: Deserialize body of JSON object. We need to create class structure based on JSON data. I put sample json here and it created required classes

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; }
}

Once you have created your class, append the code from step 2 after

var json = reader.ReadToEnd();

to deserialize and parse 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
}

Upvotes: 0

Related Questions