I am working on a project for Windows Phone 7.1 in Visual Studio 2010. I am trying to download JSON data and deserialize it into a list of objects. The following is the code I am using to build the web request and handle the response.
public class HttpGetTask<T>
{
public HttpGetTask(string url, Action<T> onPostExecute)
{
this.Url = url;
this.OnPostExecute = onPostExecute;
}
public void Execute()
{
MessageBox.Show("We are in the task Execute method");
if (this.OnPreExecute != null)
{
this.OnPreExecute();
}
// create the http request
HttpWebRequest httpWebRequest = WebRequest.CreateHttp(this.Url);
httpWebRequest.Method = "GET";
httpWebRequest.Accept = "application/json";
// get the response asynchronously
httpWebRequest.BeginGetResponse(OnGetResponseCompleted, httpWebRequest);
}
private void OnGetResponseCompleted(IAsyncResult ar)
{
MessageBox.Show("We are in the OnGetResponseCompleted Method");
var httpWebRequest = (HttpWebRequest)ar.AsyncState;
// get the response
HttpWebResponse response;
try
{
response = (HttpWebResponse)httpWebRequest.EndGetResponse(ar);
}
catch (WebException e)
{
this.InvokeOnErrorHandler("Unable to connect to the web page.");
return;
}
catch (Exception e)
{
this.InvokeOnErrorHandler(e.Message);
return;
}
if (response.StatusCode != HttpStatusCode.OK)
{
this.InvokeOnErrorHandler((int)response.StatusCode + " " + response.StatusDescription);
return;
}
// response stream
var stream = response.GetResponseStream();
// deserialize json
var jsonSerializer = new DataContractJsonSerializer(typeof(T));
var responseObject = (T)jsonSerializer.ReadObject(stream);
// call the virtual method
this.InvokeInUiThread(() => this.OnPostExecute(responseObject));
}
The following are the DataContract classes I am using.
[DataContract]
public class OwnersList
{
public List<Owner> Owners {get; set; }
}
[DataContract]
public class Owner
{
[DataMember(Name = "oid")]
public string Oid { get; set; }
[DataMember(Name = "fname")]
public string Fname { get; set; }
[DataMember(Name = "lname")]
public string Lname { get; set; }
}
The following is a sample of te JSON data I am trying to deserialize.
[{"oid":"1","fname":"John","lname":"Doe"},{"oid":"2","fname":"Mary","lname":"Smith"},{"oid":"3","fname":"Jimi","lname":"Hendrix"},{"oid":"4","fname":"Carole","lname":"King"},{"oid":"5","fname":"John","lname":"Winchester"},{"oid":"6","fname":"John","lname":"Hurt"},{"oid":"7","fname":"Rick","lname":"Grimes"},{"oid":"8","fname":"Haris","lname":"Okic"},{"oid":"9","fname":"Dino ","lname":"Okic"},{"oid":"10","fname":"Mirza","lname":"Cirkic"}]
When I run my app, I get an Invalid Casting Exception either when creating the serializer object, or on the jsonserializer.ReadObject(stream) line. Any ideas as to why this is happening?
Related
I am trying to call the EORI validation open interface from within a C# application but am not getting anywhere.
I've looked around the site and there doesn't seem to be any documentation on how to do this.
Site: http://ec.europa.eu/taxation_customs/dds2/eos/news/newstar.jsp?Lang=en
WSDL: http://ec.europa.eu/taxation_customs/dds2/eos/validation/services/validation?wsdl
I've created a new C# Console App and added the WSDL as a service reference then tried calling the service but get the following exception...
System.ServiceModel.CommunicationException: 'The server did not
provide a meaningful reply; this might be caused by a contract
mismatch, a premature session shutdown or an internal server error.'
I've used the online tool with the number and it returns data as expected
http://ec.europa.eu/taxation_customs/dds2/eos/eori_validation.jsp?Lang=en
Has anybody else had any luck with this?
Thanks
Thanks for the help, In case anyone else was struggling, below is the helper class for making and sending the request.
public class EoriModel
{
string _url;
public EoriModel()
{
_url = "http://ec.europa.eu/taxation_customs/dds2/eos/validation/services/validation";
}
public EoriResponseModel ValidateEoriNumber(string number)
{
if (number == null)
{
return null;
}
XmlDocument soapEnvelopeXml = CreateSoapEnvelope(number);
HttpWebRequest webRequest = CreateWebRequest(_url);
InsertSoapEnvelopeIntoWebRequest(soapEnvelopeXml, webRequest);
IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);
asyncResult.AsyncWaitHandle.WaitOne();
string response;
using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult))
{
using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))
{
response = rd.ReadToEnd();
}
}
int startPos = response.IndexOf("<return>");
int lastPos = response.LastIndexOf("</return>") - startPos + 9;
string responseFormatted = response.Substring(startPos, lastPos);
XmlSerializer serializer = new XmlSerializer(typeof(EoriResponseModel));
EoriResponseModel result;
using (TextReader reader = new StringReader(responseFormatted))
{
result = (EoriResponseModel)serializer.Deserialize(reader);
}
return result;
}
private static HttpWebRequest CreateWebRequest(string url)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
return webRequest;
}
private static XmlDocument CreateSoapEnvelope(string number)
{
XmlDocument soapEnvelopeDocument = new XmlDocument();
StringBuilder xmlBuilder = new StringBuilder();
xmlBuilder.AppendFormat("<soap:Envelope xmlns:soap={0} >", "'http://schemas.xmlsoap.org/soap/envelope/'");
xmlBuilder.Append("<soap:Body>");
xmlBuilder.AppendFormat("<ev:validateEORI xmlns:ev={0} >", "'http://eori.ws.eos.dds.s/'");
xmlBuilder.AppendFormat("<ev:eori>{0}</ev:eori>", number);
xmlBuilder.Append("</ev:validateEORI>");
xmlBuilder.Append("</soap:Body> ");
xmlBuilder.Append("</soap:Envelope> ");
soapEnvelopeDocument.LoadXml(xmlBuilder.ToString());
return soapEnvelopeDocument;
}
private static void InsertSoapEnvelopeIntoWebRequest(XmlDocument soapEnvelopeXml, HttpWebRequest webRequest)
{
using (Stream stream = webRequest.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
}
}
And the class with annotation used to parse the results
[XmlRoot(ElementName = "return")]
public class EoriResponseModel
{
[XmlElement(ElementName = "requestDate")]
public string RequestDate { get; set; }
[XmlElement(ElementName = "result")]
public List<Result> Result { get; set; }
}
[XmlRoot(ElementName = "result")]
public class Result
{
[XmlElement(ElementName = "eori")]
public string Eori { get; set; }
[XmlElement(ElementName = "status")]
public string Status { get; set; }
[XmlElement(ElementName = "statusDescr")]
public string StatusDescr { get; set; }
[XmlElement(ElementName = "name")]
public string Name { get; set; }
[XmlElement(ElementName = "street")]
public string Street { get; set; }
[XmlElement(ElementName = "postalCode")]
public string PostalCode { get; set; }
[XmlElement(ElementName = "city")]
public string City { get; set; }
[XmlElement(ElementName = "country")]
public string Country { get; set; }
}
If you Google the URI that is deep in the Reference.cs file that opens if you open the definition of the EORI validation methods, then you'll that someone on this page here https://www.codeproject.com/Questions/1075553/Soap-Message-Format-Issue-while-accessing-webservi is having the same issue.
On that page he quotes this sample code that he is using to make a query.
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ev:validateEORI xmlns:ev="http://eori.ws.eos.dds.s/">
<ev:eori>DE123456</ev:eori>
<ev:eori>IT123456789</ev:eori>
</ev:validateEORI>
</soap:Body>
</soap:Envelope>
Try this code in Postman, and enjoy the results. :D
His query is ultimately that the C# code he wrote isn't creating valid XML, but at least this XML will get you results from the API for your testing / development process to proceed.
I am working on a requirement where I need to create multiple issues in one go by Using the REST API. However, I start with uploading a single issue because I am new in API integration. I write few lines of code in c#. Here is my code:
static void Main(string[] args)
{
JavaScriptSerializer jss = new JavaScriptSerializer();
JiraCreateIssueRequest jcir = new JiraCreateIssueRequest();
//////////////////////////////////////////////////////////////////
string sUsername = "aaa#xyz.com";
string sPassword = "TestPassword";
string uri = #"https://domain.atlassian.net/rest/api/2/issue";
Uri address = new Uri(uri);
HttpWebRequest request;
//HttpWebResponse response = null;
StreamReader sr;
string sData = null;
string returnXML = string.Empty;
if (address == null) { throw new ArgumentNullException("address"); }
//jcir.project.ID = 100;
//jcir.Summary = "This issue is created by JIRA REST Api";
//jcir.Description = "This issue is created by JIRA REST Api";
//jcir.IssueType.ID = 1;
sData = #"{""fields"":{""project"":{""key"": ""SITT""},""summary"": ""REST API Uploading"",""description"":""Creating an issue via REST API"",""issuetype"": {""name"": ""Test""}}}";
//sData = jcir.ToString();
try
{
// Create and initialize the web request
request = WebRequest.Create(address) as HttpWebRequest;
request.Method = "POST";
request.ContentType = "application/json";
// Add the Authorization header to the web request
request.Credentials = new NetworkCredential(sUsername, sPassword);
//Write Data
if (sData != null)
{
byte[] byteData = UTF8Encoding.UTF8.GetBytes(sData);
// Set the content length in the request headers
request.ContentLength = byteData.Length;
// Write data
using (Stream postStream = request.GetRequestStream())
{
postStream.Write(byteData, 0, byteData.Length);
}
// Get response
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
// Get the response stream
StreamReader reader = new StreamReader(response.GetResponseStream());
string str = reader.ReadToEnd();
}
}
}
catch (WebException wex)
{
// This exception will be raised if the server didn't return 200 - OK
// Try to retrieve more information about the error
if (wex.Response != null)
{
using (HttpWebResponse errorResponse = (HttpWebResponse)wex.Response)
{
try
{
string sError = string.Format("The server returned '{0}' with the status code {1} ({2:d}).",
errorResponse.StatusDescription, errorResponse.StatusCode,
errorResponse.StatusCode);
sr = new StreamReader(errorResponse.GetResponseStream(), Encoding.UTF8);
returnXML = sr.ReadToEnd();
}
finally
{
if (errorResponse != null) errorResponse.Close();
}
}
}
else
{
throw new Exception(wex.Message);
}
}
}
public class JiraCreateIssueRequest
{
protected JavaScriptSerializer jss = new JavaScriptSerializer();
public JiraProject project = new JiraProject();
public string Summary { get; set; }
public string Description { get; set; }
public JiraIssueType IssueType = new JiraIssueType();
public override string ToString()
{
return jss.Serialize(this);
}
}
public class JiraCreateIssueResponse
{
}
public class JiraProject
{
public int ID { get; set; }
//public string Key { get; set; }
}
public class JiraIssueType
{
public int ID { get; set; }
//public string Name { get; set; }
}
But when I am running the above code, I am getting the '400' error. I googled it and found that this usually this error comes when the URL or the Username/Password are incorrect. I cross checked both the things however its correct.
May I know why this error is coming or what will be the resolution of the problem?
Your password is not your login password, it's an API token that you get from here:
https://id.atlassian.com/manage/api-tokens
Generate a token, then use that as your password.
I am calling an API through a HttpClient and getting a response like follows.
{
"result_set": []
}
I parsed the response in to a dynamic object.
dynamic dbResponseBody = await dbResponse.Content.ReadAsAsync<object>();
How to check the result_set is empty or not. Currently I am doing as follows but looking for a better way.
if (dbResponseBody.Result.result_set != "[]") {}
You can construct a model for your response if you know the type.
class Response
{
[JsonProperty("result_set")]
public List<string> ResultSet { get; set; }
}
If your items in your array model are more complex you can construct the following
class Response
{
[JsonProperty("result_set")]
public List<Items> ResultSet { get; set; }
}
class Items{
[JsonProperty("P1")]
public string P1 { get; set; }
[JsonProperty("P2")]
public int P2 { get; set; }
}
Then you can read your response as follows:
using (HttpWebResponse response = await request.GetResponseAsync() as HttpWebResponse)
{
if (response != null && response.StatusCode != HttpStatusCode.OK)
throw new Exception(String.Format(
"Server error (HTTP {0}: {1}).",
response.StatusCode,
response.StatusDescription));
if (response != null)
{
Stream responseStream = response.GetResponseStream();
Respose myResponse = GetResponseModel<Response>(responseStream);
}
else throw new Exception("My message");
Using Newtonsoft you can get the model back again
protected T GetResponseModel<T>(Stream respStream) where T : class
{
if (respStream != null)
{
var respStreamReader = new StreamReader(respStream);
Task<string> rspObj = respStreamReader.ReadToEndAsync();
rspObj.Wait();
Debug.WriteLine("Response: {0}", rspObj.Result);
T jsonResponse = JsonConvert.DeserializeObject<T>(rspObj.Result);
return jsonResponse;
}
return default(T);
}
At the end after this line you can check the properties of your model
Respose myResponse = GetResponseModel<Response>(responseStream);
if(myResponse.Result.Count == 0){.....}
I got the following problem:
I am trying to implement Instagram into my website. However I am stuck on the step where I need to get the Acces token. The api's documentation says I need to request it like this :
curl \-F 'client_id=CLIENT-ID' \
-F 'client_secret=CLIENT-SECRET' \
-F 'grant_type=authorization_code' \
-F 'redirect_uri=YOUR-REDIRECT-URI' \
-F 'code=CODE' \https://api.instagram.com/oauth/access_token
I use ASP.NET so I found this equivalent OAuth 2.0 In .NET With Instagram API:
NameValueCollection parameters = new NameValueCollection();
parameters.Add("client_id", "ssdfsdfsdfsdfsdf");
parameters.Add("client_secret", "sdsdfdsfsdfsdfsdfsdfsdf");
parameters.Add("grant_type", "authorization_code");
parameters.Add("redirect_uri", "http://localhost:2422/LoginsGuests/GetLoginPage");
parameters.Add("code", code);
WebClient client = new WebClient();
var result = client.UploadValues("https://api.instagram.com/oauth/access_token", parameters);
var response = System.Text.Encoding.Default.GetString(result);
However I keep getting:
System.Net.WebException: The remote server returned an error: (400) Bad Request.
What I am i doing wrong?
Almost there the instagram api expects a POST not a GET.
Add the "POST" parameter.
var result = client.UploadValues("https://api.instagram.com/oauth/access_token", "POST", parameters);
Also check the instagram settings -> redirect url.
Then this may help don't forget to add a reference to Newtonsoft.Json. Is in .Net version 4.5.1:
using System;
using System.Collections.Specialized;
using System.Net;
using System.Text;
namespace Instagram
{
public class InstagramClient
{
public InstagramClient(string code)
{
GetToken(code);
}
private void GetToken(string code)
{
using (var wb = new WebClient())
{
var parameters = new NameValueCollection
{
{"client_id", "ClientId"},
{"client_secret", "ClientSecret"},
{"grant_type", "authorization_code"},
{"redirect_uri", "RedirectUri"},
{"code", code}
};
var response = wb.UploadValues("https://api.instagram.com/oauth/access_token", "POST", parameters);
string json = Encoding.ASCII.GetString(response);
try
{
var OauthResponse = (InstagramOAuthResponse) Newtonsoft.Json.JsonConvert.DeserializeObject(json, typeof(InstagramOAuthResponse));
}
catch (Exception ex)
{
//handle ex if needed.
}
}
}
public class InstagramOAuthResponse
{
public string access_token { get; set; }
public User user { get; set; }
}
public class User : System.Security.Principal.IIdentity
{
public string username { get; set; }
public string website { get; set; }
public string profile_picture { get; set; }
public string full_name { get; set; }
public string bio { get; set; }
public string id { get; set; }
public string OAuthToken { get; set; }
public string AuthenticationType
{
get { return "Instagram"; }
}
public bool IsAuthenticated
{
get { return !string.IsNullOrEmpty(id); }
}
public string Name
{
get
{
return String.IsNullOrEmpty(full_name) ? "unknown" : full_name;
}
}
}
}
}
If you prefer HttpWebRequest class:
var request = (HttpWebRequest)WebRequest.Create("https://api.instagram.com/oauth/access_token/");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
var requestDetails = "client_id=" + AppConfig.InstagramClientId;
requestDetails += "&client_secret=" + AppConfig.InstagramClientSecret;
requestDetails += "&grant_type=authorization_code";
requestDetails += "&redirect_uri=" + redirectUrl;
requestDetails += "&code=" + exchangeCode;
byte[] bytes = Encoding.ASCII.GetBytes(requestDetails);
request.ContentLength = bytes.Length;
using (Stream outputStream = request.GetRequestStream())
{
outputStream.Write(bytes, 0, bytes.Length);
}
var response = request.GetResponse();
var code = ((HttpWebResponse)response).StatusCode;
if (code == HttpStatusCode.OK)
{
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
var jsonString = streamReader.ReadToEnd();
var accessToken = ParseAccessToken(jsonString);
return accessToken;
}
}
I asked this question before but I'm going to complete the question with a solution proposed and make another question.
I'm using this class to make an async WebRequest:
class HttpSocket
{
public static void MakeRequest(Uri uri, Action<RequestCallbackState> responseCallback)
{
WebRequest request = WebRequest.Create(uri);
request.Proxy = null;
Task<WebResponse> asyncTask = Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null);
ThreadPool.RegisterWaitForSingleObject((asyncTask as IAsyncResult).AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), request, 1000, true);
asyncTask.ContinueWith(task =>
{
WebResponse response = task.Result;
Stream responseStream = response.GetResponseStream();
responseCallback(new RequestCallbackState(response.GetResponseStream()));
responseStream.Close();
response.Close();
});
}
private static void TimeoutCallback(object state, bool timedOut)
{
Console.WriteLine("Timeout: " + timedOut);
if (timedOut)
{
Console.WriteLine("Timeout");
WebRequest request = (WebRequest)state;
if (state != null)
{
request.Abort();
}
}
}
}
And i'm testing the class with this code:
class Program
{
static void Main(string[] args)
{
// Making a request to a nonexistent domain.
HttpSocket.MakeRequest(new Uri("http://www.google.comhklhlñ"), callbackState =>
{
if (callbackState.Exception != null)
throw callbackState.Exception;
Console.WriteLine(GetResponseText(callbackState.ResponseStream));
});
Thread.Sleep(100000);
}
public static string GetResponseText(Stream responseStream)
{
using (var reader = new StreamReader(responseStream))
{
return reader.ReadToEnd();
}
}
}
Once executed, the callback is reached immediately, showing "Timeout: false" and there aren't more throws, so the timeout isn't working.
This is a solution proposed in the original thread but, as you could see, the code works for him.
What I'm doing wrong?
EDIT: Other classes used by the code:
class RequestCallbackState
{
public Stream ResponseStream { get; private set; }
public Exception Exception { get; private set; }
public RequestCallbackState(Stream responseStream)
{
ResponseStream = responseStream;
}
public RequestCallbackState(Exception exception)
{
Exception = exception;
}
}
class RequestState
{
public byte[] RequestBytes { get; set; }
public WebRequest Request { get; set; }
public Action<RequestCallbackState> ResponseCallback { get; set; }
}
This approach works. I would recommend switching this to explicitly handle exceptions (including your timeout, but also bad domain names, etc) slightly differently. In this case, I've split this into a separate continuation.
In addition, in order to make this very explicit, I've shorted the timeout time, put a "real" but slow domain in, as well as added an explicit timeout state you can see:
using System;
using System.IO;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
class HttpSocket
{
private const int TimeoutLength = 100;
public static void MakeRequest(Uri uri, Action<RequestCallbackState> responseCallback)
{
WebRequest request = WebRequest.Create(uri);
request.Proxy = null;
Task<WebResponse> asyncTask = Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null);
ThreadPool.RegisterWaitForSingleObject((asyncTask as IAsyncResult).AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), request, TimeoutLength, true);
asyncTask.ContinueWith(task =>
{
WebResponse response = task.Result;
Stream responseStream = response.GetResponseStream();
responseCallback(new RequestCallbackState(response.GetResponseStream()));
responseStream.Close();
response.Close();
}, TaskContinuationOptions.NotOnFaulted);
// Handle errors
asyncTask.ContinueWith(task =>
{
var exception = task.Exception;
var webException = exception.InnerException;
// Track whether you cancelled or not... up to you...
responseCallback(new RequestCallbackState(exception.InnerException, webException.Message.Contains("The request was canceled.")));
}, TaskContinuationOptions.OnlyOnFaulted);
}
private static void TimeoutCallback(object state, bool timedOut)
{
Console.WriteLine("Timeout: " + timedOut);
if (timedOut)
{
Console.WriteLine("Timeout");
WebRequest request = (WebRequest)state;
if (state != null)
{
request.Abort();
}
}
}
}
class RequestCallbackState
{
public Stream ResponseStream { get; private set; }
public Exception Exception { get; private set; }
public bool RequestTimedOut { get; private set; }
public RequestCallbackState(Stream responseStream)
{
ResponseStream = responseStream;
}
public RequestCallbackState(Exception exception, bool timedOut = false)
{
Exception = exception;
RequestTimedOut = timedOut;
}
}
class RequestState
{
public byte[] RequestBytes { get; set; }
public WebRequest Request { get; set; }
public Action<RequestCallbackState> ResponseCallback { get; set; }
}
class Program
{
static void Main(string[] args)
{
// Making a request to a nonexistent domain.
HttpSocket.MakeRequest(new Uri("http://www.tanzaniatouristboard.com/"), callbackState =>
{
if (callbackState.RequestTimedOut)
{
Console.WriteLine("Timed out!");
}
else if (callbackState.Exception != null)
throw callbackState.Exception;
else
Console.WriteLine(GetResponseText(callbackState.ResponseStream));
});
Thread.Sleep(100000);
}
public static string GetResponseText(Stream responseStream)
{
using (var reader = new StreamReader(responseStream))
{
return reader.ReadToEnd();
}
}
}
This will run, and show a timeout appropriately.
Use 2 different classes:
class RequestCallbackException : Exception
{
public RequestCallbackException(Stream responseStream, Exception exception) : base(exception)
{
}
}
and
class RequestCallbackStream
{
public Stream ResponseStream { get; private set; }
public RequestCallbackState(Stream responseStream)
{
ResponseStream = responseStream;
}
}
You will notice that sometimes GetResponseStream() returns null, which immediately raise an exception in
asyncTask.ContinueWith() -->
GetResponseText(callbackState.ResponseStream)-->
using (var reader = new StreamReader(responseStream)) // responseStream is null
{
}