Search code examples
contentfulheadless-cms

Contentful .NET SDK Query Failures


Update 1 9.July.2020: At least two issues. Sorry, I can't get the editor to format the text properly.

  1. The field names need to have a fields. prefix.

    QueryBuilder queryBuilder = QueryBuilder.New.FieldExists("fields.myurl", true).FieldEquals("fields.myurl", "/");

  2. It seems necessary to iterate content types.

    https://cdn.contentful.com/spaces/qjiunow8a0ig/entries?fields.myurl[exists]=true&fields.myurl=%2F

    Unhandled exception. Contentful.Core.Errors.ContentfulException: A Content Type ID is required. When querying for Entries and involving fields you need to limit your query to a specific Content Type. Please send a Content Type ID (not the name) as the URI query parameter "content_type" at Contentful.Core.ContentfulClientBase.CreateExceptionForFailedRequest(HttpResponseMessage res) in C:\temp\deliverystack\Contentful.Core\ContentfulClientBase.cs:line 142 at Contentful.Core.ContentfulClientBase.EnsureSuccessfulResult(HttpResponseMessage response) in C:\temp\deliverystack\Contentful.Core\ContentfulClientBase.cs:line 320 at Contentful.Core.ContentfulClientBase.SendHttpRequest(HttpRequestMessage request, CancellationToken cancellationToken) in C:\temp\deliverystack\Contentful.Core\ContentfulClientBase.cs:line 264 at Contentful.Core.ContentfulClientBase.SendHttpRequest(String url, HttpMethod method, String authToken, CancellationToken cancellationToken, HttpContent content, Nullable1 version, String contentTypeId, String organisationId, List1 additionalHeaders) in C:\temp\deliverystack\Contentful.Core\ContentfulClientBase.cs:line 257 at Contentful.Core.ContentfulClient.Get(String url, CancellationToken cancellationToken) in C:\temp\deliverystack\Contentful.Core\ContentfulClient.cs:line 654 at Contentful.Core.ContentfulClient.GetEntries[T](String queryString, CancellationToken cancellationToken) in C:\temp\deliverystack\Contentful.Core\ContentfulClient.cs:line 188 at Contentful.Core.ContentfulClient.GetEntries[T](QueryBuilder`1 queryBuilder, CancellationToken cancellationToken) in C:\temp\deliverystack\Contentful.Core\ContentfulClient.cs:line 171 at cfclt.Program.Main(String[] args) in C:\temp\deliverystack\cfclt\Program.cs:line 33

So this works:

QueryBuilder<Entry> queryBuilder = QueryBuilder<Entry>.New.ContentTypeIs("firstContentType").FieldExists("fields.url", true).FieldEquals("fields.url", "/");

I guess I will iterate the content types and create threads to query.

Original Thread:

I would like to use the Contentful .NET SDK (https://www.contentful.com/developers/docs/net/) to implement the content delivery tier for a web application.

One of my first issues is how to map the incoming HTTP request to an entry in Contentful without storing any relevant configuration in the content delivery tier. I want to pass a URL and have the SDK return a hydrated object of the appropriate type.

I put a text field named URL in my entries that should have URLs. I want to query all content types to find any Entries that have a specific value in that URL field.

I tried a few queries, but always get exceptions:

QueryBuilder<Entry> queryBuilder = QueryBuilder<Entry>.New.ContentTypeIs("firstContentType").FieldExists("url", true).FieldEquals("url", "/");
ContentfulCollection<Entry> entries = client.GetEntries(queryBuilder).GetAwaiter().GetResult();

Unhandled exception. Contentful.Core.Errors.ContentfulException: The query you sent was invalid. Probably a filter or ordering specification is not applicable to the type of a field.[
  {
    "name": "unknown",
    "path": [
      "url"
    ],
    "details": "The path \"url\" is not recognized"
  }
]
   at Contentful.Core.ContentfulClientBase.CreateExceptionForFailedRequest(HttpResponseMessage res) in C:\temp\deliverystack\Contentful.Core\ContentfulClientBase.cs:line 142
   at Contentful.Core.ContentfulClientBase.EnsureSuccessfulResult(HttpResponseMessage response) in C:\temp\deliverystack\Contentful.Core\ContentfulClientBase.cs:line 320
   at Contentful.Core.ContentfulClientBase.SendHttpRequest(HttpRequestMessage request, CancellationToken cancellationToken) in C:\temp\deliverystack\Contentful.Core\ContentfulClientBase.cs:line 264
   at Contentful.Core.ContentfulClientBase.SendHttpRequest(String url, HttpMethod method, String authToken, CancellationToken cancellationToken, HttpContent content, Nullable`1 version, String contentTypeId, String organisationId, List`1 additionalHeaders) in C:\temp\deliverystack\Contentful.Core\ContentfulClientBase.cs:line 257
   at Contentful.Core.ContentfulClient.Get(String url, CancellationToken cancellationToken) in C:\temp\deliverystack\Contentful.Core\ContentfulClient.cs:line 654
   at Contentful.Core.ContentfulClient.GetEntries[T](String queryString, CancellationToken cancellationToken) in C:\temp\deliverystack\Contentful.Core\ContentfulClient.cs:line 188
   at Contentful.Core.ContentfulClient.GetEntries[T](QueryBuilder`1 queryBuilder, CancellationToken cancellationToken) in C:\temp\deliverystack\Contentful.Core\ContentfulClient.cs:line 171

I am relatively certain that there is an entry of firstContentType with a value of / in its URL field. What am I doing wrong?

Why/how can it be so hard to do something so basic with a headless CMS? See this; it's like a rabbit hole that I don't have time to explore.

https://www.contentfulcommunity.com/t/how-to-query-on-multiple-content-types/473/10

If needed, I would not mind iterating the content types, but I'm not sure that it is worth the effort if query doesn't work anyway?


Solution

  • You need to specify the entire path to the field you're filtering on. So .FieldExists("fields.url", true).FieldEquals("fields.url", "/") should do the trick.