JSON.net not finding property value when property exists - c#

I'm working with Json.net, I have retrieved the following JSON from a web page:
"{\"Response\":
[{
\"iconPath\":\"",
\"membershipType\":1,
\"membershipId\":\"124877458474\",
\"displayName\":\"DarylJG\"
}],
\"ErrorCode\":1,
\"ThrottleSeconds\":0,
\"ErrorStatus\":\"Success\",
\"Message\":\"Ok\",
\"MessageData\":{ }}"
Now, I'm getting the following error when trying to return a string from this property:
An unhandled exception of type
'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in
System.Core.dll
Additional information: 'Newtonsoft.Json.Linq.JArray' does not contain
a definition for 'iconPath'
Which the iconPath does exist within this JSON file. The code i'm using:
var response = client.GetAsync("CorrectServerPath & Auth").Result;
var content = response.Content.ReadAsStringAsync().Result;
dynamic item = Newtonsoft.Json.JsonConvert.DeserializeObject(content);
return item.Response.iconPath;
This is the lines of code which are throwing this error, but the following code:
return item.Message;
will return OK
So my overall question, is how can I reach iconPath in the provided json file using JSON.net? As, i'm at a loss. Research material has come up with nothing & Probably using the incorrect Search Terms

Your Response member is an array, not an object. Use item.Response[0].iconPath, instead.

Related

System.Text.Json.JsonException: The input does not contain any JSON tokens

I'm just trying to use a Http POST method in a Blazor app through
public async Task CreateUnit(UnitEntity unit)
{
await _http.PostJsonAsync<UnitEntity>("api/units", unit);
}
_http and myObject have been defined elsewhere, but I'm getting this weird error. Can anyone help? This is the closest thing I could find elsewhere: https://github.com/dotnet/runtime/issues/30945.
The full error message is
System.Text.Json.JsonException: The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0.
And it here's the stack
Another reason this error could pop up, as it did for me, is simply because the API endpoint doesn't exist because it was misspelled.
I got a similar error in Program.cs Main method CreateHostBuilder(args).Build();:
System.FormatException: 'Could not parse the JSON file.'
JsonReaderException: The input does not contain any JSON tokens.
Expected the input to start with a valid JSON token, when isFinalBlock
is true. LineNumber: 0 | BytePositionInLine: 0.
For me it turned out to be the local secrets.json file that not contained a valid json object.
https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-5.0&tabs=windows#secret-manager
Because of this I could not see any errors in Git or rollback to a working commit since the file is not checked in.
Solved by adding an empty object to the file via Visual Studio - right click the project in solution explorer and select Manage User Secrets:
{
}
https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-5.0&tabs=windows#manage-user-secrets-with-visual-studio
In my case the code was doing this:
var json = await response.Content.ReadAsStringAsync();
var result = JsonObject.Parse(json); // threw the exception mentioned in the question
Why did that happen? That's because json value was an empty string "". Parse fails with an empty string.
Fixed it doing this simple change:
var json = await response.Content.ReadAsStringAsync();
var result = string.IsNullOrEmpty(json) ? null : JsonObject.Parse(json);
i had similar issue and the problem to check if the json string you are readying is empty, null, or bad formatted. debug to the code line where you are reading data into string before deserialize or serialize call.
I got this error when communicating between two APIs.
request = await req.DeserializeRequestBodyAsync<MyDto>(jsonSerializerOptions);
Turned out the code below did not actually send any values:
httpRequestMessage.Content = JsonContent.Create(myDto);
var httpClient = _clientFactory.CreateClient();
var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage, cancellationToken);
I had to manually specify:
await httpRequestMessage.Content.LoadIntoBufferAsync();
Like this:
httpRequestMessage.Content = JsonContent.Create(myDto);
await httpRequestMessage.Content.LoadIntoBufferAsync();
var httpClient = _clientFactory.CreateClient();
var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage, cancellationToken);
For me, this error occurred when calling FindByNameAsync of UserManager.
Sounds silly, but the database connection string in the appsettings was wrong!
Late answer - but I ran into this using Blazor WebAssembly with Browser Link (trying to get Hot Reload to work). Turns out it's an issue loading the appsettings and Browser Link was expecting the secrets file. I fixed by right clicking the Server project and copy/pasting my appsettings values into the secrets file.
In my case, I was passing the id of my object along with the object itself in the url of the put request to an API and faced the same exception. It turned out that it was not necessary to pass the id (as it was retrieved from the object itself, in fact it was not present in the method signature). Removing the id solved the problem.
This error occurred when communicating between client and web API.
API code:
public async Task<IActionResult> PostAsync(object review)
{
return Ok();
}
Client code:
var res = await _client.PostAsJsonAsync("api/reviews", review);
if (res.IsSuccessStatusCode)
{
var myObject = await res.Content.ReadFromJsonAsync<MyObject>(); //this line threw mentioned error
}
Turned out that the API endpoint was returning something different compared to what I was trying to read from JSON i.e. I was trying to read MyObject but API was returning ActionResult
In my case database column was marked not null and I was passing null in API.

