Deserialization not filling my variables/response.data shows null - c#

I want to put the jsonBody I get from the Rest API into this class construction.
Console.WriteLine(response.Data);
Somehow it only returns null.
This my whole code:
RestClient client = new RestClient("https://euterpe.webuntis.com/WebUntis/jsonrpc.do?school=HTL-Perg");
public void login()
{
var request = new RestRequest(Method.POST);
request.AddHeader("Content-type", "application/jason");
request.AddJsonBody(new
{
id = "ID",
method = "authenticate",
#params = new
{
user = "kung",
password = "foo",
client = "CLIENT"
},
jsonrpc = "2.0"
});
var response = this.client.Execute<AuthenticationResponse>(request);
Console.WriteLine(response.Data);
}
The request is working and I get the following return of the Rest API:
{
"jsonrpc":"2.0",
"id":"ID",
"result": {
"sessionId":"A173BECFB75F66123D6B678BE9745A29",
"personType":5,
"personId":1234,
"klasseId":123
}
}
Finally this are the two classes the response should get stored to, but the variables seem to stay empty:
public class AuthenticationResponse
{
[DeserializeAs(Name = "jsonrpc")]
public String Jsonrpc { get; set; }
[DeserializeAs(Name = "id")]
public int id { get; set; }
[DeserializeAs(Name = "result", Content=true)]
AuthenticationResult res { get; set; }
}
public class AuthenticationResult
{
[DeserializeAs(Name = "sessionId")]
string sessionId { get; set; }
[DeserializeAs(Name = "personType")]
int personType { get; set; }
[DeserializeAs(Name = "personId")]
int personId { get; set; }
[DeserializeAs(Name = "klasseId")]
int klasseId { get; set; }
}
Thanks for every advice.

I have taken a look at your code and tried it with WebUntis. Here is a working example as a console app. Especially important is the call to client.AddHandler Hope it helps solving your problem.
using RestSharp;
using RestSharp.Deserializers;
using System;
using System.Text;
namespace ConsoleApp3
{
internal class Program
{
private static RestClient client = new RestClient("https://euterpe.webuntis.com/WebUntis/jsonrpc.do?school=HTL-Perg");
public class AuthenticationResponse
{
[DeserializeAs(Name = "id")]
public string id { get; set; }
[DeserializeAs(Name = "result", Content = true)]
public AuthenticationResult result { get; set; }
}
public class AuthenticationResult
{
[DeserializeAs(Name = "sessionId")]
public string sessionId { get; set; }
[DeserializeAs(Name = "personType")]
public int personType { get; set; }
[DeserializeAs(Name = "personId")]
public int personId { get; set; }
[DeserializeAs(Name = "klasseId")]
public int klasseId { get; set; }
}
private static void Main(string[] args)
{
client.AddHandler(new JsonDeserializer(), "application/json-rpc");
var request = new RestRequest(Method.POST);
request.AddHeader("Content-type", "application/json");
request.AddJsonBody(new
{
id = "ID",
method = "authenticate",
#params = new
{
user = "kung",
password = "foo",
client = "CLIENT"
},
jsonrpc = "2.0"
});
var response = client.Execute<AuthenticationResponse>(request);
var resp = Encoding.UTF8.GetString(response.RawBytes, 0, (int)response.ContentLength);
Console.WriteLine(response.Data);
}
}
}
Greetings,
Rainer.

Your AuthenticationResponse possibly needs to be
public class AuthenticationResponse
{
[DeserializeAs(Name = "id")]
public string id { get; set; }
[DeserializeAs(Name = "result")]
AuthenticationResult res { get; set; }
public string jsonrpc { get; set; } // Can remove if you dont need it.
}
Update
Based on your comment that this didn't work, please try to use Newtonsoft.Json to deserialize your result.
var response = client.Execute(request);
var deserialized = JsonConvert.DeserializeObject<AuthenticationResponse>(response.Content);
You would have to use JsonPropertyAttribute instead of DeserliazeAs in your class definition.
public class AuthenticationResponse
{
[JsonProperty("id")]
public string id { get; set; }
[JsonProperty("result")]
AuthenticationResult res { get; set; }
}
public class AuthenticationResult
{
[JsonProperty("sessionId")]
string sessionId { get; set; }
[JsonProperty("personType")]
int personType { get; set; }
[JsonProperty("personId")]
int personId { get; set; }
[JsonProperty("klasseId")]
int klasseId { get; set; }
}
Additional Option
You could also use RestSharp.Newtonsoft.Json which makes Newtonsoft.Json default serializer for RestSharp (and skipping the intermediate step).

