Convert JSON response to Graph.EducationAssignment Object - c#

When I attempt to convert a JSON response to a Graph.EducationAssignment root Object there is no data. I get no error message, just an empty object.
I'm calling /beta/education/classes/{classId}/assignments
HttpResponseMessage response = await HttpClient.GetAsync(webApiUrl);
if (response.IsSuccessStatusCode)
{
string json = await response.Content.ReadAsStringAsync();
Microsoft.Graph.EducationAssignment Assignments =
JsonConvert.DeserializeObject<Microsoft.Graph.EducationAssignment>(json);
// List<Microsoft.Graph.EducationAssignment> Assignments1 =
// JsonConvert.DeserializeObject<List<Microsoft.Graph.EducationAssignment>>(json);
}
Due to the size of the response, here is the first line, which shows that the assignments are held in an array.
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#education/classes('id')/assignments",
"value": [
{
"classId": "blah-blah",
"displayName": "The homeless",
"closeDateTime": null
I'd appreciate it if somebody could help me out.

You don't describe what Microsoft.Graph.EducationAssignment looks like or where it came from. The most likely issue is that you're trying to deserialize a collection of resources (which is contained in value) into a single object.
Unless you're familiar with OData and JSON serialization, I'd avoid trying to hand-craft your own Graph client. You will have a much easier time using the Microsoft Graph Beta SDK. The SDK will handle all of this for you and you'll end up with cleaner code:
var assignments = await graphClient
.Education
.Classes["id"]
.Assignments
.Request()
.GetAsync();
var assignment = await graphClient
.Education
.Classes["id"]
.Assignments["id"]
.Request()
.GetAsync();

Related

badrequest when sending json data

I'm trying to send json data to an api and it doesn't come trough.
First of all the data is a list of objects. the very first time it works, and that is because the array is empty.
however the second time it tries to send I directly get a 400 without my debugger even coming in the controller.
I suspect that my json data cannot be deserialized form some reason, this is also my second suspect again since my reponse is of type application/problem+json.
However everything might be possible tough.
I have tried to use ['frombody'], I have tried build in json serializer aswell as newtonsoft. I have tried to use formatting.Intended but all witouth luck.
There is one paramater in my object a string that could cause problems as it contains lot of special characters-> this paramater hold a fysical path to a directory so it will contains '/' and '' and space and or other special characters from the directory name.
client:
using (HttpClient client = new HttpClient())
{
var message = new HttpRequestMessage();
message.Content = JsonContent.Create(files, typeof(List<WatchedFile>));
message.RequestUri = new Uri("http://localhost:5245/api/fileagent");
message.Method = HttpMethod.Post;
var response = await client.SendAsync(message);
if (!response.IsSuccessStatusCode)
{
logger.LogError($"Sending to api was not successful {(int)response.StatusCode}");
}
}
This still needs to be refactored to inject the hhtpclient rather thatn the using statement
controller:
[HttpPost]
public async Task<ActionResult> AddMessages([FromBody]List<WatchedFile> messages)
{
messages.ForEach(x => x.Ipaddress = HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString());
//send to repository
await context.WatchedFiles.AddRangeAsync(messages);
await context.SaveChangesAsync();
return Ok();
}
I would make sure the JSON is actually a valid JSON.
Then you try to send it with Postman to your endpoint to see if you get the intended result.
That would at least help you eliminate some of the places where it could go wrong.

Deserialize a JsonResult from C#

I access a REST API with this code :
public async Task<IActionResult> NetExplorerAPI(string AdresseAPI, object Requete, RestSharp.Method Methode)
{
var client = new RestClient(AdresseAPI);
var request = new RestRequest();
request.Method = RestSharp.Method.Post;
request.AddJsonBody(Requete);
request.AddHeader("Accept", "application/json");
//request.AddHeader("Authorization", "Bearer a844024a4e744182aeaa62dd6347b9049f9ba35650339d2b9362e1bf03a92ac0");
//IRestResponse response = await client.ExecuteAsync(request);
RestResponse response = await client.ExecuteAsync(request);
JsonResult jr = new JsonResult(response);
return (jr);
}
I want to deserialize the JsonResult to get the token in a string :
{ "token": "med6RRIikrZ-2tua9jUa6pVZubnPvhqSH6wHvtkH42TNfJGXOaI-GioUKPvfbhP7XiGG6UgjCzUnJt87kwsljQBAKEb" }
But When I serialize the JsonResult I get a lot of items I don't need to :
string s = JsonConvert.SerializeObject(jr);
{"ContentType":null,"SerializerSettings":null,"StatusCode":null,"Value":{"ContentType":null,"SerializerSettings":null,"StatusCode":null,"Value":{"Request":{"AlwaysMultipartFormData":false,"MultipartFormQuoteParameters":false,"FormBoundary":null,"Parameters":[{"DataFormat":0,"ContentEncoding":null,"Name":"","Value":{"user":"sylvain.krier#protonmail.com","password":"S#r#line2004"},"Type":3,"Encode":false,"ContentType":"application/json"},{"Name":"Accept","Value":"application/json","Type":2,"Encode":false,"ContentType":null}],"Files":[],"Method":1,"Timeout":0,"Resource":"","RequestFormat":0,"RootElement":null,"OnBeforeDeserialization":null,"OnBeforeRequest":null,"OnAfterRequest":null,"Attempts":1,"CompletionOption":0,"ResponseWriter":null,"AdvancedResponseWriter":null},"ContentType":"application/json","ContentLength":103,"ContentEncoding":[],**"Content":"{\"token\":\"wlK4LIRpOxqKOwJ2Hs554l5-WI--IrqHW7TECZ3YtdS-RpzDuQGaQeLI0qjo8NzaSPhCUYaarBcXstrI5sPlXkwCmk9\"}"**,"StatusCode":200,"IsSuccessful":true,"StatusDescription":"Ok","RawBytes":"eyJ0b2tlbiI6IndsSzRMSVJwT3hxS093SjJIczU1NGw1LVdJLS1JcnFIVzdURUNaM1l0ZFMtUnB6RHVRR2FRZUxJMHFqbzhOemFTUGhDVVlhYXJCY1hzdHJJNXNQbFhrd0NtazkifQ==","ResponseUri":"https://patrimoine-click.netexplorer.pro/api/auth","Server":"Apache","Cookies":[],"Headers":[{"Name":"Date","Value":"Tue, 19 Jul 2022 06:40:36 GMT","Type":2,"Encode":false,"ContentType":null},{"Name":"Server","Value":"Apache","Type":2,"Encode":false,"ContentType":null},{"Name":"Pragma","Value":"no-cache","Type":2,"Encode":false,"ContentType":null},{"Name":"Cache-Control","Value":"no-store, must-revalidate, no-cache","Type":2,"Encode":false,"ContentType":null},{"Name":"X-NetExplorer-Version","Value":"7.4.4.12","Type":2,"Encode":false,"ContentType":null},{"Name":"Access-Control-Allow-Origin","Value":"*","Type":2,"Encode":false,"ContentType":null},{"Name":"X-UA-Compatible","Value":"IE=edge,chrome=1","Type":2,"Encode":false,"ContentType":null},{"Name":"Connection","Value":"close","Type":2,"Encode":false,"ContentType":null},{"Name":"X-Content-Type-Options","Value":"nosniff","Type":2,"Encode":false,"ContentType":null},{"Name":"Transfer-Encoding","Value":"chunked","Type":2,"Encode":false,"ContentType":null}],"ContentHeaders":[{"Name":"Expires","Value":"Thu, 19 Nov 1981 08:52:00 GMT","Type":2,"Encode":false,"ContentType":null},{"Name":"Content-Type","Value":"application/json","Type":2,"Encode":false,"ContentType":null},{"Name":"Content-Length","Value":"103","Type":2,"Encode":false,"ContentType":null}],"ResponseStatus":1,"ErrorMessage":null,"ErrorException":null,"Version":"1.1","RootElement":null}}}
I don't know how to get the "content" item.
From RestSharp's official QuickStart:
When using typed ExecuteAsync<T>, you get an instance of RestResponse<T> back, which is identical to RestResponse but also contains the T Data property with the deserialized response.
None of ExecuteAsync overloads throw if the remote server returns an error. You can inspect the response and find the status code, error message, and, potentially, an exception.
Extensions like GetAsync<T> will not return the whole RestResponse<T> but just a deserialized response. These extensions will throw an exception if the remote server returns an error. The exception will tell you what status code was returned by the server.
It looks like you have to choices:
Use client.ExecuteAsync and then response.Data
Use client.GetAsync<T>
For client.GetAsync you'll need a new type. For exmaple
public class MyTokenClass { public string token {get; set;} }
and then var t = await client.GetAsync<MyTokenClass>().
I think this is what you looking for let me know if you need something specific.
string theToken = JObject.Parse(response.Content)["token"].ToString();
When you get a Response object from ExecuteAsync, response is already deserialized into c# Response class, but Content is not. In this case Content contains a json string. You can parse the string to get a token (or deserialize it if you create a custom class)
This code will return { "token": "med6RRIikrZ-2tua9jUa6p...} as an ActionResult
string token = (string)JObject.Parse(response.Content)["token"];
return Ok( new { token = token});
You need to return JsonResult with the Content property of RestResponse:
return new JsonResult(response.Content);

Unable to deserialize JSON in C# using the same class at both ends

I'm looking for someone to point out the obvious blunder here.
A .NET Core in C# application makes an HTTP call to another such application. Some processing is performed, and a response is sent thus:
Response response = new Response(input)
{
stuff = processedStuff;
};
responseMessage = JsonConvert.SerializeObject(response);
return new OkObjectResult(responseMessage);
This all looks good and responseMessage contains valid JSON (according to an online JSON checker I found).
At the other end, this is received thus:
Response returned = new Response();
var response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
returned = JsonConvert.DeserializeObject<Response>(json);
}
This fails with an Error converting value *the JSON string* to "Response" at line 1
Response is the same class file in both applications. What never obvious and apparently invisible mistake am I making here?
The invisible mistake you are making is double-serializing the result. The contract of OkObjectResult is that it will automatically serialize the result object to the negotiated content type (e.g. JSON or XML) and return an OK status. You are serializing the object first and then passing the serialized string to OkObjectResult so it ends up getting serialized twice.
responseMessage = JsonConvert.SerializeObject(response); // serialize to JSON
return new OkObjectResult(responseMessage); // implicit serialization here
Possible solutions:
Allow the implicit serialization to do its thing (recommended):
return new OkObjectResult(response); // implicit serialization of response object
Use a ContentResult instead (good if you need special serialization handling):
responseMessage = JsonConvert.SerializeObject(response); // serialize to JSON
return new ContentResult()
{
Content = responseMessage,
ContentType = "application/json",
StatusCode = 200
};
Deserialize twice on the receiving end (use as a last resort, i.e. you don't control the server):
var doubleSerializedJson = await response.Content.ReadAsStringAsync();
var json = JsonConvert.DeserializeObject<string>(doubleSerializedJson);
returned = JsonConvert.DeserializeObject<Response>(json);
check if the returned string is not wrapped in OkObjectResult object.
As far as I know, you don't need the serialization and deserialization, the framework already takes care of everything. If you need to, you could always deserialize to either an anonymous type or cast it from object.
https://www.newtonsoft.com/json/help/html/DeserializeAnonymousType.htm
I would also help if you could share the response class, since it's most likely part of the problem.
As someone old enough to remember when the Simpsons started, I can only answer in the traditional manner:
D'oh!
Using implicit serialization as described by the kind responder above resolved the issue.

Cannot serialize stream data asp .net core

Trying to deserialize objects from HTTP response.
Response stream returns information in json and I already checked if it is valid in online deserializer.
I got the object class from the API framework so I think all of the properties should be configured for the response.
Code:
var request = new HttpRequestMessage(HttpMethod.Get,
"api_url");
var client = _clientFactory.CreateClient();
var response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
using var responseStream = await response.Content.ReadAsStreamAsync();
var reponseString = await response.Content.ReadAsStringAsync();
var data = await JsonSerializer.DeserializeAsync<IEnumerable<Tournament>>(responseStream);
}
else
{
GetBranchesError = true;
}
I see that information in responseString is correct but data objects are always null.
Weird part is that it partially works because it shows how many objects are in the responseStream but all of the object properties are nulls.
Also tried to set the stream position to 0 - didn't help.
Any idea what I am doing wrong to deserialize these objects?
Desirializer used - System.Text.Json;
Project asp .net core 3.1
The problem is that the properties you are looking for in the JSON array are actually wrapped inside an object called "tournament". It's easier to notice when you format the JSON string nicely like this for example:
[
{
"tournament": {
"id": 1,
"name": "name1",
...
}
},
{
"tournament": {
"id": 2,
"name": "name2",
...
}
}
]
To deserialize this I would suggest you make a wrapper class to handle that:
public class TournamentItem
{
[JsonPropertyName("tournament")]
public Tournament Tournament { get; set; }
}
And then deserialize to that class:
var data = await JsonSerializer.DeserializeAsync<IEnumerable<TournamentItem>>(responseStream);
Now data.Tournament will contain all the properties.
There might still be a few issues in your properties like Spam for example. The JSON string has a null as value, but the property is not nullable - I didn't check all your properties. DeserializeAsync will throw an error and tell you.

Post JSON data to Microsoft Graph API Azure Function

I'm trying to use an Azure function to forward an Outlook email using its ID.
var url = "https://graph.microsoft.com/v1.0/users('<blah>')/messages/" + ID + "/forward";
var content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
var response = await client.PostAsJsonAsync(url, content);
log.Info(response.Content.ReadAsStringAsync().Result);
The result I'm getting is The value of the parameter 'ToRecipients' is empty. Specify 'ToRecipients' either in the message object or in the action.
The data variable I'm passing in is {"message":{"ToRecipients":[{"emailAddress":{"address":"<blah>"}}]}}.
What am I doing wrong? How do I successfully post a data JSON object? I feel like I've tried every example I can find online and I haven't had any luck.
FYI, token has already been attached to headers, I'm just not showing that part.
You appear to be double serializing the data to be sent.
First when you manually serialize
...JsonConvert.SerializeObject(data)...
and second when you call PostAsJsonAsync
client.PostAsJsonAsync(url, content);
which would serialize the provided object to JSON before posting.
If calling PostAsJsonAsync then no need for you to create the content manually
//...
var url = "https://graph.microsoft.com/v1.0/users('<blah>')/messages/" + ID + "/forward";
var response = await client.PostAsJsonAsync(url, data);
var result = await response.Content.ReadAsStringAsync();
log.Info(result);
//...

Categories

Resources