Giter VIP home page Giter VIP logo

contentful.net's Introduction

header

Join Contentful Community Slack   Join Contentful Community Forum

contentful.net - Contentful .NET Library

.NET library for the Contentful Content Delivery API, Content Preview API and the Contentful Management API. It helps you to easily access your Content stored in Contentful with your .NET applications.

This repository is actively maintained   MIT License   Build Status

What is Contentful?

Contentful provides content infrastructure for digital teams to power websites, apps, and devices. Unlike a CMS, Contentful was built to integrate with the modern software stack. It offers a central hub for structured content, powerful management and delivery APIs, and a customizable web app that enable developers and content creators to ship their products faster.

Table of contents

Core Features

Getting started

We recommend you use the NuGet Package Manager to add the library to your .NET Application using one of the following options:

  • In Visual Studio, open Package Manager Console window and run the following command:

    PM> Install-Package contentful.csharp
  • In a command-line, run the following .NET CLI command:

    > dotnet add package contentful.csharp

Usage

The ContentfulClient handles all communication with the Contentful Content Delivery API.

To create a new client you need to pass an HttpClient, your delivery API key and any other configuration options:

var httpClient = new HttpClient();
var client = new ContentfulClient(httpClient, "<content_delivery_api_key>", "<content_preview_api_key>", "<space_id>");

or:

var httpClient = new HttpClient();
var options = new ContentfulOptions
{
    DeliveryApiKey = "<content_delivery_api_key>",
    PreviewApiKey = "<content_preview_api_key>",
    SpaceId = "<space_id>"
};
var client = new ContentfulClient(httpClient, options);

If you are running asp.net core and wish to take advantage of the options pattern you can do so by passing an IOptions<ContentfulOptions> to the constructor. This lets you keep your authorization token in your application settings, in environment variables or your own custom Microsoft.Extensions.Configuration.IConfigurationSource provider.

Your first request

After creating a ContentfulClient, you can now query for a single entry:

var entry = await client.GetEntry<Product>("<entry_id>");

Console.WriteLine(entry.ProductName); // => Contentful
Console.WriteLine(entry.Price); // => 12.38
Console.WriteLine(entry.Description); // => A fantastic product.
public class Product
{
    public string ProductName { get; set; }
    public string Price { get; set; }
    public string Description { get; set; }
}

The properties of your class will be automatically deserialized from fields with matching names.

If you're interested in the system properties of the entry, add a SystemProperties property to the class.

public class Product
{
    public SystemProperties Sys { get; set; }
    public string ProductName { get; set; }
    public string Price { get; set; }
    public string Description { get; set; }
}
var productEntry = await client.GetEntry<Product>("<entry_id>");

Console.WriteLine(productEntry.Price); // => 12.38
Console.WriteLine(productEntry.Sys.Id); // => 2CfTFQGwogugS6QcOuwO6q

Management API

To edit, update and delete content you use the ContentfulManagementClient class which uses the same familiar pattern as the regular client.

var httpClient = new HttpClient();
var managementClient = new ContentfulManagementClient(httpClient, "<content_management_api_key>", "<space_id>");

You can then use the client to, for example, create a content type.

var contentType = new ContentType();
contentType.SystemProperties = new SystemProperties()
{
    Id = "new-content-type"
};
contentType.Name = "New contenttype";
contentType.Fields = new List<Field>()
{
    new Field()
    {
        Name = "Field1",
        Id = "field1",
        Type = "Text"
    },
    new Field()
    {
        Name = "Field2",
        Id = "field2",
        Type = "Integer"
    }
};


await managementClient.CreateOrUpdateContentType(contentType);

Using the library with the Preview API

This library can also be used with the Preview API. Make sure you have a preview API key configured and set UsePreviewAPI on your client.

var httpClient = new HttpClient();
var options = new ContentfulOptions()
{
    DeliveryApiKey = "<content_delivery_api_key>",
    PreviewApiKey, "<content_preview_api_key>"
    SpaceId = "<space_id>",
    UsePreviewApi = true
}
var client = new ContentfulClient(httpClient, options);

Authentication

To get your own content from Contentful, an app should authenticate with an OAuth bearer token.

You can create API keys using the Contentful web interface. Go to the app, open the space that you want to access (top left corner lists all the spaces), and navigate to the APIs area. Open the API Keys section and create your first token. Done.

