How to receive a real object in GraphQL dotnet client app? - c#

I run a GraphQL client and send the queries
var response3 = await client2.SendQueryAsync<ADescriptorResponse2>(request2);
var response2 = await client2.SendQueryAsync<dynamic>(request2);
var response1 = await client2.SendQueryAsync<object>(request2);
There is
public class ADescriptorResponse2
{
public ADescriptor aDescriptor { get; set; }
}
public class ADescriptor
{
public long Action { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
But in the 1st case
var response3 = await client2.SendQueryAsync(request2);
i receive the response3.Data ==null, type ADescriptorResponse2
In other both cases I receive Data correct but it isNewtonsoft.Json.Linq.JObject type.
Why I do not receive the Data of ADescriptorResponse2 filled with data?
What is incorrect?

This most probably means that the structure of the data is such that it cannot correctly deserialize to type of ADescriptorResponse2.
You can check the structure of the data which you get from response2 and response1 and see if it is in the shape of ADescriptorResponse2.
It could be some nested object issue where you need another object on top of ADescriptorResponse2 or something of that nature.

Related

JsonConvert.DeserializeObject returns nulls

I have the following code which I am using in an ASP.NET MVC c# application
HttpClient client = new HttpClient();
try
{
var result = client.GetStringAsync(url).Result;
APIReturn = JsonConvert.DeserializeObject<APIReturn>(result);
}
catch
{
}
When I place my breakpoint on the APIReturn = .... line, and I view the contents of result, I see what looks like a valid return from the API call. I even copied the contents of the variable result and applied it to an online json tool. This is what the tool shows:
This is the definition of the APIReturn class:
public class APIReturn
{
public string return_response { get; set; }
public string return_code { get; set; }
public string return_plan_name { get; set; }
public string return_menu_string { get; set; }
public string return_peo_ind { get; set; }
}
At the end of the execution of the code, I look at the values of APIReturn and each field is null.
Any ideas why Json is not parsing the string?
Thank you.
Your json is an array of objects... but you are deserializing it to an object. Change the deserialization to List and should work
var list = JsonConvert.DeserializeObject<List<APIReturn>>(result);

How do I convert an object passed from an api back to that item's class?

In my api I have a class with a few fields including one of type object. I insert an object of another class into that field. Then I return the entire class back to the program calling the api. In that program, I can convert the entire result to the class it was originally, but I can't convert the object field back to it's original class. What am I missing?
API
public class APIResponse
{
public int statusCode { get; set; }
public string errorMessage { get; set; }
public object returnObject { get; set; }
}
[HttpPost("CompleteCustomFilterOrder")]
[Produces("application/json", Type = typeof(APIResponse))]
public APIResponse GetItem
{
ItemDTO item = new ItemDTO();
item.ID = 12345
item.Name = "Widget";
item.Status = "Active";
APIResponse response = new APIResponse();
response.statusCode = 98765;
response.errorMessage = "Success!";
response.returnObject = item;
return response;
}
Program calling API
var client = new RestClient(url + "GetItem");
var request = new RestRequest(Method.GET);
var apiResponse = client.Execute<APIResponse>(request);
APIResponse response = apiResponse.Data;
ItemDTO item = (ItemDTO)response.returnObject;
Response correctly gets converted back to a class, but item throws the error
Unable to cast object of type 'System.Collections.Generic.Dictionary`2[System.String,System.Object]' to type 'ProjectName.BusinessLogicLayer.Classes.ItemDTO'.
The ItemDTO class is identical in both programs except for the namespace.
You are reciving JSON object as a response so direct cast won't work. You need to deserialize this object using eg. JsonConvert from Newtonsoft.Json.
Btw. did you consider making APIResponse a generic class ?
public class APIResponse<T> where T: class
{
public int statusCode { get; set; }
public string errorMessage { get; set; }
public T returnObject { get; set; }
}

Unable to use JSON data with Newtonsoft.Json in WPF

I am retrieving data from office365 api. The response is in JSON format. I want to get data like Id, DisplayName etc. into variables but not getting the right way to do it. Following this link. I'm new to API and JSON. Will Appreciate pointers as well towards best learning links.Sample JSON below for listing sub folders of Inbox folder.
Response JSON data.
{"#odata.context":"https://outlook.office365.com/api/v1.0/$metadata#Me/Folders('Inbox')/ChildFolders","value":
[
{"#odata.id":"https://outlook.office365.com/api/v1.0/Users('sample.user#demosite.com')/Folders('AAMkADBjMGZiZGFlLTE4ZmEtNGRlOS1iMjllLTJmsdfsdfdDSFSDFDFDF=')",
"Id":"AAMkADBjMdfgdfgDFGDFGDFGdfGDFGDFGDFGGDzrACAAB4xqMmAAA=",
"DisplayName":"SampleFolder","ParentFolderId":"AAMkADBjMGZiZGFlLTE4ZmEtNGRlOS1sdsDFSDFSDFSDFSDFSDFDFDFrACAAAAAAEMAAA=","ChildFolderCount":0,"UnreadItemCount":8,"TotalItemCount":94},
{"#odata.id":"https://outlook.office365.com/api/v1.0/Users('sample.user#demosite.com')/Folders('AAMkADBjMGZiZGFlLTE4ZmEasdasdasdASDASDASDASDSADDASDASDAB4xqMnAAA=')",
"Id":"AAMkADBjMGZiZGFlLTE4ZmEtNGRlOS1iMjllLTJmOGZkNGRhZmIzNQAuAasdASDASDASDASEDASDASDxSEHjzrACAAB4xqMnAAA=",
"DisplayName":"AnotherSampleFolder","ParentFolderId":"AAMkADBjMGZiZGFlLTE4ZmEtNGRlOS1sdsDFSDFSDFSDFSDFSDFDFDFrACAAAAAAEMAAA=","ChildFolderCount":0,"UnreadItemCount":21,"TotalItemCount":75}
]
}
The C# code using to parse JSON and find the required data.
HttpResponseMessage response = httpClient.SendAsync(request).Result;
if (!response.IsSuccessStatusCode)
throw new WebException(response.StatusCode.ToString() + ": " + response.ReasonPhrase);
string content = response.Content.ReadAsStringAsync().Result;
JObject jResult = JObject.Parse(content);
if (jResult["odata.error"] != null)
throw new Exception((string)jResult["odata.error"]["message"]["value"]);
//Attempt one - using dynamic [NOT WORKING - getting NULL values in the variables]
dynamic results = JsonConvert.DeserializeObject<dynamic>(content);
var folderName = results.Id;
var folderId = results.Name;
//Attempt two - [Not working - Throwing exception -
//Object reference not set to an instance of an object.]
var folderID = (string)jResult["odata.context"]["odata.id"][0]["Id"];
First create a class for your json object
public class RootObject
{
[JsonProperty(PropertyName = "#odata.context")]
public string context { get; set; }
public List<Value> value { get; set; }
}
public class Value
{
[JsonProperty(PropertyName = "#odata.id")]
public string dataId { get; set; }
public string Id { get; set; }
public string DisplayName { get; set; }
public string ParentFolderId { get; set; }
public int ChildFolderCount { get; set; }
public int UnreadItemCount { get; set; }
public int TotalItemCount { get; set; }
}
Then Json Convert the Json string to your RootObject if your are using Newtonsoft Json then Deserilaze by using
RootObject shortiee = JsonConvert.DeserializeObject<RootObject>("Your Json String");
private List<string> GetDisplayNames(JObject content)
{
var obj = Json.Parse(content);
var values = obj["value"].ToList();
var displayNames = new List<string>();
foreach (var value in values)
{
displayNames .Add(system["DisplayName"].ToString());
}
return displayNames;
}
This would return the names, for example, and you could do this for each value you need to retrieve. However, this does not require you to serialize/deserialize the json object before using it. It works, but is most likely not best practice.
if (jResult["odata.error"] != null)
throw new Exception((string)jResult["odata.error"]["message"]["value"]);
//Attempt one - using dynamic [NOT WORKING - getting NULL values in the variables]
dynamic results = JsonConvert.DeserializeObject<dynamic>(content);
Side note: There is no key called "odata.error" in your JSON data. So you're effectively calling something which will return null.
One of the ways to deserialise JSON is to create model classes for the objects you want to process and deserialise into them directly, eg. JsonConvert.DeserializeObject<Folder>(content). As you are talking to an Office365 API, you find documentation and examples here on how they are defined.
Taken your folder response as an example, your model for a single Folder could look like this:
public class Folder
{
[JsonProperty(PropertyName = "#odata.id")]
public string OdataId { get; set; }
public string Id { get; set; }
public string DisplayName { get; set; }
public string ParentFolderId { get; set; }
public int ChildFolderCount { get; set; }
public int UnreadItemCount { get; set; }
public int TotalItemCount { get; set; }
}
Note1: in your example, you get a response with list of folders, so have to adjust this accordingly.
Note2: you can use JsonProperty to define a mapping between a JSON property/key and a C# property as shwon for #odata.id.
However, you can also use the Outlook Client Library which would make it mostly unnecessary to deal with JSON data directly (which seems preferable, unless you have a very specific reason to deal with JSON directly).

HttpClient GetAsync and ReadAsStringAsync needed to deserialize just part of a complex JSON response

I am trying to deserialize just part of my JSON response when I call my function and then return it as a viewmodel but I can't seem to access an inner part of the JSON when I do this. The function in question is this,
// GetUserInfoTest method gets the currently authenticated user's information from the Web API
public IdentityUserInfoViewModel GetUserInfo()
{
using (var client = new WebClient().CreateClientWithToken(_token))
{
var response = client.GetAsync("http://localhost:61941/api/Account/User").Result;
var formattedResponse = response.Content.ReadAsStringAsync().Result;
return JsonConvert.DeserializeObject<IdentityUserInfoViewModel>(formattedResponse, jsonSettings);
}
}
I am able to setup an HttpClient with a token of an already authenticated user, and now I just need to get information regarding them by making a call to my API. Here is the viewmodel I am trying to fit the JSON into,
// Custom view model for an identity user
/// <summary>Custom view model to represent an identity user and employee information</summary>
public class IdentityUserInfoViewModel
{
/// <summary>The Id of the Identity User</summary>
public string Id { get; set; }
/// <summary>The Username of the Identity User</summary>
public string UserName { get; set; }
/// <summary>The Email of the Identity User</summary>
public string Email { get; set; }
/// <summary>Active status of the user</summary>
public bool Active { get; set; }
/// <summary>The Roles associated with the Identity User</summary>
public List<string> Roles { get; set; }
}
And the sample response,
{
"Success":true,
"Message":null,
"Result":{
"Id":"BDE6C932-AC53-49F3-9821-3B6DAB864931",
"UserName":"user.test",
"Email":"user.test#testcompany.com",
"Active":true,
"Roles":[
]
}
}
As you can see here, I just want to get the Result JSON and deserialize it into the IdentityUserInfoViewModel but I just can't seem to figure out how to go about doing it. It feels like something simple that I'll be kicking myself in the butt about later but can't seem to grasp what it is. Any ideas?
The data to deserialize into IdentityUserInfoViewModel is actually contained in the "Result" property of your posted JSON. Therefore you need to deserialize into some kind of container object like this:
public class Foo
{
public bool Success { get; set; }
public string Message { get; set; }
public IdentityUserInfoViewModel Result { get; set; }
}
Then your can deserialize into that and access the resulting object's Result property:
var o = JsonConvert.DeserializeObject<Foo>(formattedResponse);
var result = o.Result; // This is your IdentityUserInfoViewModel
You can make the response container generic, so it can contain any kind of result:
public class ResultContainer<T>
{
public bool Success { get; set; }
public string Message { get; set; }
public T Result { get; set; }
}
And then:
var container = JsonConvert.DeserializeObject<ResultContainer<IdentityUserInfoViewModel>>(formattedResponse);
var result = container.Result; // This is your IdentityUserInfoViewModel
Maybe I can help you by showing how I use the Deserializer for JSON:
public async Task GetJsonAsync()
{
HttpClient client = new();
HttpResponseMessage response = await client.GetAsync("put in your https");
if (response.IsSuccessStatusCode)
{
rootobjects = JsonSerializer
.Deserialize<ObservableCollection<Rootobject>>(await response.Content.ReadAsStringAsync(),
new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });
}`

Filling list with Json data and getting the objects from it

I have a php webservice which gets the data from database and returns it as json data.
Json data
{"faqs":
[
{"faq":{"id":"123"}},
{"faq":{"id":"124"}}
]
}
Object classes
public class FaqList
{
public List<Faq> faqs { get; set; }
}
public class Faq
{
public string id { get; set; }
}
Test class
var client = new HttpClient();
HttpResponseMessage response = await client.GetAsync(new Uri("http://www.mydomain.com/webservice/7/server.php"));
var jsonString = await response.Content.ReadAsStringAsync();
FaqList list = JsonConvert.DeserializeObject<FaqList>(jsonString);
list.faqs.Count() => 2
list.faqs[0].id => NULL !!
I fill all the objects to the 'list'. With count test I see that it's filled. But if I try to get an objects from it, I get null error.
So, how can I correctly fill my list so that I can get the objects from it?
http://json2csharp.com/ suggests these definitions. (One more class Faq2)
public class Faq2
{
public string id { get; set; }
}
public class Faq
{
public Faq2 faq { get; set; }
}
public class RootObject
{
public List<Faq> faqs { get; set; }
}

Categories

Resources