where am i going wrong with deserializing - c#

I am trying to get the total number of questions on stackoverflow for an exercise I am doing and am stuck at the deserialization.
I would be grateful if someone could please let me know what I need to do an maybe provide some example code that would help me.
when I run this up in the console I get the error
"There was an error deserializing the object of type. Encountered unexpected character" which is a downward pointing triangle...
this is what I have so far
using System;
using System.Threading.Tasks;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
namespace cs_StackOverflowAPI
{
[DataContract(Namespace = "http://schemas.microsoft.com/search/local/ws/rest/v1")]
public class Question
{
[DataMember(Name = "question_id")]
public int Questions { get; set; }
}
[DataContract]
public class ResourceSet
{
[DataMember(Name = "estimatedTotal")]
public long EstimatedTotal { get; set; }
[DataMember(Name = "resources")]
public Question[] Resources { get; set; }
}
[DataContract]
public class Response
{
[DataMember(Name = "statusCode")]
public int StatusCode { get; set; }
[DataMember(Name = "statusDescription")]
public string StatusDescription { get; set; }
[DataMember(Name = "authenticationResultCode")]
public string AuthenticationResultCode { get; set; }
[DataMember(Name = "errorDetails")]
public string[] errorDetails { get; set; }
[DataMember(Name = "traceId")]
public string TraceId { get; set; }
[DataMember(Name = "resourceSets")]
public ResourceSet[] ResourceSets { get; set; }
}
class Program
{
public string serverUrl = "https://api.stackexchange.com/";
public HttpClient client = null;
static void Main(string[] args)
{
try
{
string noOfQuestions = CreateRequest("questions");
Response noOfQuestionsReponse = MakeRequest(noOfQuestions);
ProcessResponse(noOfQuestionsReponse);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.Read();
}
}
public static string CreateRequest(string queryString)
{
string UrlRequest = "https://api.stackexchange.com/2.2/" +
queryString +
"?&site=stackoverflow";
return (UrlRequest);
}
public static Response MakeRequest(string requestUrl)
{
try
{
HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
if (response.StatusCode != HttpStatusCode.OK)
throw new Exception(String.Format(
"Server error (HTTP {0}: {1}).",
response.StatusCode,
response.StatusDescription));
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(Response));
object objResponse = jsonSerializer.ReadObject(response.GetResponseStream());
Response jsonResponse
= objResponse as Response;
return jsonResponse;
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return null;
}
}
static public void ProcessResponse(Response noOfQuestionsReponse)
{
// this is where the error occurs
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
public static long ToUnixTime(DateTime date)
{
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return Convert.ToInt64((date.ToUniversalTime() - epoch).TotalSeconds);
}
}
}

It is returning compressed content (gzip, specifically). If possible, tell your http client to automatically decompress it:
request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
request.AutomaticDecompression =
DecompressionMethods.GZip | DecompressionMethods.Deflate;
The next issue is: the schema doesn't match; the questions are in the items of the root:
[DataContract]
public class Response
{
[DataMember(Name ="items")]
List<Question> questions { get;set; }
}

Related

Deserialize JSON property starting with #