In your Json there is nothing called "res" that is being returned .
This should fix your issue :
public class AuthenticationResponse
{
[DeserializeAs(Name = "jsonrpc")]
public String Jsonrpc {get;set;}
[DeserializeAs(Name = "id")]
public int Id { get; set; }
[DeserializeAs(Name = "result")]
AuthenticationResult Result { get; set; }
}

Related

Getting Http Error Code 411 : Length Required

When I am trying to upload a file using following code I am receiving Length Required error. Please note that if I am uploading a TEXT file then I don't see any issues. But when I upload WORD or PDF I am seeing the error. FYI, I am able to see to Content-Length in my request header in both occasions. Any help would be much appreciated.
internal static class CreateFile
{
private static string _Server = "MyServer.com";
private static string _Database = "ACTIVE";
internal static async Task<string> CreateFileInFolder(string _AuthToken, string _FolderId, string _FileLocation)
{
// Force TLS 1.2 instead of the default value.
ServicePointManager.ServerCertificateValidationCallback = (s, cert, chain, ssl) => true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
//folder creation URI
string _FileCreateUri = $"https://{_Server}/api/v2/customers/1/libraries/{_Database}/folders/{_FolderId}/documents";
FileInfo _FileDetails = new (_FileLocation);
string _Result = "";
FileRoot _FileRoot = new()
{
doc_profile = new FileProfile()
{
author = "ADMIN",
comment = "New Import",
default_security = "private",
name = _FileDetails.Name,
custom1 = "Test",
custom2 = "Test",
custom17 = "12345",
access = "full_access",
database = _Database,
size = _FileDetails.Length,
#class = "DOC",
type = "ACROBAT",
type_description = "",
wstype = "document"
},
audit = new FileAudit()
{
comments = "Test Import"
},
keep_locked = false,
warnings_for_required_and_disabled_fields = true
};
byte[] _FileBytes = File.ReadAllBytes(_FileDetails.FullName);
string _Boundary = $"----------{DateTime.Now.Ticks:x}";
MultipartFormDataContent _MultipartFormDataContent = new(_Boundary)
{
{
JsonContent.Create(_FileRoot), "profile"
},
{
new StreamContent(new MemoryStream(_FileBytes), _FileBytes.Length), "file"
}
};
_MultipartFormDataContent.Headers.Remove("Content-Type");
_MultipartFormDataContent.Headers.TryAddWithoutValidation("Content-Type", $"multipart/form-data; boundary={_Boundary}");
using (HttpClient _HttpClient = new())
{
//include authentication token in request header
_HttpClient.DefaultRequestHeaders.Add("X-Auth-Token", _AuthToken);
using (HttpResponseMessage _HttpResMsg = await _HttpClient.PostAsync(_FileCreateUri, _MultipartFormDataContent))
{
if (_HttpResMsg.StatusCode == HttpStatusCode.Created)
{
_Result = _HttpResMsg.Content.ReadAsStringAsync().Result;
}
}
}
//MessageBox.Show($"Json profile newly created folder: {_HttpResMsg.Content.ReadAsStringAsync().Result}", "New Folder Profile", MessageBoxButton.OK);
return _Result;
}
public class FileAudit
{
public string comments { get; set; }
}
public class FileProfile
{
public string author { get; set; }
public string access { get; set; }
public string comment { get; set; }
public string #class { get; set; }
public string database { get; set; }
public string default_security { get; set; }
public string name { get; set; }
public long size { get; set; }
public string type { get; set; }
public string type_description { get; set; }
public string wstype { get; set; }
public string custom1 { get; set; }
public string custom2 { get; set; }
public string custom17 { get; set; }
}
public class FileRoot
{
public FileProfile doc_profile { get; set; }
public FileAudit audit { get; set; }
public bool keep_locked { get; set; }
public bool warnings_for_required_and_disabled_fields { get; set; }
}
}
Tried to use HttpRequestMessage by setting Content-Length but again able to upload TEXT files but not WORD or PDF files.

Reading and writting on appsettings.json

