Reputation: 1572
I am having issue with kentico kontent a bit. Basically when I call _deliveryClient.GetItemsAsync<object>
I am getting null even though the json below is being brought back.
{
"item": {
"system": {
"id": "0b9e6cf0-a9aa-422b-9e14-1576adfb6324",
"name": "Home",
"codename": "home",
"language": "default",
"type": "home",
"sitemap_locations": [],
"last_modified": "2020-04-30T17:16:48.706142Z"
},
"elements": {
"header": {
"type": "text",
"name": "Header",
"value": "This is my name"
},
"description": {
"type": "text",
"name": "Description",
"value": ".net specialist"
},
"background": {
"type": "modular_content",
"name": "Background",
"value": [
"universe"
]
}
}
},
"modular_content": {
"universe": {
"system": {
"id": "a8898eef-0f4b-4646-af72-c0a1e41ab165",
"name": "Universe",
"codename": "universe",
"language": "default",
"type": "background",
"sitemap_locations": [],
"last_modified": "2020-04-30T17:19:02.9586245Z"
},
"elements": {
"user_vid_or_imag": {
"type": "multiple_choice",
"name": "User Vid or Imag",
"value": [
{
"name": "Video",
"codename": "video"
}
]
},
"background_item": {
"type": "asset",
"name": "Background Item",
"value": [
{
"name": "Time Lapse Video Of Night Sky.mp4",
"description": null,
"type": "video/mp4",
"size": 2076845,
"url": "https://preview-assets-us-01.kc-usercontent.com:443/..."
}
]
}
}
}
}
}
However, if I use the concretion I get the Model back as expected. This is an issue even for members of a class e.g. linked items. The problem is that we have lots of models so we have opted to use the ModelGenerator kentico provides. The thing is we cannot tell the the Generator not to generate some of the objects so it will overwrite everything even though we only want to update one model. So this means I cannot go into every model and change the to some concretion because that will be overwritten.
The documentation says that should always work so is this a bug? or am I making a mistake somewhere.
Upvotes: 0
Views: 124
Reputation: 7696
You should always use the model generator in combination with partial
classes. To enable customization via partial classes use the --generatepartials true
switch. This will output something like:
public partial class Article
{
public const string Codename = "article";
public const string TitleCodename = "title";
public const string BodyCopyCodename = "body_copy";
public const string RelatedArticlesCodename = "related_articles";
public string Title { get; set; }
public IRichTextContent BodyCopy { get; set; }
public IEnumerable<object> RelatedArticles { get; set; }
}
public partial class Article
{
// Space for your customizations
public IEnumerable<Article> ArticlesTyped => RelatedArticles.Cast<Article>();
}
Feel free to suggest improvements for the code generator at https://github.com/Kentico/kontent-generators-net/issues/new/choose
The most probable reason why your code doesn't work at the moment is that you haven't registered the implementation of the ITypeProvider
interface. You can do so by adding it to the DI container (IServiceCollection
):
services
.AddSingleton<ITypeProvider, CustomTypeProvider>();
.AddDeliveryClient(Configuration);
or by passing it to the DeliveryClientBuilder
CustomTypeProvider customTypeProvider = new CustomTypeProvider();
IDeliveryClient client = DeliveryClientBuilder
.WithProjectId("975bf280-fd91-488c-994c-2f04416e5ee3")
.WithTypeProvider(customTypeProvider)
.Build();
as described in the docs. You can either generate the CustomTypeProvider
by the model generator utility or implement it by hand. It should look similar to this:
public class CustomTypeProvider : ITypeProvider
{
private static readonly Dictionary<Type, string> _codenames = new Dictionary<Type, string>
{
// <CLI type, model codename in Kontent>
{typeof(Article), "article"}
};
public Type GetType(string contentType)
{
return _codenames.Keys.FirstOrDefault(type => GetCodename(type).Equals(contentType));
}
public string GetCodename(Type contentType)
{
return _codenames.TryGetValue(contentType, out var codename) ? codename : null;
}
}
Alternatively, you can specify the type when calling GetItemsAsync()
in the following way: _deliveryClient.GetItemsAsync<Article>()
but this will resolve only the 1st level type. Any nested models will be null
because the SDK won't know how to resolve them (that's what the ITypeProvider
is for). So I'd avoid this.
Upvotes: 3