Im writing a c# console app, where i need get som JSON date from a webapi.
For the most part this works fine, however in one of my JSON responses i get a property name staring with #. I cant seem to figure out how to put that JSON property into a C# object.
My code look as follows:
public class AlertResponse
{
public string #class { get; set; }
public string result { get; set; }
public string info { get; set; }
}
public class AuthenticationResponse
{
public string Access_token { get; set; }
}
class Test
{
private static HttpClient client = new HttpClient();
private static string BaseURL = "https://xxxxx.xxxx";
public void Run()
{
client.BaseAddress = new Uri(BaseURL);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
AuthenticationResponse authenticationResponse = Login();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authenticationResponse.Access_token);
AlertResponse OpenAlerts = GetOpenAlerts();
}
internal AlertResponse GetOpenAlerts()
{
var response = client.GetAsync("/api/v2/xxxxxxxxxxxxxxxxxx/alerts/open").Result;
if (response.IsSuccessStatusCode)
{
return response.Content.ReadAsAsync<AlertResponse>().Result;
}
else
{
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
}
return null;
}
private AuthenticationResponse Login()
{
string apiKey = "gdfashsfgjhsgfj";
string apiSecretKey = "sfhsfdjhssdjhsfhsfh";
var byteArray = new UTF8Encoding().GetBytes("public-client:public");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
var form = new FormUrlEncodedContent(new Dictionary<string, string> { { "username", apiKey }, { "password", apiSecretKey }, { "grant_type", "password" } });
HttpResponseMessage tokenMessage = client.PostAsync("/auth/oauth/token", form).Result;
if (tokenMessage.IsSuccessStatusCode)
{
return tokenMessage.Content.ReadAsAsync<AuthenticationResponse>().Result;
}
else
{
Console.WriteLine("{0} ({1})", (int)tokenMessage.StatusCode, tokenMessage.ReasonPhrase);
}
return null;
}
}
And the JSON i get looks like this:
"AlertResponse": {
"#class": "patch_ctx",
"patchUid": "afdhgfhjdajafjajadfjadfjdj",
"policyUid": "dsgafdhasfjafhdafhadfh",
"result": "0x80240022",
"info": "fdgdfhsfgjh"
}
How can i fix this?
Best regards
Glacier
Are you using Newtonsoft.Json or System.Text.Json?
In either cases you should decorate the #class Property with
//System.Text.Json
[JsonPropertyName("#class")]
public string class { get; set; }
or
//Newtonsoft.Json
[JsonProperty("#class")]
public string class { get; set; }
I guess you are looking for DataMemberAttribute and DataContract
using System.Runtime.Serialization;
[DataContract]
public class AlertResponse
{
[DataMember(Name = "#class")]
public string Class { get; set; }
[DataMember(Name = "result")]
public string Result { get; set; }
[DataMember(Name = "info")]
public string Info { get; set; }
}

How to make api request to Github repository using restapi?

I am new to C# and .Net and I am struggling to understand this issue that I have. I feel like what I have is enough but not sure myself. SO if someone can just review the codes that I have below and tell me were to correct and what is wrong.Thank you
This is my Model Class
namespace github_project.Models
{
public class GithubItem
{
public int Id { get; set; }
public string UserName { get; set; }
public string FullName { get; set; }
public string City { get; set; }
public string ProjectName { get; set; }
public string Commits { get; set; }
public double Rating { get; set; }
public string AvatarUrl { get; set; }
}
}
and this is my database context
namespace github_project.Database
{
public class GithubContext : DbContext
{
public DbSet<GithubItem> Github { get; set; }
public GithubContext(DbContextOptions<GithubContext> options) : base(options)
{
}
public GithubItem ItemsList()
{
List<GithubItem> build = Build();
GithubItem itemsList = JsonConvert.DeserializeObject<GithubItem>(build);
return itemsList;
}
public List<GithubItem> Build()
{
var getData = GetGithubData();
return System.Text.Json.JsonSerializer.Deserialize<List<GithubItem>>(getData);
}
private string GetGithubData()
{
string username = "**test**";
var url = "https://api.github.com/users/" + username + "/repos?page=1";
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Method = "GET";
request.ContentType = "application/json";
request.UserAgent = "TestApp";
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
StreamReader reader = new StreamReader(response.GetResponseStream());
return reader.ReadToEnd();
}
}
public List<GithubItem> getGithub() => Github.Local.ToList<GithubItem>();
}
}
finally this is my controller
[HttpGet("/github")]
public GithubItem GetAll()
{
return _context.ItemsList();
}
I am making a request to github in order to get all the data and use it in my request. I am getting an here here of converting Collection.List to String on this method below:
public GithubItem ItemsList()
{
List<GithubItem> build = Build();
GithubItem itemsList = JsonConvert.DeserializeObject<GithubItem>(**build**);
return itemsList;
}
Can someone help me and and someone tell me what is wrong here??? Thank you
You cannot deserialize an object or convert an object from List<GithubItem> to single GithubItem. That is what you are doing.
As you can see, you have build:
List<GithubItem> build = Build();
This build variable is a List<GithubItem. Now you want to convert it to single using Deserialize of JsonConvert?
You can just get one record, whatever your requirements is using this code:
GithubItem itemsList = build.FirstOrDefault();
That would build fine. But this is just an example since I am not sure what is your requirement. If you need to filter your record, you can also pass a argument on FirstOrDefault:
GithubItem itemsList = build.FirstOrDefault(x => x.UserName == "John");
That would also work fine.

Microsoft Azure Text Translator - Subscription Key Not Working

