Deserializing HttpWebResponse from JSON API in c# - c#

I know that such of these topics existing a lot here on stackoverflow.
But I have a little bit different problem:
I have created a DataContract Class like below:
[DataContract]
public class GLSParcelClass {
internal string Location;
internal string ConsignmentId;
internal string Labels;
internal List<Parcels> ParcelList;
internal List<Returns> ReturnList;
}
[DataContract]
public class Parcels {
internal string Location;
internal string TrackId;
internal string ParcelNumber;
}
[DataContract]
public class Returns {
internal string Location;
internal string TrackId;
internal string ParcelNumber;
}
Then I wrote the following function:
WebRequest httpWebRequest = WebRequest.Create(this.GLSUri);
string json = "{" +
"\"shipperId\":\"2764200001 276a165X14\"," +
"\"references\":[\"47110815\"]," +
"\"addresses\":{" +
"\"delivery\":{" +
"\"name1\":\"Max Meyer\"," +
"\"name2\":\"Meyer Ltd.\"," +
"\"street1\":\"Meyer Str. 227\"," +
"\"street2\":\"2. Floor\"," +
"\"country\":\"DE\"," +
"\"zipCode\":\"92753\"," +
"\"city\":\"Passau\"," +
"\"email\":\"maxmeyer#gmail.com\"}}," +
"\"parcels\":[" +
"{" +
"\"weight\":2.5," +
"\"references\":[" +
"\"47110815\"]" +
"}" +
"]" +
"}";
httpWebRequest.ContentType = "application/json";
Type type = httpWebRequest.Headers.GetType();
System.Reflection.BindingFlags flags = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic;
System.Reflection.MethodInfo m = type.GetMethod("AddWithoutValidate", flags);
m.Invoke(httpWebRequest.Headers, new string[] { "Accept", "application/json" });
m.Invoke(httpWebRequest.Headers, new string[] { "Accept-Language", "de" });
m.Invoke(httpWebRequest.Headers, new string[] { "Accept-Encoding", "gzip,deflate" });
httpWebRequest.Method = "POST";
string lsEncodedCred = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("utf-8").GetBytes("shipmentsapi" + ":" + "shipmentsapi"));
httpWebRequest.Headers.Add("Authorization", "Basic " + lsEncodedCred);
httpWebRequest.PreAuthenticate = true;
StreamWriter streamWriter = null;
using (streamWriter = new StreamWriter(httpWebRequest.GetRequestStream())) {
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (StreamReader loStream = new StreamReader(httpResponse.GetResponseStream())) {
GLSParcelClass deserializedParcels = new GLSParcelClass();
string lsJSON = loStream.ReadToEnd();
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(lsJSON));
DataContractJsonSerializer ser = new DataContractJsonSerializer(deserializedParcels.GetType());
deserializedParcels = ser.ReadObject(ms) as GLSParcelClass;
ms.Close();
}
I got the answer "Created" with status code 201 from the JSON API in the response header. So far so good. But when I will get the ResponseStream I get the error "System.Runtime.Serialization.SerializationException - Error while deserializing the object. Unexpected char ".".".
Alternative I have tested it with the Mozilla REST client. And I will get the correct header with a correct response stream.
The response stream included also a base64 string encoded pdf document.
I really don't know what's wrong and I hope you can help me.
Thx a lot in advance.
Milo

I just be able to post a very small part of the JSON response as on the screenshot:
JSON response part
If I'm opening the JSON quick view at the monitoring window, I just get the message back "string is not JSON formated".
Milo

Related

C# Make HttpWebResponse wait until response has been received instead of receiving HTTP 400 Error

