Giter VIP home page Giter VIP logo

Comments (45)

rytmis avatar rytmis commented on June 7, 2024 1

Reading this method in Json.NET leads me to believe that the internal serializer is in fact the party in all this that keeps the reference map, so to me, this does look like a clue. :)

from contentful.net.

rytmis avatar rytmis commented on June 7, 2024 1

Ah, that actually makes more sense!

I'm sort of impatient with documentation, so if I don't immediately find what I'm looking for, I usually just go for the IDE -- that's where the code will end up anyway. %)

from contentful.net.

daspuru avatar daspuru commented on June 7, 2024 1

Thanks @Roblinde. I made all my POCO models and your code suggestion worked fine.

Greetings.

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

Hmm, this sounds like something related to the ref id stuff we solved quite recently. Is this with the latest version?

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

Thinking of this issue #47

from contentful.net.

rytmis avatar rytmis commented on June 7, 2024

Ah, fair point. Let me try and see if it reproduces with the latest.

from contentful.net.

rytmis avatar rytmis commented on June 7, 2024

Still reproduces on 0.13.0-beta. Let me see if I can distill a simple test case for you.

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

Great, I'll look into it asap

from contentful.net.

rytmis avatar rytmis commented on June 7, 2024

Interesting. I forked the repo and attempted to recreate the situation with an on-disk version of the API response, but it doesn't seem to reproduce there.

I then added a console app project (targeting .NET 4.6.2) to the solution, brought in the entity class and related configuration data and re-ran the test against the actual API, and it does reproduce.

I'm going to see if I can debug the deserialization process a little bit to see what's going on.

from contentful.net.

rytmis avatar rytmis commented on June 7, 2024

Soooo. I'm beginning to think this has got to be something to do with dependent assemblies and/or runtime versions. I debugged through the process that resolves the linked assets and replaces duplicates with $ref entries in the JSON, saved the results from both the console app and the test case -- and the files are identical. This leads me to believe that the difference actually occurs inside Json.NET, because the next step in the deserialization is the ToObject<T> call.

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

Wow, that's interesting. I'm soon back at a computer and will have a look as well.

Thanks for the thorough investigation.

from contentful.net.

rytmis avatar rytmis commented on June 7, 2024

So just to humor myself I added another console app that targets netcoreapp11, duplicated the code from the first one there... and it still fails. I'm running out of ideas on how to pinpoint the guilty party here. :)

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

Well, that's good at least I think. Not the framework version, but probably something else then...

After the call to ToObject<T> there's one more code that is run in the SDK and that's the AssetJsonConverter could there be something in there that fails?

from contentful.net.

rytmis avatar rytmis commented on June 7, 2024

You might be on to something:

image

Edit: And yes, in the test project it does return the asset.

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

hmm, interesting. Still weird it only fails in certain cases...

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

Just tried to replicate this locally with a console application. Here's what I did:

  • Create a content type with one property images of type multiple assets.
  • Create an entry of the content type. Add 4 images.
  • Duplicate the entry.
  • Create a netcore console app.
  • Create a very simple c# class:
public class Borg
    {
        public List<Asset> Images { get; set; }
    }

(dont ask me why Borg, it was just random...)

  • Get the entries:
var client = new ContentfulClient(new System.Net.Http.HttpClient(), 
                "<api_key>", "<space_id>");

            var borgs = client.GetEntriesAsync<Borg>(QueryBuilder<Borg>.New.ContentTypeIs("borg")).Result;

And it works... Did you do anything differently that you can imagine?

from contentful.net.

rytmis avatar rytmis commented on June 7, 2024

Was it netcore10 or netcore11? Maybe we have different dependency trees.

Some interesting observations from the AssetConverter. Here's a debugger view of the JsonSerializer's internals when deserializing the first entry:

image

I've used Make Object ID here to track the serializer. Now, here's the very same view when converting assets for the next entry (and note that this is all happening within that one single Select statement in GetEntriesAsync):

image

Note how the serializer is the same instance, but the proxy has changed, as has the reader.