For more information, check the Contentful REST API reference on Authentication.

Further documentation

You can read the full documentation at https://www.contentful.com/developers/docs/net/ and explore the api at https://contentful.github.io/contentful.net-docs/

Reach out to us

You have questions about how to use this library?

  • Reach out to our community forum: Contentful Community Forum
  • Jump into our community slack channel: Contentful Community Slack

You found a bug or want to propose a feature?

  • File an issue here on GitHub: File an issue. Make sure to remove any credentials from your code before sharing it.

You need to share confidential information or have other questions?

  • File a support ticket at our Contentful Customer Support: File support ticket

Get involved

PRs Welcome

We appreciate any help on our repositories. For more details about how to contribute see our CONTRIBUTING.md document.

License

This repository is published under the MIT license.

Code of Conduct

We want to provide a safe, inclusive, welcoming, and harassment-free space and experience for all participants, regardless of gender identity and expression, sexual orientation, disability, physical appearance, socioeconomic status, body size, ethnicity, nationality, level of experience, age, religion (or lack thereof), or other identity markers.

Read our full Code of Conduct.

contentful.net's People

Contributors

akzent avatar cf-allstar[bot] avatar chandankkrr avatar divinci avatar erikej avatar foobarwidget avatar freshrob avatar ghepting avatar jakobbacklund avatar jamiepollock avatar jerriep avatar jjolton-contentful avatar jonathansant avatar marcolink avatar mariobodemann avatar matt-hammond avatar mercedesb avatar mrcunninghamz avatar msm-agyemang avatar myoxocephalus avatar nholik avatar nteague22 avatar nwgallegos avatar ob1dev avatar olee avatar pfrendo avatar robert-msmg avatar roblinde avatar sethreidnz avatar technicaldogsbody avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

contentful.net's Issues

Installation issue

When I try and install the package into my solution I am getting the following error:

You are trying to install this package into a project that targets
'.NETFramework,Version=v4.5.2', but the package does not contain any assembly references or content files that are compatible with that framework.

I'm not able to change the .net version in my project.

GetEntriesAsync not always working after recent id/ref change

The new deserialization logic using $id/$ref has a flaw that makes the deserialization fail in some cases when there are multiple link-properties on the same entity.

The fault is in the ResolveLinks method which iterates through the properties in reverse order. This results in a JSON that can have a $ref before the corresponding $id.

The fix seems to be simply to reverse the iteration order.

I will attach a pull request with the fix and a test case shortly.

Can you merge properties by default locale?

I would like a way to merge properties with a default locale.

My scenario is the following:

TestContentType (English-Default)
{
Name: "Test",
Surname: "Test-English"
}

TestContentType (German)
{
Name: null,
Surname: "Test-German"
}

When I request german I would like this model to be returned

TestContentType (German)
{
Name: "Test",
Surname: "Test-German"
}

Now this can either be achieved by handling it within the SDK or by allowing me to query multiple locales at the same time... as currently I can only query one locale.

So I can use something like this

new QueryBuilder<T>().ContentTypeIs(contentType).LocalesAre(new List<string>() { defaultLocale, locale });

ResolveLinks throws NullReferenceException when select is used in query

The method ResolveLinks in the ContentfulClient throws whenever a select is used in a query string, because in that case the Contentful API doesn't return the sys.id property but only the fields that have been selected. Thus in line 267

var id = ((JValue) entryToken.SelectToken("$.sys.id")).Value.ToString(); entryToken.AddFirst(new JProperty( "$id", new JValue(id)));

throws a NullReferenceException.

It's hard to include an example without a proper contentful API connection but I hope you're able to reproduce this. Makes using the new contentful.aspnetcore package impossible for me at this point.

Example query string: ?include=2&content_type=mytype&order=-sys.updatedAt&select=fields.myfield

Cheers
Peter

JsonConvertor attribute prevents object population through GetEntriesByTypeAsync

I have a Term content type which has a reference to multiple Chapter content types through a Chapters field. The POCO class for Term has this:

public List<Chapter> Chapters { get; set; }

Per the documentation, I have this on the Chapter class definition:

[JsonConverter(typeof(EntryFieldJsonConverter))]
public class Chapter

This works when getting Term entries -- I also get the referenced Chapter entries, populated correctly.