I am trying to access Adobe's Datawarehouse reporting using their API. The way it works is by first forming the JSON using the metrics available and the dimensions you want it to be brojen down by. That all works fine. However where I do have the issue comes down to this. Whenever I request more than 3 to 4 dimensions, the report takes longer to generate. I would need the HttpWebResponse to wait until it has been completed before moving to the next line. Below is my sample code that I have built based on an example from github.
class Program
{
protected static string JSONFolder = System.Configuration.ConfigurationManager.AppSettings["JSONFolder"];
protected static string USERNAME = System.Configuration.ConfigurationManager.AppSettings["Username"];
protected static string SECRET = System.Configuration.ConfigurationManager.AppSettings["Secret"];
protected static string ReportSuiteID = System.Configuration.ConfigurationManager.AppSettings["ReportSuiteID"];
private static string ENDPOINT = "https://api5.omniture.com/admin/1.4/rest/";
protected static string environment = "dev";
static void Main(string[] args)
{
DateTime previousDay = DateTime.Today.AddDays(-1);
string json = RequestJsonBuilder(previousDay, previousDay, ReportSuiteID);
string response = callMethod("Report.Queue", json, 15);
var jss = new JavaScriptSerializer();
var requestDetails = jss.Deserialize<Dictionary<string, string>>(response);
}
/*Build the json for the methods Report.GetStatus and Report.Get*/
public static string RequestJsonBuilderStatus(string id)
{
ReportID json = new ReportID() { reportID = id };
var serializer = new JavaScriptSerializer();
var serializedResult = serializer.Serialize(json);
return serializedResult;
}
/*Build the json for the method Report.Queue*/
static string RequestJsonBuilder(DateTime StartDate, DateTime EndDate, string ReportSuiteID)
{
//Build the list of metrics to send with the request
var listMetrics = new List<Metrics>();
listMetrics.Add(new Metrics() { id = "visits" });
//Build the list of elements to send with the request
var listElements = new List<Elements>();
listElements.Add(new Elements() { id = "page" , top = "25"});
var serializer2 = new JavaScriptSerializer();
Dictionary<string, RankedRequest> dic = new Dictionary<string, RankedRequest>();
dic.Add("reportDescription", new RankedRequest()
{
reportSuiteID = ReportSuiteID,
dateFrom = StartDate.ToString("yyyy-MM-dd"),
dateTo = EndDate.ToString("yyyy-MM-dd"),
metrics = listMetrics,
elements = listElements,
source = "warehouse"
});
var serializedResult2 = serializer2.Serialize(dic);
return serializedResult2;
}
/*Build the rest call to the Adobe Analytics REST APII 1.4*/
public static String callMethod(String method, String data, int secs)
{
Program prog = new Program();
HttpWebResponse statusResponse = null;
string responseXml = "";
StringBuilder sbUrl = new StringBuilder(ENDPOINT + "?method=" + method);
HttpWebRequest omniRequest = (HttpWebRequest)WebRequest.Create(sbUrl.ToString());
string timecreated = generateTimestamp();
string nonce = generateNonce();
string digest = getBase64Digest(nonce + timecreated + SECRET);
nonce = base64Encode(nonce);
omniRequest.Headers.Add("X-WSSE: UsernameToken Username=\"" + USERNAME + "\", PasswordDigest=\"" + digest + "\", Nonce=\"" + nonce + "\", Created=\"" + timecreated + "\"");
omniRequest.Method = "POST";
omniRequest.ContentType = "text/json";
//Write the json details to the request
using (var streamWriter = new StreamWriter(omniRequest.GetRequestStream()))
{
string json = data;
Console.WriteLine("\n 2.0 ############## Json request : \n\n " + json + "\n\n");
streamWriter.Write(json);
}
//Get the response of the request
try
{
Console.WriteLine("\n 2.0 ############## Sleeping thread for " + secs + "\n");
using (HttpWebResponse statusResponse = (HttpWebResponse) omniRequest.GetResponse())
{
using (Stream receiveStream = statusResponse.GetResponseStream())
{
using (StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8))
{
responseXml = readStream.ReadToEnd();
return responseXml;
}
}
}
}
catch (Exception ex) { throw ex; }
}
// other methods defined below
// private static string getBase64Digest(string input)
// private static string generateNonce()
// public static string base64Encode(string data)
// etc.
}
How do I make HttpWebResponse wait until a HTTP 200 response is actually received. This might take minutes to sometimes an hour depending on the number of metrics and dimensions I add.
Things I have tried also include changing line 88 to something like this:
How to process WebResponse when .NET throws WebException ((400) Bad Request)?
how to wait until a web request with HttpWebRequest is finished?
Sincerely appreciate all help here.
Thanks
Did you try setting the timeout? I was looking recently for the similar question and found that one:
HttpWebRequest.GetResponse() keeps getting timed out