I'd say this is coincidental, except: when I run the tests and trace them in a similar fashion, I get the same three instances every time. So I'm leaning towards a hypothesis where something within Json.NET is resetting the state of the reader in two of my three cases.

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

That would explain it, resetting the reader would probably mean that it has no idea where to resolve the $id from. My test was with netcoreapp1.1

from contentful.net.

rytmis avatar rytmis commented on June 7, 2024

Sigh. I guess there's no way around this. Since I'm the one with the repro, I'm going to see if I can build Json.NET from sources and see what's actually going on here. 🙄

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

Haha, I'm sorry man. Don't feel obliged to though, I'll keep looking on my side too. Will test with full framework next.

from contentful.net.

rytmis avatar rytmis commented on June 7, 2024

Nah, it's all good. There's a reason it's called the bleeding edge. 😉 This might be a bit tricky though, given that Json.NET is strongly named...

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

Yeah, strong naming. What a great idea... not!

Still working for me on full framework 4.6.2 unfortunately (or fortunately, not sure really...)

from contentful.net.

rytmis avatar rytmis commented on June 7, 2024

Did you have to install the System.Net.Http 4.3.1 package from NuGet? There's a whole slew of reasons why one might end up doing that -- the .NET 4.6.2 release broke a bunch of stuff there by accident. I'm left wondering if maybe I have a different set of runtime assemblies that somehow causes this issue.

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

ah, there's something to that, it rings a bell... let me check.

It seems I have that installed: c:\projects\ConsoleApp54\packages\System.Net.Http.4.3.0\lib\net46\System.Net.Http.dll

Did you have that?

It still says Version 4.1.1.0 though on the assembly

from contentful.net.

rytmis avatar rytmis commented on June 7, 2024

Yeah, I do. So there's no difference there either. Dammit, I'm beginning to question my sanity here. 😄

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

Hmm could it be some gac version of jsonconverter.net or something?

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

Json.net I mean

from contentful.net.

rytmis avatar rytmis commented on June 7, 2024

Nah, I've had that happen to me before, so I made sure to check that in the debugger.

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

hmm, running out of ideas. Perhaps you could mail me a zip of a project that doesn't run (you could replace the api tokens with a temporary one) at [email protected] and I'll see if it fails on my machine as well or if there's some other difference in our setup.

from contentful.net.

rytmis avatar rytmis commented on June 7, 2024

I'll get back to this tomorrow. I still have a couple of things I can try out, but if I end up stuck, I'll throw you the zip file. Thanks for your help so far!

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

Sounds like a plan! Let me know if you want me to verify something on my end.

from contentful.net.

rytmis avatar rytmis commented on June 7, 2024

Wee-eell. It looks like I may have led myself and you down a very deep rabbit hole because I had forgotten to check an assumption or two. Sigh.

Using a fresh brain, I noticed that there was a difference between the on-disk test case and the network case, and it had nothing to do with the network, TFMs or anything else like that. Just your average case of "rytmis is a dumbass" 😉

I was deserializing to Entry<EntryType> instead of just EntryType -- is that even supposed to be supported?

from contentful.net.

rytmis avatar rytmis commented on June 7, 2024

To expand on that a bit, if I deserialize to Entry, the resulting entries seem to have the right content in the Fields property -- it's just the assets that didn't quite work right. But of course I've barely looked into it, so maybe other things are wrong too and I just haven't noticed.

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

Aaah, yeah they are handled a bit differently. I'm of half a mind to just get rid of the Entry<T> class I think it might have outlived its usefulness. Why did you decide to use that instead of a POCO of your own?

That said, it of course should work with an Entry<T> as well, but at least now we know what went wrong 😄

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

