Contentful logo

Contentful Community

Getting Entry + Metadata

I’ve created classes that map to my content types (e.g. “Page”) in Contentful. I’m using the GetEntry and GetEntriesByType methods on ContentfulClient. If I use Page as the T parameter, everything works fine. But in some cases I want the metadata as well, so I am trying to pass in Entry, but the Fields property of the result is always null. (I can see in the network traffic that the fields are actually coming back from the server; the C# code just isn’t populating them.)

Using the C# code, how can I get an entry by ID and get both the content and the content type metadata?

Hi!

You can add a public SystemProperties Sys { get; set; } property to your custom class and it will automatically be populated with the system metadata.

Hope this helps and just let me know if you have any further questions!

Great, thanks! I actually needed to do some custom deserialization, so I am just using JObject as my entry type now.

Oh, interesting, what custom deserialization is that? Keep in mind that using JObject will not automatically resolve referenced entries. It’s almost always better to use strong types.

I have an entry ID, but I don’t know ahead of time what type of content the entry is. So when I get the JObject response, I look at sys.contentType.sys.id, and choose the type based on that. And then manually resolve the included entries/assets.

SDK-wise, it would be nice if there was a non-generic version of GetEntries that would choose the type based on the ContentTypeResolver.

Ah, sounds like what you’re looking for is the IContentTypeResolver

On the IContentfulClient you can set a ContentTypeResolver property, basically instructing the SDK how you want your different content types to be resolved. An implemented resolver could look something like this:

public class EntityResolver : IContentTypeResolver
    {
        public Dictionary<string, Type> _types = new Dictionary<string, Type>()
        {
            { "person", typeof(Person) },
            { "product", typeof(Product) },
        };

        public Type Resolve(string contentTypeId)
        {
            return _types.TryGetValue(contentTypeId, out var type) ? type : null;
        }
    }

This resolver will resolve the contenttypes “person” and “product” into Person and Product respectively. All you need to do next is to give your classes some sort of marker interface, lets say IEntity and then make a call like this:

client.ContentTypeResolver = new EntityResolver();
var entities = await client.GetEntries<IEntity>();

and the entities collection would now contain both Person and Product respectively. You could then do:

var persons = entities.Where(p => p is Person);
var products = entities.Where(p => p is Product);

To get a collection of each.

Perfect! Looks like I don’t even need a marker interface, I can just use object.

I tried ContentResolver before, but it didn’t work because I was using GetEntry. Now that I’m using GetEntries, it works just as expected.

Thanks.

1 Like