Error 400 GCM Invalid Request json

I am completely new to this kind of programming so I don't really know if there is an answer to this already, but I weren't able to find it. So I am testing to see if I can get a dry-run gcm message to work without errors.
The error I get is the error 400 Invalid Request, and it's saying something about the json being invalid, so I have assumed the problem has to do with string manipulation or the definition of postdata, but I can't figure it out. Most of the code is just copy pasted anyway so one could believe that others in a similar situation will get the same error, if they copy from the same source.
And also I have put in actual values for the "lorem"s.
This is the only code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Web.Script.Serialization;
namespace ServerGMC
{
public class ServerGMC
{
static void Main ()
{
// Prepares and calls the function to send message
List<string> RedIdList = new List<string>(1) { "aaaaaaaaaaaaaaaaaaaaaaaa" };
RedIdList.TrimExcess();
Console.WriteLine(SendNotification(RedIdList, "HelloWorld", "test", 220299));
Console.Read();
}
static public string SendNotification(List<string> deviceRegIds, string message, string title, long id)
{
try
{
string regIds = string.Join("\",\"", deviceRegIds);
string AppId = "lorem";
var SenderId = "lorem";
NotificationMessage nm = new NotificationMessage();
nm.Title = title;
nm.Message = message;
nm.ItemId = id;
var value = new JavaScriptSerializer().Serialize(nm);
WebRequest wRequest;
wRequest = WebRequest.Create("https://android.googleapis.com/gcm/send");
wRequest.Method = "post";
wRequest.ContentType = " application/json;charset=UTF-8";
wRequest.Headers.Add(string.Format("Authorization: key={0}", AppId));
wRequest.Headers.Add(string.Format("Sender: id={0}", SenderId));
string postData = "{\"collapse_key\":\"standard\",\"time_to_live\":108,\"delay_while_idle\":true,\"dry_run\":true,\"data\": { \"message\" : " + "\"" + value + "\",\"time\": " + "\"" + System.DateTime.Now.ToString() + "\"},\"registration_ids\":[\"" + regIds + "\"]}";
//string postData = "collapse_key=score_update&time_to_live=108&delay_while_idle=1&data.message=" + value + "&date.time=" + System.DateTime.Now.ToString() + "&registration_ids=" + regIds + "";
Console.WriteLine(postData);
Byte[] bytes = Encoding.UTF8.GetBytes(postData);
wRequest.ContentLength = bytes.Length;
Stream stream = wRequest.GetRequestStream();
stream.Write(bytes, 0, bytes.Length);
stream.Close();
WebResponse wResponse = wRequest.GetResponse();
stream = wResponse.GetResponseStream();
StreamReader reader = new StreamReader(stream);
String response = reader.ReadToEnd();
HttpWebResponse httpResponse = (HttpWebResponse)wResponse;
string status = httpResponse.StatusCode.ToString();
reader.Close();
stream.Close();
wResponse.Close();
if (status == "")
{
return response;
}
else
{
return "";
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
Console.WriteLine();
return "";
}
}
private class NotificationMessage
{
public string Title;
public string Message;
public long ItemId;
}
}
}
The postData isn't properly formatted in JSON. If you check it out using an online formatting tool, it looks like this
{
"collapse_key":"standard",
"time_to_live":108,
"delay_while_idle":true,
"dry_run":‌​true,
"data":{
"message":"{"Title":"test",
"Message":"HelloWorld",
"ItemId":220299}",
"time":"22/04/2016 13:04:38"
},
"registration_ids":["aaaaaaaaaaaaaaaaaaaaaaaa"]
}
You can either remove the data.message node and place its properties in data, or use a 3rd-party JSON parser or System.Web.Helpers.Json.Decode (which were suggested in this issue)
Hopefully this helps with the issue.
Happy coding!