I am trying to build a basic text translator in console using Microsoft Azure's Text Translator. However, my subscription keys are simply not working. I have generated them multiple times, as well as inputted them manually. Please assist. I have left in the keys for further clarification. Thank you for reading, and for your help.
The code generates this error:
if (null == subscriptionKey)
{
throw new Exception("Please set/export the environment variable: " + key_var);
// This sample requires C# 7.1 or later for async/await.
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
// Install Newtonsoft.Json with NuGet
using Newtonsoft.Json;
namespace TranslateTextSample
{
/// <summary>
/// The C# classes that represents the JSON returned by the Translator Text API.
/// </summary>
public class TranslationResult
{
public DetectedLanguage DetectedLanguage { get; set; }
public TextResult SourceText { get; set; }
public Translation[] Translations { get; set; }
}
public class DetectedLanguage
{
public string Language { get; set; }
public float Score { get; set; }
}
public class TextResult
{
public string Text { get; set; }
public string Script { get; set; }
}
public class Translation
{
public string Text { get; set; }
public TextResult Transliteration { get; set; }
public string To { get; set; }
public Alignment Alignment { get; set; }
public SentenceLength SentLen { get; set; }
}
public class Alignment
{
public string Proj { get; set; }
}
public class SentenceLength
{
public int[] SrcSentLen { get; set; }
public int[] TransSentLen { get; set; }
}
class Program
{
private const string key_var="b1f43a68dce24b0280360691ad68bc75";
private static readonly string subscriptionKey = Environment.GetEnvironmentVariable(key_var);
private const string endpoint_var = "https://consoletexttranslator.cognitiveservices.azure.com/sts/v1.0/issuetoken";
private static readonly string endpoint = Environment.GetEnvironmentVariable(endpoint_var);
static Program()
{
if (null == subscriptionKey)
{
throw new Exception("Please set/export the environment variable: " + key_var);
}
if (null == endpoint)
{
throw new Exception("Please set/export the environment variable: " + endpoint_var);
}
}
// Async call to the Translator Text API
static public async Task TranslateTextRequest(string subscriptionKey, string endpoint, string route, string inputText)
{
object[] body = new object[] { new { Text = inputText } };
var requestBody = JsonConvert.SerializeObject(body);
using (var client = new HttpClient())
using (var request = new HttpRequestMessage())
{
// Build the request.
request.Method = HttpMethod.Post;
request.RequestUri = new Uri(endpoint + route);
request.Content = new StringContent(requestBody, Encoding.UTF8, "application/json");
request.Headers.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
// Send the request and get response.
HttpResponseMessage response = await client.SendAsync(request).ConfigureAwait(false);
// Read response as a string.
string result = await response.Content.ReadAsStringAsync();
TranslationResult[] deserializedOutput = JsonConvert.DeserializeObject<TranslationResult[]>(result);
// Iterate over the deserialized results.
foreach (TranslationResult o in deserializedOutput)
{
// Print the detected input languge and confidence score.
Console.WriteLine("Detected input language: {0}\nConfidence score: {1}\n", o.DetectedLanguage.Language, o.DetectedLanguage.Score);
// Iterate over the results and print each translation.
foreach (Translation t in o.Translations)
{
Console.WriteLine("Translated to {0}: {1}", t.To, t.Text);
}
}
}
}
static async Task Main(string[] args)
{
// This is our main function.
// Output languages are defined in the route.
// For a complete list of options, see API reference.
// https://learn.microsoft.com/azure/cognitive-services/translator/reference/v3-0-translate
string route = "/translate?api-version=3.0&to=de&to=it&to=ja&to=th";
// Prompts you for text to translate. If you'd prefer, you can
// provide a string as textToTranslate.
Console.Write("Type the phrase you'd like to translate? ");
string textToTranslate = "Hello, Tommy.";
await TranslateTextRequest(subscriptionKey, endpoint, route, textToTranslate);
Console.WriteLine("Press any key to continue.");
Console.ReadKey();
}
}
}
pls try the code below , it works for me :
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
// Install Newtonsoft.Json with NuGet
using Newtonsoft.Json;
namespace TranslateTextSample
{
/// <summary>
/// The C# classes that represents the JSON returned by the Translator Text API.
/// </summary>
public class TranslationResult
{
public DetectedLanguage DetectedLanguage { get; set; }
public TextResult SourceText { get; set; }
public Translation[] Translations { get; set; }
}
public class DetectedLanguage
{
public string Language { get; set; }
public float Score { get; set; }
}
public class TextResult
{
public string Text { get; set; }
public string Script { get; set; }
}
public class Translation
{
public string Text { get; set; }
public TextResult Transliteration { get; set; }
public string To { get; set; }
public Alignment Alignment { get; set; }
public SentenceLength SentLen { get; set; }
}
public class Alignment
{
public string Proj { get; set; }
}
public class SentenceLength
{
public int[] SrcSentLen { get; set; }
public int[] TransSentLen { get; set; }
}
class Program
{
private const string subscriptionKey = "<your translator API key>";
private const string endpoint = "https://api.cognitive.microsofttranslator.com";
static Program()
{
if (null == subscriptionKey)
{
throw new Exception("Please set/export the environment variable: " + subscriptionKey);
}
if (null == endpoint)
{
throw new Exception("Please set/export the environment variable: " + endpoint);
}
}
// Async call to the Translator Text API
static public async Task TranslateTextRequest(string subscriptionKey, string endpoint, string route, string inputText)
{
object[] body = new object[] { new { Text = inputText } };
var requestBody = JsonConvert.SerializeObject(body);
using (var client = new HttpClient())
using (var request = new HttpRequestMessage())
{
// Build the request.
request.Method = HttpMethod.Post;
request.RequestUri = new Uri(endpoint + route);
request.Content = new StringContent(requestBody, Encoding.UTF8, "application/json");
request.Headers.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
// Send the request and get response.
HttpResponseMessage response = await client.SendAsync(request).ConfigureAwait(false);
// Read response as a string.
string result = await response.Content.ReadAsStringAsync();
TranslationResult[] deserializedOutput = JsonConvert.DeserializeObject<TranslationResult[]>(result);
// Iterate over the deserialized results.
foreach (TranslationResult o in deserializedOutput)
{
// Print the detected input languge and confidence score.
Console.WriteLine("Detected input language: {0}\nConfidence score: {1}\n", o.DetectedLanguage.Language, o.DetectedLanguage.Score);
// Iterate over the results and print each translation.
foreach (Translation t in o.Translations)
{
Console.WriteLine("Translated to {0}: {1}", t.To, t.Text);
}
}
}
}
static void Main(string[] args)
{
MainAsync(args).GetAwaiter().GetResult();
Console.ReadKey();
Console.WriteLine("press anykey to exit");
}
static async Task MainAsync(string[] args)
{
string route = "/translate?api-version=3.0&to=de&to=it&to=ja&to=th";
// Prompts you for text to translate. If you'd prefer, you can
// provide a string as textToTranslate.
string textToTranslate = "Hello, Tommy.";
await TranslateTextRequest(subscriptionKey, endpoint, route, textToTranslate);
}
}
}
before you run this console app, pls replace the value of "subscriptionKey" with your own key value here :
Result :
If there is anything unclear , pls feel free to let me know : )

