episerver

Customize API response for content delivery API


I am working on implementing content delivery API. One of the issue with the response is the list of unwanted fields that are not relevant for the front-end application. Here's an article from Optimizely to customize the data.

https://world.optimizely.com/documentation/developer-guides/archive/content-delivery-api/how-to-customize-api-to-change-data-returned-to-clients/how-to-customize-data-returned-to-clients/

The issue here is, CustomContentResultService class is not getting called.

The Episerver Version that I am working on is 11

[InitializableModule]
public class DependencyResolverInitialization : IConfigurableModule
{
    public void ConfigureContainer(ServiceConfigurationContext context)
    {
        //Implementations for custom interfaces can be registered here.
        context.ConfigurationComplete += (o, e) =>
        {                 

            //Register custom implementations that should be used in favour of the default implementations
            context.Services.AddTransient<IContentRenderer, ErrorHandlingContentRenderer>()
                .AddTransient<ContentAreaRenderer, XYZContentAreaRenderer>()
                .AddTransient<ContentResultService, CustomContentResultService>();
                
        };
        context.Services.Configure<ContentApiConfiguration>(config =>
        {
            config.Default()
                .SetMinimumRoles(string.Empty)
                .SetMultiSiteFilteringEnabled(false)
               .SetSiteDefinitionApiEnabled(true)
                .SetIncludeMasterLanguage(false)
               .SetFlattenPropertyModel(true)
                .SetIncludeNullValues(false)
               .SetValidateTemplateForContentUrl(false);
        });
    }

    public void Initialize(InitializationEngine context)
    {
        DependencyResolver.SetResolver(new ServiceLocatorDependencyResolver(context.Locate.Advanced));
    }

    public void Uninitialize(InitializationEngine context)
    {
    }

    public void Preload(string[] parameters)
    {
    }
}

CustomContentResultService class is exactly how it is implemented in

https://world.optimizely.com/documentation/developer-guides/archive/content-delivery-api/how-to-customize-api-to-change-data-returned-to-clients/how-to-customize-data-returned-to-clients/


Solution

  • Assuming you are using CMS 11 you want to look at ContentModelMapperBase.

    However, the serialization of fields outputted by the content delivery api will also follow common attributes like [JsonIgnore], e.g.

    [JsonIgnore]    
    [Display(Name="Ignore Me")] 
    public virtual XHtmlString IgnoredContent { get; set; }
    

    If you want full control of your Content Delivery API create an ExtendedContentModelMapper that inherit ContentModelMapperBase and implement the TransformContent method.

    public class ExtendedContentModelMapper : ContentModelMapperBase
    {
        public ExtendedContentModelMapper(
            IContentTypeRepository contentTypeRepository,
            ReflectionService reflectionService,
            IContentModelReferenceConverter contentModelService,
            IUrlResolver urlResolver,
            IEnumerable<IPropertyModelConverter> propertyModelConverters,
            IContentVersionRepository contentVersionRepository,
            ContentLoaderService contentLoaderService) 
            : base(
                  contentTypeRepository,
                  reflectionService,
                  contentModelService, 
                  urlResolver, 
                  propertyModelConverters,
                  contentVersionRepository, 
                  contentLoaderService)
        {
            // other injections
        }
    
        public override ContentApiModel TransformContent(IContent content, bool excludePersonalizedContent, string expand)
        {
            var contentModel = base.TransformContent(content, excludePersonalizedContent, expand);
    
            // magic stuff
    
            contentModel.Properties.Remove("IgnoredContent");
            contentModel.Properties.Remove("Title");
            contentModel.Properties.Remove("WhateverProperites");
            contentModel.Properties.Add("FakeProperty", "This property is created virtually");
    
            if(content is ArticlePage) 
            {
                // code
            }
    
            return contentModel;
        }
    }
    

    Don't forget to inject the contentModelMapper E.g. context.Services.AddTransient<IContentModelMapper, ExtendedContentModelMapper>();