Customize API response for content delivery API

274 Views Asked by At

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/

1

There are 1 best solutions below

5
Eric Herlitz On BEST ANSWER

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>();