I am trying to read and write a value on appsettings.json.It is called Refreshed_Token. I have found something on internet and it was very well explained as an example but i get only one error. Can you please guys help me thank you very much.
Worker.cs
public async Task request_refresh_token()
{
var client = new RestClient("https://accounts.zoho.eu/oauth/v2/token?grant_type=authorization_code&client_id=" +_config.Value.Zoho_Client_Id+ "&client_secret=" +_config.Value.Zoho_Client_Secret+ "&code=" +_config.Value.Zoho_Code);
var request = new RestRequest();
request.AddHeader("Cookie", "xxx; xxx; iamcsr=xxx");
RestResponse response = await client.PostAsync(request);
var result = JObject.Parse(response.Content);
var refresh_token = result["refresh_token"].Value<string>();
update_appsettings_json(refresh_token);
}
public void update_appsettings_json(string refresh_token)
{
var appSettingsPath = Path.Combine(System.IO.Directory.GetCurrentDirectory(), "appsettings.json");
var json = File.ReadAllText(appSettingsPath);
var jsonSettings = new JsonSerializerSettings();
jsonSettings.Converters.Add(new ExpandoObjectConverter());
jsonSettings.Converters.Add(new StringEnumConverter());
dynamic config = JsonConvert.DeserializeObject<System.Dynamic.ExpandoObject>(json, jsonSettings);
config.Config.Zoho_Code = Zoho_Refreshed_Token.refresh_token;
var newJson = JsonConvert.SerializeObject(config, Formatting.Indented, jsonSettings);
File.WriteAllText(appSettingsPath, newJson);
}
appsetting.json file :
{
"Config": {
"LeadCustomerId": "4096",
"URL": "example.com",
"Token": "xxx",
"Contact_Custom_Id": "11249",
"Opportunity_Custom_Id": "11261",
"Account_Custom_Id": "13397",
"Task_Custom_Id": "16876",
"Call_Custom_Id": "17033",
"Meeting_Custom_Id": "17098",
"Zoho_Client_Id": "xxx",
"Zoho_Client_Secret": "xxx",
"Zoho_Code": "xxx",
"Zoho_Refreshed_Token": ""
}
}
Config.cd file is:
public class Config
{
public string LeadCustomerId { get; set; }
public string WeclappURL { get; set; }
public string Weclapp_Token { get; set; }
public string Contact_Custom_Id { get; set; }
public string Opportunity_Custom_Id { get; set; }
public string Account_Custom_Id { get; set; }
public string Task_Custom_Id { get; set; }
public string Call_Custom_Id { get; set; }
public string Meeting_Custom_Id { get; set; }
public string Zoho_Client_Id { get; set; }
public string Zoho_Client_Secret { get; set; }
public string Zoho_Code { get; set; }
public string Zoho_Refreshed_Token { get; set; }
}
The error i get is this: The Zoho_Refreshed_Token does not exist in the current context
Thank you for your time!

Fetching data from Json and displaying it in Combobox