However, somewhere else in the code, I just get all the Chapter entries by themselves, like this:

var chapters = myContentfulClient.GetEntriesByTypeAsync<Chapter>("chapter").Result.ToList();

chapters ends up to be a list of 16 null values. There are 16 chapters, so it found them all, but it didn't populate the objects with any information.

On a hunch, I removed the JsonConvertor attribute from the Chapter class definition, and it worked again -- now I got all 16 Chapter entries, populated correctly.

But now my Chapters reference from Term doesn't work.

The existence of the JsonConvertor attribute makes one situation work, and the other not. What am I doing wrong?

Missing or inaccessible entries should be skipped during deserialization

Currently, if you have a contentful entry that references another entity which no longer exists (e.g. was deleted). the deserialization routine will create an empty instance of the expected class.

For example, if you reference an asset and later delete the asset without updating its usages, you will get empty Asset-objects with all properties set to null. This can easily lead to bugs when code expects certain required properties to be filled. An example is the integrated ContentfulImageTagHelper which will throw a NullReferenceException if it encounters an Asset like this.

My suggestion is to skip such entries completely during deserialization, effectively converting them to "null" values, which makes them easier to handle in code.

Implement custom ReferenceResolver

There are situations where entries with referenced content can fail to deserialize correctly.

It cannot be assumed that the entire JSON structure is deserialized as the client is free to provide any class as a generic argument, thus only deserializing part of the fields. This means that if an $id reference is in a part that is not deserialized forthcoming $ref references will fail to deserialize.

Resolving deeply nested links to entries

When calling IContentfulClient.GetEntriesAsync<T> and using a Include(int) greater than the default of 1, I was expecting my references to be resolved into my object graph to that level also.

Say I have a Content Model like:

ContentTypeA
- String Field

ContentTypeB
- References Many ContentTypeA
- Another String Field

ContentTypeC
- References a Single ContentTypeA

ContentTypeD
- References Many ContentTypeB
- References Many ContentTYpeC

With corresponding POCOs like:

public class ContentTypeA
{
   public string Field { get; set; }
   public SystemProperties Sys { get; set; }
}

public class ContentTypeB
{
   public List<ContentTypeA> ContentTypeA { get; set; }   
   public string AnotherField { get; set; }
   public SystemProperties Sys { get; set; }
}

public class ContentTypeC
{
   public ContentTypeA ContentTypeA { get; set; } 
   public SystemProperties Sys { get; set; }
}

public class ContentTypeD
{
   public List<ContentTypeB> ContentTypeB { get; set; }   
   public List<ContentTypeC> ContentTypeC { get; set; }
   public SystemProperties Sys { get; set; }
}      

And then I call IContentfulClient.GetEntiresAsync<ContentTypeD> I get a list of ContentTypeDs where all my list properties are populated and the ContentTypeB.AnotherField property is populated too, but the list of ContentTypeAs on the ContentTypeBs have their Sys.Type properties containing Link with null for the ContentTypeA.Field.

If I use IContentfulClient.GetEntriesCollectionAsync all the linked and expected ContentTypeAs are on the ContentfulCollection.IncludedEntries, but the same behaviour is observed.

So, the question/issue is, should I be resolving those links myself or has this scenario not been baked into the client yet but is the expected behaviour when you've got out of beta?

Included assets are not deserialized

When querying entries which link to assets, my expectation would be that the assets will be deserialized automatically, just as it works with assets. However it seems that the automatic link resolution only works for entries and not for assets.

I believe the error is in the following lines in the GetEntriesAsync method:

            var includedLinks = json.SelectTokens("$.items..fields..sys").ToList();
            includedLinks.AddRange(json.SelectTokens("$.includes.Entry..fields..sys"));

As you can see, only entry-includes are considered, not asset-includes.

Is it possible to automatically populate a SystemProperties property in a POCO class?

I have a POCO class called Term. It is populating as expected.

Can I get a SystemProperties object populated? I'd like to do something like this:

public string Title { get; set; }
public string Body { get; set; }
public SystemProperties Sys { get; set; }

As I'm sure you're aware, this doesn't populate (Sys remains null). I know that I could do Entry<Term> to get this, but how reasonable is it to expect the API to reflect the existence of a SystemProperties property, and automatically populate that?

QueryBuilder dies with RuntimeBinderException on incorrect API key