Getting error while passing json string to Rest service(POST) in C#

I'm trying to send the JSON data to the REST service but getting error. The JSON data is {"Project":111,"itemType":123,"fields":{"name":"Test","Description":"Tseting only"}}
Below is the code
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);//I'm passing the url from as a parameter
request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(System.Text.Encoding.Default.GetBytes("xxxx:xxxx"));
request.ContentType = "text/json";
request.Method = "POST";
//string names = "praneeth";
using (StreamWriter streamWriter = new StreamWriter(request.GetRequestStream()))
{
string json =
"{ \"project\": 111," +
"\"itemType\": 123," +
"\"fields\":\"{ \"name\":\"Test\"," + "\"description\":\"Testing only\"}\"}";
streamWriter.Write(json);
}
WebResponse response = request.GetResponse();
Stream dataStream = response.GetResponseStream();
StreamReader sreader = new StreamReader(dataStream);
string responsereader = sreader.ReadToEnd();
response.Close();
The error I'm getting is
{"meta":{"status":"Bad
Request","timestamp":"2015-08-04T22:40:55.645+0000","message":"Can not
instantiate value of type java.util.LinkedHashMap from String value
('{ '); no single-String constructor/factory method\n at [Source:
org.glassfish.jersey.message.internal.EntityInputStream#50e3274b;
line: 1, column: 33] (through reference chain:
com.jamasoftware.contour.rest.v1.domain.RequestItem[\"fields\"])"}}
You say the JSON data is this:
{"Project":111,"itemType":123,"fields":{"name":"Test","Description":"Tseting only"}}
But what you're actually constructing is this:
{ "project": 111,"itemType": 123,"fields":"{ "name":"Test","description":"Testing only"}"}
Which is not valid JSON.
So, remove those extra quotes.
You are currently sending fields as a string, which is not valid for the target type of that property. Take out the encapsulating quotation marks, to send this a object instead.
Such as the following:
string json =
"{"
+ "\"project\": 111,"
+ "\"itemType\": 123,"
+ "\"fields\": { "
+ "\"name\" : \"Test\","
+ "\"description\":\"Testing only\""
+ "}" +
"}";
streamWriter.Write(json);
I would also recommend deserializing from your own Object rather than concatenated string literals. This makes forming your JSON a lot easier, and safer.

Posting tasks to asana through API stopped working

I wrote a program to post tasks to asana through the API and it has been working fine up until this morning, can anyone help me figure out why that is?
this is an example of the JSON string I am sending:
{"workspace":09876543321111,"data": {"assignee":null,"name":"Sample Name","notes":"Sample Noted","due_on":"2015-01-27","projects":"12434567889099","completed":false}}
and I am getting a 400 error: bad request.
this is my code:
string ID = "09876543321111"; //workspace ID
string url = #"https://app.asana.com/api/1.0/workspaces/" + ID + #"/tasks";
Data dat = new Data();
string ProjName = "Test Project";
dat.projects = "1234567890234";
dat.assignee = null;
dat.name = "Sample Name";
dat.notes = "Sample Notes";
dat.due_on = val.requiredBy.Value.ToString("u").Substring(0, 10);
dat.completed = false;
//if task doesnt exist, make one
if (!Tasks.CheckExist(project, dat.projects, dat.name, apiKey, log))
{
string json = JsonConvert.SerializeObject(dat);
string data = "{\"workspace\":" + ID + ",\"data\": " + json + "}";
log.WriteLine(data);
Functions.Post(data, url, apiKey, log);
}
Post function:
//post tasks to asana
public static void Post(string data, string url, string apiKey, StreamWriter log)
{
byte[] bytes = Encoding.UTF8.GetBytes(data);
var req = (HttpWebRequest)WebRequest.Create(url);
req.Method = WebRequestMethods.Http.Post;
req.ContentLength = bytes.Length;
req.ContentType = "application/json";
var authInfo = apiKey + ":";
var encodedAuthInfo = Convert.ToBase64String(
Encoding.Default.GetBytes(authInfo));
req.Headers.Add("Authorization: Basic " + encodedAuthInfo);
req.ContentLength = bytes.Length;
Stream reqStream = req.GetRequestStream();
reqStream.Write(bytes, 0, bytes.Length);
reqStream.Close();
try
{
HttpWebResponse response = (HttpWebResponse)req.GetResponse();
string res = new StreamReader(response.GetResponseStream()).ReadToEnd();
}
catch (WebException ex)
{
HttpWebResponse response = ((HttpWebResponse)ex.Response);
string exc = url + " caused a " + (int)response.StatusCode + " error.\n" + response.StatusDescription;
Console.WriteLine(exc);
log.WriteLine(exc);
}
}
EDIT
for anyone who cares I solved the problem by changing string data to:
string data = "{\"data\": " + json + "}";
We recently made a change to return a 400 error if there were unexpected parameters passed at the top level, as (nearly) all API routes only use the parameters passed in under the "data" attribute. In this case (as you correctly determined) the "workspace" attribute at the top level was incorrect - previously we just ignored it, but in an effort to make the API less "surprising" we wanted to be explicit and strict about parameters that could be ignored, as otherwise it could be misleading.

GetResponse throws 400 Bad request

Getting 400 bad Request When trying to get the Response from my HTTPS post request. Here is my code:
try
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://coupons.valassis.eu/capi/directPrint/"+offerID);
httpWebRequest.Credentials = new NetworkCredential(userName,Password);
WebHeaderCollection myWebHeaderCollection = httpWebRequest.Headers;
myWebHeaderCollection.Add("Authorization: Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(httpWebRequest.Credentials.ToString())));
myWebHeaderCollection.Add("x-valassis-country-code: uk");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Accept = "application/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "[{ \"consumerId\": \"000000000000001\", \"remoteConsumerId\": \"000000000000001\" , \"Barcode\": \"Itf: 04910033400000000000000001,Ean13:ccode\", \"Type\": \"j\", \"returnUrl\": \"http://www.durex.co.uk\",\"CouponDescription\" : \"Coupon For:\"" + this.FirstName + " " + this.SurName + "\" }]";
var serializer = new JavaScriptSerializer();
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (Stream streamReader =httpResponse.GetResponseStream())
{
using (StreamReader r = new StreamReader(streamReader))
{
var result = r.ReadToEnd();
}
}
}
}
catch (WebException e)
{
}
Any one knows what might be the problem? or How to solve this issue?
The JSON string that you create is invalid, as the CouponDescription property contains an odd number of quotes.
If i run this....
var FirstName = "Joe";
var SurName = "Bloggs";
var json = "[{ \"consumerId\": \"000000000000001\", \"remoteConsumerId\": \"000000000000001\" , \"Barcode\": \"Itf: 04910033400000000000000001,Ean13:ccode\", \"Type\": \"j\", \"returnUrl\": \"http://www.durex.co.uk\",\"CouponDescription\" : \"Coupon For:\"" + FirstName + " " + SurName + "\" }]";
I get...
[{ "consumerId": "000000000000001", "remoteConsumerId": "000000000000001" , "Barcode": "Itf: 04910033400000000000000001,Ean13:ccode", "Type": "j", "returnUrl": "http://www.durex.co.uk","CouponDescription" : "Coupon For:"Joe Bloggs" }]
Look at the CouponFor value, the quotes are not closed.
Tools like LINQPad and JSONLint are very useful for validating code snippets in these scenarios

Categories

Resources