HTTP response is never returned

I am building an app in Xamarin.Android ! which determines my Address using google Maps API when given a latitude and longitude. However my App fails to deliver an HTTP response. I don't receive any runtime errors and VS debugger behaves as if my App has hanged.
1> I don't know whether this is an issue of Xamarin.Android
2> As i read somehwere it could be an issue of blocking,asynchronous codes but then I use the same piece of code for my Windows App and it never gave me trouble
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading.Tasks;
namespace App_Code
{
public class myLocationProxy
{
public static async Task<RootObject_AutoLocationAddress> getmyLocation(string lat, string lng)
{
var http = new HttpClient();
/*CODE STOPS HERE*/var response = await http.GetAsync(String.Format("http://maps.google.com/maps/api/geocode/json?latlng={0},{1}&sensor=false", Uri.EscapeDataString(lat), Uri.EscapeDataString(lng)));
var result = await response.Content.ReadAsStringAsync();
var serializer = new DataContractJsonSerializer(typeof(RootObject_AutoLocationAddress));
var ms = new MemoryStream(Encoding.UTF8.GetBytes(result));
var data = (RootObject_AutoLocationAddress)serializer.ReadObject(ms);
return data;
}
}
[DataContract]
public class AddressComponent_AutoLocationAddress
{
[DataMember]
public string long_name { get; set; }
[DataMember]
public List<string> types { get; set; }
}
[DataContract]
public class Result_AutoLocationAddress
{
[DataMember]
public List<AddressComponent_AutoLocationAddress> address_components { get; set; }
[DataMember]
public string formatted_address { get; set; }
}
[DataContract]
public class RootObject_AutoLocationAddress
{
[DataMember]
public List<Result_AutoLocationAddress> results { get; set; }
[DataMember]
public string status { get; set; }
}
}
Try below code snippet just added TimeOut value.
public static async Task<RootObject_AutoLocationAddress> getmyLocation(string lat, string lng)
{
var client = new HttpClient()
{
Timeout = TimeSpan.FromMilliseconds(10000) //10 second, This line might help you
};
var response = await client.GetAsync(String.Format("http://maps.google.com/maps/api/geocode/json?latlng={0},{1}&sensor=false", Uri.EscapeDataString(lat), Uri.EscapeDataString(lng)));
var result = await response.Content.ReadAsStringAsync();
var serializer = new DataContractJsonSerializer(typeof(RootObject_AutoLocationAddress));
var ms = new MemoryStream(Encoding.UTF8.GetBytes(result));
var data = (RootObject_AutoLocationAddress)serializer.ReadObject(ms);
return data;
}
Cheers!!