Deserialising XML To DTOs In Service Reference

I want to use captured SOAP responses as test data. I've successfully got the SOAP XML and now want to use it to populate the DTOs in my project service reference. This is where I'm coming unstuck.
When I use Message.CreateMessage in conjunction with either message.GetBody or TypedMessageConverter, I have a problem where the deserialiser is trying to populate the PropertyChanged event handler and throws an exception. Why would it do this and how can I stop it?
Added From Comments
Truncated XML:
<GetServiceDetailsResponse xmlns="http://thing.com/thing/">
<GetServiceDetailsResult xmlns:lt4="http://thing.com/thing/types">
<lt4:generatedAt>2016-10-14T14:10:39.7718069+01:00</lt4:gene‌​ratedAt>
</GetServiceDetailsResult>
</GetServiceDetailsResponse>
Code:
string action = null;
XmlReader bodyReader = XmlReader.Create(new StringReader(Resources.eg_xml));
Message msg = Message.CreateMessage(MessageVersion.Default, action, bodyReader);
var b = msg.GetBody<GetServiceDetailsResponse>();`
Exeption
SetUp : System.TypeInitializationException : The type initializer for
'IntegrationTests.GetServiceDetail.Class1' threw an exception. ---->
System.ServiceModel.Dispatcher.NetDispatcherFaultException : The
formatter threw an exception while trying to deserialize the message:
There was an error while trying to deserialize parameter
http://thing.com/thing/:GetServiceDetailsResult. The InnerException
message was ''EndElement' 'GetServiceDetailsResult' from namespace
'http://thing.com/thing/' is not expected. Expecting element
'PropertyChanged'.'

Web Api Get method returns HTTP/1.1 500 Internal Server Error

I create controllers using entity. There are severel models in my project and for every model in context "Get method" works fine, but this one, which is the same like others, did'nt.
This is simple code:
// GET: api/Proizvodi
public IQueryable<Proizvodi> GetProizvodi()
{
return db.Proizvodi;
}
I tested with fidler and this is message:
{"Message":"An error has occurred.","ExceptionMessage":"The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.","ExceptionType":"System.InvalidOperationException","StackTrace":null,"InnerException":{"Message":"An error has occurred.","ExceptionMessage":"Self referencing loop detected with type 'System.Data.Entity.DynamicProxies.Proizvodi_B322A16527536C491FCFE47A9DC60617BBB3A2AAF1FABD41D99F924F0D8FE589'. Path '[0].JediniceMjere.Proizvodi'.","ExceptionType":"Newtonsoft.Json.JsonSerializationException",...
I know there are severel same question and im looking for answer but can't find. Is there problem with entity freimwork, problem with serialization or something else. ??
Maybe this help: when i delete all records from database for this model/class, "Proizvodi", i get "HTTP/1.1 200 OK".
Add thhe following to
Global.asax
HttpConfiguration config = GlobalConfiguration.Configuration;
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

Using suds for python as a SOAP client and failing to handle NoneType

So i'm using suds-jurko for python3 and I have a value in my request like this:
`Date = None`
Date is not a required field. The issue I'm running into is when it processes the request, I get the error:
WebFault: Server raised fault: 'The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://webservices.soapclient.com/v11:request. The InnerException message was 'There was an error deserializing the object of type WebServices.Posting.Request. The value '' cannot be parsed as the type 'DateTime'.'. Please see InnerException for more details.'
Any clue how I can pass a valid NoneType so that my client won't convert it to an empty string?
If the Date field is optional, you should completely skip it and not try to pass any value at all (even if it's set to NoneType).

Encountered invalid root element name 'HTML'. 'root' is the only allowed root element name

i am using msdn sample code and it has jsonp wrapper files you can find the code here
of this article and MSDN article JSON with Padding (AJAX)
but when i run the code it throw me this error:
Encountered invalid root element name 'HTML'. 'root' is the only allowed root element name
what does it mean?
It means that you've made some kind of web request that is expecting to get some kind of XML data back but instead it is getting HTML data back. The usual cause is a messed up URL. If your URL were correct, then XML would be returned as expected. Since it is messed up you end up getting back HTML (probably an error page at that).
Check your URLs to make sure they are correct.
I found the solution to similar problem. In my case, I was getting similar error, when my service was returning raw JSON, that is to say it was returning a Stream which represented this JSON.
The error was: Encountered invalid root element name 'Binary'. 'root' is the only allowed root element name.
The problem is that the MS provided example uses JsonWriter to take convert the message to JSON, but this writer expects that your message consists of JSON objects which he can convert to Stream. In my case the message was compose of binary data, so instead of one "root" element I was having "Binary" element.
I got over this issue by modifying classes provided by the MS sample. Basically I check the format of the message - if it is JSON I can still use the JsonWriter, if it is Binary, I have to take a different approach. In your case the message is in HTML format (I am not sure how do you serve it), but you will find a different way to get the body of the message.
I wrote a blog post about my issue here: http://hoonzis.blogspot.com/2011/07/provide-jsonp-with-your-wcf-services.html
Hope it helps a bit, Honza
I ran into the same error message but in a different scenario. I was adding JSON support to a WCF web service that only supported XML.
Specifically I wanted to return the error messages object in JSON also.
I had a class that was implementing System.ServiceModel.Dispatcher.IErrorHandler. Within the ProvideFault method I was setting the `WebBodyFormateMessageProperty to the corresponding one wither, XML or JSON based on what it was passed in the accept header. I was also setting the content type accordingly. What I was missing was using the correct serializer for each case
Dim webBodyFormatMessageProp As Channels.WebBodyFormatMessageProperty
Dim contentType As String
Dim serializer As XmlObjectSerializer
If WebOperationContext.Current.OutgoingResponse.Format = WebMessageFormat.Json Then
webBodyFormatMessageProp = New System.ServiceModel.Channels.WebBodyFormatMessageProperty(System.ServiceModel.Channels.WebContentFormat.Json)
contentType = "application/json"
serializer = New DataContractJsonSerializer(GetType(MyErroClass))
Else
webBodyFormatMessageProp = New System.ServiceModel.Channels.WebBodyFormatMessageProperty(System.ServiceModel.Channels.WebContentFormat.Xml)
contentType = "text/xml"
serializer = New DataContractSerializer(GetType(MyErroClass))
End If
Dim detail = faultException.[GetType]().GetProperty("Detail").GetGetMethod().Invoke(faultException, Nothing)
fault = System.ServiceModel.Channels.Message.CreateMessage(version, "", detail, serializer)
fault.Properties.Add(System.ServiceModel.Channels.WebBodyFormatMessageProperty.Name, webBodyFormatMessageProp)
Dim httpResponseMessageProp = New System.ServiceModel.Channels.HttpResponseMessageProperty()
httpResponseMessageProp.Headers(System.Net.HttpResponseHeader.ContentType) = contentType
httpResponseMessageProp.StatusCode = System.Net.HttpStatusCode.OK
httpResponseMessageProp.StatusDescription = [error].Message
fault.Properties.Add(System.ServiceModel.Channels.HttpResponseMessageProperty.Name, httpResponseMessageProp)
Apologize for the VB.net but that is what I am currently working on.

Categories