Ok, so I probably found the issue. When the type was an IContentfulResource I ran json.SelectTokens("$.items[*]") .Select(t => t.ToObject<T>(Serializer)); which basically runs with a new serializer proxy for every object (I'm assuming). But for standard POCOs I ran: json.SelectToken("$.items").ToObject<IEnumerable<T>>(Serializer); Which means one serializer for all of the objects...

Gonna test my theory and release an update if it's correct.

Many thanks for your thorough detective work on this one!

from contentful.net.

rytmis avatar rytmis commented on June 7, 2024

I suppose it was just a matter of bumping up against that class, looking at it and going "huh, this looks like it might work" -- it was the first thing I tried. I have a bad habit of learning APIs through IntelliSense-driven exploration.

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

Ok, but that's all fine! Just curious if you had a particular use case I wasn't aware of, because the more I've played around with it myself the less I see any reason to use Entry<T> anywhere really... I still use it in the managementclient though... I'll have to consider if it's worth dropping it entirely.

from contentful.net.

rytmis avatar rytmis commented on June 7, 2024

I actually thought about the line you just referenced and even tried to lift the Serializer property to a temp to avoid new invocations. For whatever reason, it didn't work -- but I may have had too many things going on at once for that to have worked anyway. :)

from contentful.net.

rytmis avatar rytmis commented on June 7, 2024

Having access to the metadata of the Entry seems like a potentially valuable thing, albeit I don't have a use case in mind right now. One would imagine that the projection from that to just select the Fields property if that's all you want would not be that much of a burden for the end users -- that is, if your point was that you'd like to drop the alternative deserialization path, you could just as well force the type to always be an Entry.

Whichever way you choose, I don't mind. Just thinking out loud, as it were. :)

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

Yeah, but to get the metadata you can just add a property public SystemProperties Sys { get; set; } to your POCO and it will be populated correctly. It's in the docs 😉

Ok, I'll consider it. Testing my theory with serialization out in a moment. Will let you know the result.

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

Now hopefully with the latest version it should work! At least my extensive testing says so (and by that I mean my prayers).

Would love for you to verify if you have the time.

from contentful.net.

rytmis avatar rytmis commented on June 7, 2024

Verified, works, thank you!

from contentful.net.

daspuru avatar daspuru commented on June 7, 2024

Hi,

I am making a loop in a c# razor HTML, in a .NET Core App (1.1), the loop is aquired in the controller via this lines:

var builder = new QueryBuilder<Entry<dynamic>>(); builder.FieldEquals("sys.id","omitted-for-security").Include(2); var entry = (await _client.GetEntriesAsync<Entry<dynamic>>(builder)).FirstOrDefault();

Then, I assign a ViewBag property in this way, which is a collection of entries:

ViewBag.practicasSaludablesServicios = entry.Fields.practicasSaludablesServicios;

Then in the Razor view, I make a loop this way:

@foreach (var servicio in ViewBag.practicasSaludablesServicios) {
And inside the loop, If I make this to see what is inside the dynamic object, I can clearly see that the Asset token does not include any subfields if the asset is repeated from another element in the IEnumerable:

`@{
var servicioSerialized = JsonConvert.SerializeObject(servicio.fields.imagen600x400);
}

@servicioSerialized
`

imagen600x400 is an Asset, which is repeated between several objects in the list, and it just have the fields populated one time in the loop.

I am using the latest Nugets:

contentful.aspnetcore 0.7.5-beta
contentful.csharp 0.14.4-beta

Am I doing something wrong?

Greetings.

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

Hi Daspuru, thanks for the detailed explanation.

The issue in this case is that when using Entry<dynamic> the serialization has no idea exactly how to deserialize your dynamic into an Asset. If you would use a custom type of your own instead it will work fine. Something like this maybe:

public class ServicioThingy {
public List<PracticasSaludablesServicio> PracticasSaludablesServicios { get ; set; }
}

public class PracticasSaludablesServicio {
public Asset Imagen600x400 { get; set; }
}

and then in your controller

var builder = new QueryBuilder<ServicioThingy>(); builder.FieldEquals("sys.id","omitted-for-security").Include(2); 

var entry = (await _client.GetEntriesAsync(builder)).FirstOrDefault();

ViewBag.practicasSaludablesServicios = entry.PracticasSaludablesServicios;

and your view

@foreach (var servicio in ViewBag.practicasSaludablesServicios) {
<p>@servicio.Imagen600x400.File.Url</p>
}

Let me know if this works better for you.

from contentful.net.

Roblinde avatar Roblinde commented on June 7, 2024

Great!

from contentful.net.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.