Problems with implementation of the factory pattern

I work with web service, and I'm get response from service. Response will be have different structure. For example, API getInfo return response:
{"code":0,"message":"","result":{"nickname":"UserName","age":"22"}}
API signin:
{"code":0,"message":"","result":"user_token"}
etc.
I use HttpWebRequest for POST request. Request and response deserialize/serialize with DataContractSerializer.
So, I want to use factory pattern, this is my implementation:
[DataContract]
public class ResultGetInfo
{
[DataMember(Name = "nickname")]
public int Nickname { get; set; }
[DataMember(Name = "age")]
public int Age { get; set; }
}
[DataContract]
public abstract class Response
{
}
[DataContract]
public class ResponseSignin : Response
{
[DataMember(Name = "code")]
public int Code { get; set; }
[DataMember(Name = "message")]
public string Message { get; set; }
[DataMember(Name = "result")]
public string Result { get; set; }
}
[DataContract]
public class ResponseGetInfo : Response
{
[DataMember(Name = "code")]
public int Code { get; set; }
[DataMember(Name = "message")]
public string Message { get; set; }
[DataMember(Name = "result")]
public ResultGetInfo Result { get; set; }
}
public abstract class CreateResponse
{
public abstract Response CreateResponseObj();
}
public class CreateResponseSignin : CreateResponse
{
public override Response CreateResponseObj()
{
return new ResponseSignin();
}
}
public class CreateResponseGetInfo : CreateResponse
{
public override Response CreateResponseObj()
{
return new ResponseGetInfo();
}
}
I get response in callback function:
private void getResponseCallback(IAsyncResult asynchronousResult)
{
var request = (Request)asynchronousResult.AsyncState;
try
{
HttpWebResponse response;
// End the get response operation
response = (HttpWebResponse)request.HttpRequest.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamReader = new StreamReader(streamResponse);
var gyResponse = streamReader.ReadToEnd();
streamResponse.Close();
streamReader.Close();
response.Close();
Response response_obj = request.Creater.CreateResponseObj();
using (MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(gyResponse)))
{
var serializer = new DataContractJsonSerializer(response_obj.GetType());
response_obj = (Response)serializer.ReadObject(stream);
if (request.CallBack != null)
{
request.CallBack.Invoke(response_obj, null);
}
}
}
catch (WebException e)
{
if (request.CallBack != null)
{
request.CallBack.Invoke(null, e);
}
}
}
For DataContractJsonSerializer I declare the type here:
var serializer = new DataContractJsonSerializer(response_obj.GetType());
Where response_obj is object, which has needed type (ResponseSignin or ResponseGetInfo).
So, I call Invoke() in my delegate.
private void ResponseHandler(Response result, Exception error)
{
if (error != null)
{
string err = error.Message;
}
else
{
Response response = result;
}
}
And here I have a problem. Variable result really contains correct answer, but I don't get properties, because abstract class Response is without properties. And I can't declare properties or override in derived classes. I'm not sure that chose the desired pattern.
Have you tried just casting the result variable to the type you need?
E.g.
private void ResponseHandler(Response result, Exception error)
{
if (error != null)
{
string err = error.Message;
return;
}
var signInResponse = result as ResponseSignin;
if (signInResponse != null)
{
HandleSignInResponse(signInResponse);
}
var infoResponse = result as ResponseGetInfo;
if (infoResponse != null)
{
HandleInfoResponse(infoResponse);
}
}

Categories