If I try to access a space with an invalid API key, the API returns 404. QueryBuilder doesn't handle this gracefully, but obviously tries to parse the result. That leaves me with stack traces of this sort (async frames removed):

`RuntimeBinderException: Cannot perform runtime binding on a null reference

CallSite.Target(Closure , CallSite , object )
System.Dynamic.UpdateDelegates.UpdateAndExecute1<T0, TRet>(CallSite site, T0 arg0)
Contentful.Core.ContentfulClientBase+d__8.MoveNext()
Contentful.Core.ContentfulClientBase+d__14.MoveNext()
Contentful.Core.ContentfulClientBase+d__11.MoveNext()
Contentful.Core.ContentfulClientBase+d__10.MoveNext()
Contentful.Core.ContentfulClient+d__32.MoveNext()
Contentful.Core.ContentfulClient+d__14.MoveNext()
Contentful.Core.ContentfulClient+d__13.MoveNext()`

If I have an invalid API key, there's a graceful error message because it can't be converted to a bearer token, but a valid token for another space causes this.

Using this SDK in ASP.NET Framework 4.5

We have an existing project on ASP.NET Framework 4.5, how can we make use of this SDK, which is on ASP.Net Core? Alternatively, is there a version which targets .NET 4.5?

CreateEntryAsync CamelCasePropertyNamesContractResolver fails if field.Id isn't camelcase

The ContentfulManagementClient.CreateEntryAsync uses the CamelCasePropertyNamesContractResolver which causes the request to fail if the field in Contentful doesn't have camelcase ids because the CMA can't find any properties with a matching id.

I defined a content type via code where the Entry title field was "Title" (the id of the field was also "Title"). When trying to create an instance of this entry via the SDK, I received an exception about being unable to find a field with id 'title.' I tested changing the field id to 'title' and my request worked as expected.

I'm not sure the best way to resolve this. Add some validation requiring that the id of a field be camel case? Or remove that contract resolver and rely on the developer to send in their request correctly cased? Or make it case insensitive?

Support srcset in ContentfulImageTagHelper

One very nice feature of Contentful is the ability to get scaled versions of an image.

In HTML you can specify a "srcset" attribute on an element, so that the browser can decide what resolution it requires. For example a browser on a retina display will typically require double the resolution of a normal display.

If the ContentfulImageTagHelper would support parameters with multiple values (e.g. "widths"), then it could easily generate the srcset attribute.

E.G:

<contentful-image widths="new[] { 500, 1000, 2000 }" jpg-qualities="new[] { 80, 65, 50 }" asset="@this.Model.Image" format="Jpg"></contentful-image>

would generate something like:
<img src="http://basecontentful.url/image.jpg" srcset="http://basecontentful.url/image.jpg?w=500&quality=80 w500 http://basecontentful.url/image.jpg?w=1000&quality=65 w1000 http://basecontentful.url/image.jpg?w=2000&quality=50 w2000" />

Should the Contentful SDK expose cancellation tokens?

Are there valid uses cases where it would be helpful to have all of the Contentful API calls expose CancellationTokens?

For example:

var source = new CancellationTokenSource(1500);
var entry = await GetEntryAsync<Entry<dynamic>>("123", source.Token);

This would cancel the request if it for whatever reason took more than 1500 ms to complete.

Removing properties from QueryBuilder

Hi Rob,

We are currently trying to recurse through calls of GetEntriesAsync with a different skip parameter to retrieve all the entries that are above our limit.

Every time we loop through we would like to change the Skip() property to a new value as to give us the correct batch of entries. However when we use .Skip(int) it is adding a new skip property on top and throwing an error when we have multiple. We are not able to create a copy of the builder then add skip to that because it is a reference.

Would it be possible to remove properties or clone the querybuilder object?

Thanks,

David

Dependent assembly loading issues

Using VS2017, I created a new class library project (all projects discussed in this issue target 4.6.1) and installed the Nuget package like this:

Install-Package contentful.csharp -Version 0.5.1-alpha -Pre