I am trying to get a json file using a url and deserialize the json and display a particular field in the combobox but nothing shows up
WebClient client = new WebClient();
string json =
client.DownloadString("https://restcountries.eu/rest/v2/all/");
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
DataContractJsonSerializer deserializer = new
DataContractJsonSerializer(typeof(RootObject));
RootObject obj = (RootObject)deserializer.ReadObject(ms);
foreach (var name in obj.name)
{
comboBox1.Items.Add(obj.name);
}
}
this is the POCO class
public class RootObject
{
public string name { get; set; }
public List<string> topLevelDomain { get; set; }
public string alpha2Code { get; set; }
public string alpha3Code { get; set; }
public List<string> callingCodes { get; set; }
public string capital { get; set; }
public List<object> altSpellings { get; set; }
public string region { get; set; }
public string subregion { get; set; }
public int population { get; set; }
public List<object> latlng { get; set; }
public string demonym { get; set; }
public double? area { get; set; }
public double? gini { get; set; }
public List<string> timezones { get; set; }
public List<object> borders { get; set; }
public string nativeName { get; set; }
public string numericCode { get; set; }
public List<Currency> currencies { get; set; }
public List<Language> languages { get; set; }
public Translations translations { get; set; }
public string flag { get; set; }
public List<object> regionalBlocs { get; set; }
public string cioc { get; set; }
}
I want to display the name in the combobox
here is the link to the json
https://restcountries.eu/rest/v2/all/
You was trying deserialized one result, however result are list.
WebClient client = new WebClient();
string json =
client.DownloadString("https://restcountries.eu/rest/v2/all/");
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
DataContractJsonSerializer deserializer = new
DataContractJsonSerializer(List<RootObject>); //TODO: FIXED
List<RootObject>obj = (List<RootObject>)deserializer.ReadObject(ms); //TODO: FIXED
foreach (var name in obj.name)
{
comboBox1.Items.Add(obj.name);
}
}
it´s work
Add manage nuget package : Newtonsoft.Json
WebClient client = new WebClient();
string json =
client.DownloadString("https://restcountries.eu/rest/v2/all/");
dynamic dyn = JsonConvert.DeserializeObject<List<CountryName>>(json);
foreach (var item in dyn)
{
comboBox1.Items.Add(item.name);
}
public class CountryName
{
public string name { get; set; }
}
Best and fast approach and it's working fine
#A.M.Patel
i couldn't able to post it in the comment section
the code u sent worked perfectly
i too used newtonsoft.json
if iam not annoying you
can u spot out my mistakes in my code
1st code which i tried for single entry
HttpClient http = new HttpClient();
string url = "https://restcountries.eu/rest/v2/alpha/ind";
HttpResponseMessage response = http.GetAsync(new Uri(url)).Result;
string responseBody = response.Content.ReadAsStringAsync().Result;
var countries = JsonConvert.DeserializeObject(responseBody);
var details = JObject.Parse(countries.ToString());
comboBox1.Items.Add(countrynames);
it worked well
2nd code which i tried for multiple entries it doesn't showed any values in the combobox the combobox remained empty
HttpClient http = new HttpClient();
IDictionary<String, Int32> countrycounts = new Dictionary<String, Int32>();
string url = "https://restcountries.eu/rest/v2/all/";
HttpResponseMessage response = http.GetAsync(new Uri(url)).Result;
string responseBody = response.Content.ReadAsStringAsync().Result;
var countries = JsonConvert.DeserializeObject(responseBody);
var details = JObject.Parse(countries.ToString());
foreach (var obj in details){
string countrynames = details["name"].ToString();
if (countrycounts.ContainsKey(countrynames))
{
int count = countrycounts[countrynames];
count++;
countrycounts[countrynames] = count;
comboBox1.Items.Add(countrynames);
}
else { comboBox1.Items.Add(countrynames); }

Cast Deserialised Object to Another Type

I'm calling an API that returns a standard response structure for all actions. I deserialise the response using Newtonsoft.Json and JsonConvert.DeserializeObject<Response>
public class Response
{
public int Code { get; set; }
public string Message { get; set; }
public object Result { get; set; }
public DateTime ResponseDateTime { get; set; }
}
The Result object changes depending on the request action that has been requested and if there was an error or not (Code + Message describe errors). I know the structure of the Result objects and have created classes for each Result I require.
How do i go about casting the Result object to a typed variable such as a Detail[]? I know i can serialize the Result object and deserialise it again but surely there is a more elegant solution.
public class Detail
{
public int Id { get; set; }
public string DetailOne { get; set; }
public string DetailTwo { get; set; }
}
If you always know what kind of Result you'll get, I'd suggest making Response generic:
public class Response<TResult>
{
public int Code { get; set; }
public string Message { get; set; }
public T Result { get; set; }
public DateTime ResponseDateTime { get; set; }
}
Then you can just deserialize to a Response<Detail[]> and Json.NET should handle everything fine.
This is assuming that if there's an error, you won't end up with a Result that could be problematic. Alternatively, you could still deserialize to a Response class, but with a JToken property type:
public class Response
{
public int Code { get; set; }
public string Message { get; set; }
public JToken Result { get; set; }
public DateTime ResponseDateTime { get; set; }
}
Then use:
Response response = JsonConvert.DeserializeObject<Response>(json);
if (response.Code == 200) // Or whatever
{
Detail[] details = response.Result.ToObject<Detail[]>();
}
You could potentially wrap that into a generic method. I'd at least try the generic response class first though.
If you change your object model to this:
public class Response<T>
{
public int Code { get; set; }
public string Message { get; set; }
public T Result { get; set; }
public DateTime ResponseDateTime { get; set; }
}
public class Detail
{
public int Id { get; set; }
public string DetailOne { get; set; }
public string DetailTwo { get; set; }
}
Then you can do this:
var original = new Response<Detail>()
{
Code = 42,
Message = "OK",
Result = new Detail()
{
Id = 1701,
DetailOne = "Don't",
DetailTwo = "Panic",
},
ResponseDateTime = DateTime.Now,
};
var json = JsonConvert.SerializeObject(original, Newtonsoft.Json.Formatting.Indented);
var response = JsonConvert.DeserializeObject<Response<Newtonsoft.Json.Linq.JToken>>(json);
if (response.Code == 42)
{
Detail detail = response.Result.ToObject<Detail>();
/* Do something with `Detail`. */
}
That seems a fairly nice way to get to the underlying Detail object.
The key technique is to serialize a Response<Detail> and deserialize as a Response<JToken>. Simple.
Of course, if you really wanted to create a Response<Detail> instance you could make a fairly straightforward way of converting from Response<JToken> to Response<Detail> by doing a straight field-to-field mapping.
Here is the Response<Detail[]> version of the code:
var original = new Response<Detail[]>()
{
Code = 42,
Message = "OK",
Result = new Detail[]
{
new Detail()
{
Id = 1701,
DetailOne = "Don't",
DetailTwo = "Panic",
},
new Detail()
{
Id = 360,
DetailOne = "Microsoft",
DetailTwo = "Xbox",
}
},
ResponseDateTime = DateTime.Now,
};
var json = JsonConvert.SerializeObject(original, Newtonsoft.Json.Formatting.Indented);
var response = JsonConvert.DeserializeObject<Response<Newtonsoft.Json.Linq.JToken>>(json);
if (response.Code == 42)
{
Detail[] detail = response.Result.ToObject<Detail[]>();
/* Do something with `Detail[]`. */
}

.net Core 2.0 Web API - Newtonsoft.Json.JsonSerializationException - IQueryable

I have two separate .net core applications, Web API and client. I get the model using:
public IEnumerable<OhaMedication> GetOhaMedication()
{
return _context.OhaMedication;
}
The model:
public class OhaMedication
{
public int OhaMedicationId { get; set; }
public string Phn { get; set; }
public int OhaTypeId { get; set; }
public int FrequencyId { get; set; }
public MedFrequancy Frequency { get; set; }
public OhaType OhaType { get; set; }
}
public class OhaType
{
public OhaType()
{
OhaMedication = new HashSet<OhaMedication>();
}
public int OhaTypeId { get; set; }
public string Name { get; set; }
public ICollection<OhaMedication> OhaMedication { get; set; }
}
public class MedFrequancy
{
public MedFrequancy()
{
OhaMedication = new HashSet<OhaMedication>();
}
public int FrequencyId { get; set; }
public string Frequency { get; set; }
public ICollection<OhaMedication> OhaMedication { get; set; }
}
In the client I use the following to get the data:
public IQueryable<OhaMedication> GetohaMedication()
{
var dir = _session.GetString(SessionsKeys.Directory);
bool connection = InternetConnection.Check(_webApiData.WebApiitems.Url);
if (connection)
{
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(_webApiData.WebApiitems.Url);
MediaTypeWithQualityHeaderValue contentType =
new MediaTypeWithQualityHeaderValue("application/json");
client.DefaultRequestHeaders.Accept.Add(contentType);
HttpResponseMessage response = client.GetAsync("/OhaMedications").Result;
string stringData = response.Content.ReadAsStringAsync().Result;
IQueryable<OhaMedication> data = JsonConvert.DeserializeObject<IQueryable<OhaMedication>>(stringData);
return data;
}
}
else
return _context.OhaMedication;
}
I need to use IQueryable to use include as follows:
var ohaMed = GetohaMedication().Where(x => x.Phn == phn).Include(o => o.Frequency)
.Include(o => o.OhaType).ToList();
I get the following error:
Newtonsoft.Json.JsonSerializationException: 'Cannot create and populate list
type System.Linq.IQueryable`1[WebUI.Data.DataModels.OhaMedication].
Path '', line 1, position 1.'
It cannot create an interface because doesnot know which type it actually should use.
Try:
JsonConvert.DeserializeObject<List<OhaMedication>>(stringData).AsQueryable()

Categories

Resources