Extending Content Data Structures in Nikcio.UHeadless
Nikcio.UHeadless provides flexibility to extend and replace content data structures to accommodate your specific needs. This documentation outlines some examples of how you can extend the content data structures.
Example 1: Simple Content Model
- Create your content model by inheriting from
BasicContent
:
using Nikcio.UHeadless.Base.Basics.Models;using Nikcio.UHeadless.Base.Properties.Factories;using Nikcio.UHeadless.Content.Basics.Models;using Nikcio.UHeadless.Content.Commands;using Nikcio.UHeadless.Content.Factories;using Nikcio.UHeadless.ContentTypes.Basics.Models;using Nikcio.UHeadless.ContentTypes.Factories;using Umbraco.Cms.Core.Models.PublishedContent;
public class MyContent : BasicContent{ public string MyCustomValue { get; set; }
public MyContent(CreateContent createContent, IPropertyFactory<BasicProperty> propertyFactory, IContentTypeFactory<BasicContentType> contentTypeFactory, IContentFactory<BasicContent> contentFactory, IVariationContextAccessor variationContextAccessor) : base(createContent, propertyFactory, contentTypeFactory, contentFactory, variationContextAccessor) { MyCustomValue = "Custom Value"; }}
- Extend the query where you want the model to be present. In this example, we extend the
ContentAtRoot
query:
using Nikcio.UHeadless.Content.Queries;
public class MyContentAtRootQuery : ContentAtRootQuery<MyContent>{}
- Register the query in Nikcio.UHeadless:
.AddUHeadless(new(){ UHeadlessGraphQLOptions = new() { GraphQLExtensions = (IRequestExecutorBuilder builder) => { builder.UseContentQueries(); // Use this from v4.1.0+ (Only add one) builder.AddTypeExtension<MyContentAtRootQuery>(); return builder; }, },})
- Open
/graphql
and observe your new model for theContentAtRoot
query.
Example 2: Extended Content Model with Custom Property
- Create your property model by inheriting from
BasicProperty
:
using Nikcio.UHeadless.Base.Basics.Models;using Nikcio.UHeadless.Base.Properties.Commands;using Nikcio.UHeadless.Base.Properties.Factories;
public class MyProperty : BasicProperty{ public string MyString { get; set; }
public MyProperty(CreateProperty createProperty, IPropertyValueFactory propertyValueFactory) : base(createProperty, propertyValueFactory) { MyString = "My string"; }}
- Create your content model by inheriting from
BasicContent<TProperty>
:
using Nikcio.UHeadless.Base.Basics.Models;using Nikcio.UHeadless.Base.Properties.Factories;using Nikcio.UHeadless.Content.Basics.Models;using Nikcio.UHeadless.Content.Commands;using Nikcio.UHeadless.Content.Factories;using Nikcio.UHeadless.ContentTypes.Basics.Models;using Nikcio.UHeadless.ContentTypes.Factories;using Umbraco.Cms.Core.Models.PublishedContent;
public class MyContentWithMyProperty : BasicContent<MyProperty>{ public string MyCustomValue { get; set; }
public MyContentWithMyProperty(CreateContent createContent, IPropertyFactory<MyProperty> propertyFactory, IContentTypeFactory<BasicContentType> contentTypeFactory, IContentFactory<BasicContent<MyProperty, BasicContentType, BasicContentRedirect>> contentFactory, IVariationContextAccessor variationContextAccessor) : base(createContent, propertyFactory, contentTypeFactory, contentFactory, variationContextAccessor) { MyCustomValue = "Custom Value"; }}
- Extend the query where you want the model to be present. In this example, we extend the
ContentAtRoot
query:
using Nikcio.UHeadless.Content.Queries;
public class MyContentAtRootQueryWithMyProperty : ContentAtRootQuery<MyContentWithMyProperty>{}
- Register the query in Nikcio.UHeadless:
.AddUHeadless(new(){ UHeadlessGraphQLOptions = new() { GraphQLExtensions = (IRequestExecutorBuilder builder) => { builder.UseContentQueries(); // Use this from v4.1.0+ (Only add one) builder.AddTypeExtension<MyContentAtRootQueryWithMyProperty>(); return builder; }, },})
- Open
/graphql
and observe your new model for theContentAtRoot
query.
Example 3: Creating Content Model from Scratch
- Create your content model by inheriting from
Content<TProperty>
:
using System.Collections.Generic;using HotChocolate;using Nikcio.UHeadless.Base.Basics.Models;using Nikcio.UHeadless.Base.Properties.Factories;using Nikcio.UHeadless.Content.Commands;using Nikcio.UHeadless.Content.Models;
public class MyContentFromScratch : Content<BasicProperty>{ public string MyCustomValue { get; set; }
[GraphQLDescription("Gets the properties of the element.")] [UseFiltering] public virtual IEnumerable<BasicProperty?>? Properties => Content != null ? PropertyFactory.CreateProperties(Content, Culture, Segment, Fallback) : default;
public MyContentFromScratch(CreateContent createContent, IPropertyFactory<BasicProperty> propertyFactory) : base(createContent, propertyFactory) { MyCustomValue = "Custom Value"; }}
- Extend the query where you want the model to be present. In this example, we extend the
ContentAtRoot
query:
using Nikcio.UHeadless.Content.Queries;
public class MyContentAtRootQueryWithMyContentFromScratch : ContentAtRootQuery<MyContentFromScratch>{}
- Register the query in Nikcio.UHeadless:
.AddUHeadless(new(){ UHeadlessGraphQLOptions = new() { GraphQLExtensions = (IRequestExecutorBuilder builder) => { builder.UseContentQueries(); // Use this from v4.1.0+ (Only add one) builder.AddTypeExtension<MyContentAtRootQueryWithMyContentFromScratch>(); return builder; }, },})
- Open
/graphql
and observe your new model for theContentAtRoot
query.
Example 4: Extended Content Model with public access settings
- Create your access rule model:
using HotChocolate;
[GraphQLDescription("Represents an access rule for the restrict public access settings.")]public class AccessRuleModel{ public AccessRuleModel(string? ruleType, string? ruleValue) { RuleType = ruleType ?? string.Empty; RuleValue = ruleValue ?? string.Empty; }
[GraphQLDescription("Gets the type of protection to grant access to the content item.")] public string RuleType { get; set; } [GraphQLDescription("Gets the name of who has access to the content item.")] public string RuleValue { get; set; }}
- Create your Permissions model:
using System.Collections.Generic;using HotChocolate;
namespace Examples.Docs.Content.PublicAccessExample;
[GraphQLDescription("Represents a restrict public access settings of a content item.")]public class PermissionsModel{ public PermissionsModel() { AccessRules = new List<AccessRuleModel>(); }
[GraphQLDescription("Gets the url to the login page.")] public string? UrlLogin { get; set; }
[GraphQLDescription("Gets the url to the error page.")] public string? UrlNoAccess { get; set; }
[GraphQLDescription("Gets the access rules for the restrict public access settings.")] public List<AccessRuleModel> AccessRules { get; set; }}
- Create your content model by inheriting from
BasicContent<TProperty, TContentType, TContentRedirect, TContent>
:
using HotChocolate;using Microsoft.Extensions.Logging;using Nikcio.UHeadless.Base.Basics.Models;using Nikcio.UHeadless.Base.Properties.Factories;using Nikcio.UHeadless.Content.Basics.Models;using Nikcio.UHeadless.Content.Commands;using Nikcio.UHeadless.Content.Factories;using Nikcio.UHeadless.ContentTypes.Basics.Models;using Nikcio.UHeadless.ContentTypes.Factories;using Umbraco.Cms.Core.Models;using Umbraco.Cms.Core.Models.PublishedContent;using Umbraco.Cms.Core.Services;using Umbraco.Cms.Core.Web;using Umbraco.Extensions;
[GraphQLDescription("Represents an extended content item.")]public class CustomBasicContent : BasicContent<BasicProperty, BasicContentType, BasicContentRedirect, CustomBasicContent>{ private readonly IPublicAccessService _publicAccessService; private readonly IContentService _contentService; private readonly IUmbracoContextAccessor _context; private readonly ILogger<CustomBasicContent> _logger;
[GraphQLDescription("Gets the restrict public access settings of the content item.")] public PermissionsModel? Permissions { get; set; }
public CustomBasicContent(CreateContent createContent, IPropertyFactory<BasicProperty> propertyFactory, IContentTypeFactory<BasicContentType> contentTypeFactory, IContentFactory<CustomBasicContent> contentFactory, IVariationContextAccessor variationContextAccessor, IPublicAccessService publicAccessService, IContentService contentService, IUmbracoContextAccessor context, ILogger<CustomBasicContent> logger) : base(createContent, propertyFactory, contentTypeFactory, contentFactory, variationContextAccessor) { _publicAccessService = publicAccessService; _contentService = contentService; _context = context; _logger = logger;
if (createContent.Content == null) { _logger.LogWarning("Content is null"); return; }
IContent? content = _contentService.GetById(createContent.Content.Id);
if (content == null) { _logger.LogWarning("Content from content service is null. Id: {contentId}", createContent.Content.Id); return; }
PublicAccessEntry? entry = _publicAccessService.GetEntryForContent(content);
if (entry != null) { var cache = _context.GetRequiredUmbracoContext();
if (cache.Content == null) { _logger.LogWarning("Content cache is null on Umbraco context"); return; }
IPublishedContent? loginContent = cache.Content.GetById(entry.LoginNodeId); IPublishedContent? noAccessContent = cache.Content.GetById(entry.NoAccessNodeId);
Permissions = new PermissionsModel { UrlLogin = loginContent?.Url(), UrlNoAccess = noAccessContent?.Url() };
foreach (PublicAccessRule rule in entry.Rules) { Permissions.AccessRules.Add(new AccessRuleModel(rule.RuleType, rule.RuleValue)); } } }}
- Extend the query where you want the model to be present. In this example, we extend the
ContentAtRoot
query:
using Nikcio.UHeadless.Content.Queries;
public class CustomBasicContentContentAtRootQuery : ContentAtRootQuery<CustomBasicContent>{}
- Register the query in Nikcio.UHeadless:
.AddUHeadless(new(){ UHeadlessGraphQLOptions = new() { GraphQLExtensions = (IRequestExecutorBuilder builder) => { builder.UseContentQueries(); // Use this from v4.1.0+ (Only add one) builder.AddTypeExtension<CustomBasicContentContentAtRootQuery>(); return builder; }, },})
- Open
/graphql
and observe your new model for theContentAtRoot
query.
These examples demonstrate different ways to extend content data structures in Nikcio.UHeadless. Choose the method that best suits your requirements and customize the models and queries accordingly.