I recreated the ContentfulGateway class (see #1).

I created a unit test project with a single test which called the ContentfulGateway.GetTermBySlug method (again, from #1). The test failed with an IOException because it couldn't load System.Diagnostics.DiagnosticSource, Version=4.0.0.0.

Thinking this may be some issue with the unit testing project specifically, I created a console application project. I attempted to call the same method from above, directly in Main. Execution failed with IOException because it couldn't load System.Net.Http, Version=4.1.1.0.

Are these issues with my environment, or issues with dependency definition in the Nuget package?

Better intellisense for webhooks

Add better intellisense for webhooks, there should be constants and stuff for common topics. Maybe even a few predefined Actions?

Implement Serialization in AssetJsonConverter

Current the AssetJsonConverter only supports reading JSON, but not writing it.

This is usually not a problem, since contentful.net is only parsing the JSON returned from the CMS. However quite often you want to save the models returned from the library in some other system. E.g. in our case we cache instances in redis. Other use cases might include storing objects in the user session or even serializing them to disk.

Now the problem is that the serialization uses the default JSON.NET serialization, but deserializing will always use the deserialization of the AssetJsonConverter since it is declared on the type. This will obviously crash as the deserialization format differs significantly from the default serialization layout created by JSON.NET.

An alternative would be to remove the AssetJsonConverter from the Asset type and add the converter manually during the deserialization process by using custom JsonSerializerSettings.

My preference would be to do both, so that the user can decide what serialization mechanism he wants to use. It might also be worth to check if there is a way to define the asset class in a way that does not require a custom converter at all.

Thank you!

Did format changed for fields property?

In your json files it is:

...
  "fields": {
    "productName": "SoSo Wall Clock",
    "slug": "soso-wall-clock",
...

but when I request entry now, it is more like this:

...
  "fields": {
    "productName": {
      "en-US": "SoSo Wall Clock"
    }
...

This complicates parsing json quite a bit in .net

CDA/CMA GetEntriesAsync for Entry<> doesn't resolve the includes

When using GetEntriesAsync<Entry<ContentType>> the includes are not resolved, but GetEntriesAsync<ContentType> does correctly resolve the includes.

This was happening with a field of type Array of references (not sure if it also happens for a singular reference).

MimeTypeValidator doesn't create expected Json object

Currently when using the MimeTypeValidator on a field in content type creation via code, the validation is added to the field but the mime type is not selected.

In CreateValidator(), the code should be changed from
return new { linkMimetypeGroup = MimeTypes.Select(c => c.ToString()), message = Message };
to
return new { linkMimetypeGroup = MimeTypes.Select(c => c.ToString().ToLower()), message = Message };

weak support for Xamarin.Forms PCL and NetStandrad

Hello there, I am using your SDK for my Xamarin.Forms Project. I will gladly share it when it is done.

The first issue I got, is that by default Contentful.csharp does not support PCL Library. This is a problem because, at this moment, when you create a Xamarin.Forms Project it creates a PCL Project and not .NetStandard. So the developer must upgrade to NetStandard from PCL which can be problematic.

The Second issue is that although Contentful.csharp is basically rest requests which would use Json.net and Microsoft Http Client, but I have to install the nuget package and use the client on Android Projects and iOS Projects which raise the need to use DI and containers to call it from the shared Project. Can you guys have a look at it ?

Should I keep this as one issue ? or make them into two issues ?

Fix bug where webhooks can't be assigned without validation

If you add a webhook like this:

app.UseContentfulWebhooks(a => {
                a.AddConsumer<Entry<dynamic>>(
                    "Very hook", 
                    "Entry", 
                    "*", 
                    (e) => {
                        var b = e;
                        return new { };
                    } );
                
            });

it fails obscurely, you need to add a WebhookAuthorization. This shouldn't be mandatory.

works if you add

a.WebhookAuthorization = s => true;

Add type for Location

When creating location fields in the management API it'd be nice to have a strong type to use instead of figuring out how to create a dynamic object yourself.

Allow custom JsonSerializerSettings inside the client

Currently all calls to JSON.NET within the library seem to use the default overloads which use the default JsonSerializerSettings.

Currently the only way to customize the deserialization process for contentful is to change the default serialization setings for JSON.NET (e.g. custom converters, $id/$ref support, etc.).

In our application we have lots of components and libraries which use JSON.NET for serialization and deserialization, so changing the default settings affects all of these as well.

It would be nice if contentful.net would support supplying custom SerializerSettings.

QueryBuilder.FieldEquals forces all field IDs to camelCase

Given that the Contentful web interface allows for e.g. PascalCase field identifiers, it seems a bit weird to force the property names to camelCase in the Query Builder, as this leads to failing queries. This happens regardless of whether one specifies a [JsonPropertyAttribute] on the property in question.

A workaround is to use FieldEquals($"field.{nameof(ClassName.PropertyName)}", value).

.NetCore support and release of package

I have seen that you have created a folder for .NetCore integration but I would also like to know if there are any plans to publish the nuget for it and continue working on it. Thanks

Are all of the dependencies required?

Hello,

For .net 4.6.1 applications, nuget installs a lot of dependencies, and some of the required updates such as System.Net.Http 4.1.1.0 cause incompatibilities with other libraries. Are all of these libraries really required?

Ignore Sys property when updating contentful

The models we deserialize Contentful responses into have a Sys property as advised by Robert. The SystemProperties deserialize into that without issue. (We have also removed all Entry<> wrappers from these objects.)

We're now trying to use the management API to update some data in Contentful and we're running into an issue where our Sys property isn't matched by a field in Contentful:

ERROR|An unexpected error occured while performing the get operation|No field with id "sys" found.[
{
"name": "unknown",
"path": [
"fields",
"sys"
]
}
]

Is there a way to ignore the Sys property as we send the object back to Contentful?

N.B. we are sending an Entry<> of our model, as the CreateOrUpdateEntryAsync seems to require one. We're setting Fields to our model and SystemProperties to our model's Sys property.

Any advice would be very much appreciated.

Thanks

Create Content Type - DisplayField not set

Given I a creating a content type using the .Net API with two fields, "id" and "title"
And I set the DisplayField to "title"
When I call CreateOrUpdateContentTypeAsync
Then the content type is created
And the DisplayField is null (should be "title")

Given I set the DisplayField via Contentful UI
And then call GetContentTypeAsync
And can see DisplayField is correctly returned set to "title"
When I pass the same content type to CreateOrUpdateContentTypeAsync
Then the DisplayField is reset to null (should be "title")

Assets linked to multiple entries will only be added to the first entry in the deserialized result

Steps to reproduce:

  1. Create a content type that has a Media field that allows multiple values
  2. Create an entry of that type and add a couple of linked assets (e.g. images)
  3. Duplicate the entry so that the same assets will be linked to both the old and the new entry
  4. Map the assets to a collection property in the C# code
  5. Request the entries with GetEntriesAsync

Expected result:

Both result entries have the same linked assets in the collection

Actual result:

The first result entry has the linked assets. The second entry (and presumably any further entries after that) has a collection of size 2, but the assets are nulls

Need Validations property on Schema

I am trying to programatically create ContentTypes using the .Net Management API SDK.
I need to create an Array of Links and would like to add a validator to restrict them to a specific ContentType - ie. at the Items/Schema level. This is not currently possible.
If I add the validation manually in the UI it appears as below:

      "items": {
        "type": "Link",
        "linkType": "Entry",
        "validations": [
          {
            "linkContentType": [
              "Market"
            ]
          }
        ]
      },
      "validations": []

I would like to be able to uncomment the code below ;-):

new ContentType
            {
                SystemProperties = new SystemProperties { Id = "test" },
                Name = "Test",
                Description = "Test content type",
                DisplayField = "title",
                Fields = new List<Field>
                {
                    new Field {Id="id", Name="Id", Required=true, Type="Symbol", Validations = new List<IFieldValidator> { new UniqueValidator() } },
                    new Field {Id="title", Name="Title", Required=true, Type="Symbol" },
                    new Field {Id="widgets", Name="Widgets", Type="Array", Items = new Schema {
                        Type = "Link",
                        LinkType ="Entry",
                        //Validations = new List<IFieldValidator> { new LinkContentTypeValidator("Market")} }
                    } }
                }
            

Need a way to hook code into the ContentfulClient pipeline, via events or alternative methods

TLDR: we need events (-ish).

One of the problems with developing a "seamless" API is that there are, well, no seams. And by "seams," I mean "places to inject code."

For example, I have some link resolution I need to do on my Term objects. In addition to processing the Markdown, I need to create some links, wiki-style. It's a unique use case, but not that unique, in the sense that it's not uncommon to need to do something post-population with any object store.

When I was doing this with the last API, all I had were the fields and had to populate the POCO myself in a constructor. But since you do the object population for me now, I've "lost" that opportunity to hook the code. I get a fully-populated object, almost magically, in a sense before I'm "ready" for it.

What I'd like to see is either a full-blown event model, like this:

ContentfulClient.OnAfterObjectPopulated += ResolveLinks

The one drawback here is that this is global to the client, where I might need different handlers for different classes. (In my example use case: Terms need to resolve links; Chapters do not.)

Or even just an interface, like this:

// This is a terrible interface name, I know...
public interface IHasAfterPopulatedMethod
{
   void OnAfterPopulated();
}

If my POCO implemented that interface, you'd call OnAfterPopulation for me at the correct time. The benefit of this is that this would be on a per-class basis.

Another, more wide-ranging, alternative might be a ContentfulEntry abstract class, from which my POCOs could inherit. It would have a set of events on it, inherited by my POCOs, which I could hook individually:

Term.OnAfterObjectPopulated += ResolveLinks

(Now that I think about it, this could have the SystemProperties property on it from #3 as well. Looking down the road, I think there are multiple instances where a base class for the POCOs would come in handy. Putting the SystemProperties on it now might be enough of an inducement to get developers doing it with their early code.)

Perhaps do both: (1) have events on ContentfulClient, and (2) have a ContentfulEntry abstract base class with inherited events for individual POCOs. This way, some code could be global, and other code would be per-class.

Loading asset for linked items

I ran into an issue I can't figure out how to solve. It's a pretty simple scenario: I have a content model for Team Member, which consist of name, e-mail, phone and a linked photo asset. Then I have a content model for Contact Page, consisting of a title, some text and a list of Team Member entries.

I try to load them like this:

var query = QueryBuilder.New()
    .ContentTypeIs("contactPage")
    .FieldEquals("fields.slug", "contact")
    .Include(6);

var entry = (await _contentful.GetEntriesAsync<Entry<ContactPage>>(query)).FirstOrDefault();

The ContactPage type has a List<Entry<TeamMember>>, and the TeamMember as a property of type Asset.

When loading it, I get the contact page, and the list of team member - but each of the team members does not include the Asset ProfilePicture - it's null.

When fetching as Entry<dynamic> and then serializing it to JSON I see that there is a link to the asset, but it's not fetched.

How can I "force" the client to fetch assets for linked content? I thought the Include(n) method should indicate to follow and fetch n-levels of linked items?

Serialization behaves differently when select is used in query

Hello again,

I stumbled upon another issue when using select statements in a query.
I understand that you implemented a way of making fields direct descendants of the root element in order to facilitate easy serialization.

While I think this is a nifty feature, it doesn't seem to work when using a select statement, because in that case the resulting response is not of type "Entry" but of type "Array" so in ContentfulClient line 230

if(grandParent["sys"] != null && grandParent["sys"]["type"]?.ToString() != "Entry")

will skip the restructuring of fields. That makes deserialization inconsistent, because if a select is used the resulting response will have a different structure although it's the same object, just with less properties. Thus now I need to have two c# objects. One for the contentful response with select query and one for the contentful response without select.

Do you think it would be possible to make this more consistent without side effects?

Cheers
Peter

"Method not found" on the client constructor

I wrote a static class for access:

public class ContentfulGateway
    {
        public static HttpClient httpClient;
        public static ContentfulClient client;

        static ContentfulGateway()
        {
            httpClient = new HttpClient();
            client = new ContentfulClient(httpClient, "[access token]", "[space id]");
        }

        public static Term GetTermBySlug(string slug)
        {
            var builder = new QueryBuilder().ContentTypeIs("term").FieldEquals("fields.slug", slug);
            return client.GetEntriesAsync<Term>(builder).Result.FirstOrDefault();
        }

    }

Here is a unit test:

        public void GetTermBySlug()
        {
            var result = ContentfulGateway.GetTermBySlug("content");
            Assert.AreEqual("content", result.Slug);
        }

It compiles, but the test fails with:

System.TypeInitializationException: The type initializer for 'FSBData.ContentfulGateway' threw an exception. ---> System.MissingMethodException: Method not found: 'Void Contentful.Core.ContentfulClient..ctor(System.Net.Http.HttpClient, System.String, System.String, Boolean)'.

So, it's failing in the static constructor of ContentfulGateway when I instantiate the client. Claiming "Method not found" on the constructor, which seems weird since it compiles...

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.