Loading...

Last updated: Oct 30 2018

Area: Content Delivery API Applies to versions: 2 and higher

Serialization

This document summarizes how the Content Delivery API serializes data returned to clients.

In this topic

How it works

The Content Delivery API defines two concepts, ContentApiModel and PropertyModel, which play a role as data transform objects for the serialization process. Basically, data is transformed to those models before being returned as the request result. The main serialization flow is illustrated by the diagram below.

The workflow should be as follows:

    • You make a request to an endpoint to query data.
    • The request is handled by components (filter, controllers, services, etc) and assumes that the expected data is retrieved in forms of IContent, IEnumerable<IContent>, or Errors.

IContent instances are transformed to ContentApiModel.

    • The properties of IContent are migrated to ContentApiModel.
    • The PropertyDataCollection of IContent is converted to a list of PropertyModel and then migrated to ContentApiModel
  • ContentApiModel is wrapped in ContentApiResult. Then, the serializer of ContentDeliveryApi serializes everything into Json and returns it.

This table maps properties between ContentData and ContentApiModel:

ContentApiModel

PageData

ContentLinkContentModelReference ContentLink: ContentReference
Name:   string Namestring
ParentLink:  ContentModelReference ParentLinkContentReference
ContentTypeList<string> ContentTypeID: int
LanguageLanguageModel LanguageCultureInfo
ExistingLanguagesList<LanguageModel> ExistingLanguageIEnumerable<CultureInfo>
MasterLanguage: LanguageModel MasterLanguageCultureInfo
RouteSegmentstring URLSegmentstring
Urlstring LinkURLstring
ChangedDateTime? ChangedDateTime
Created DateTime? Created: DateTime
StartPublishDateTime? StartPublishDateTime?
StopPublishDateTime? StopPublish DateTime?
Saved: DateTime? SavedDateTime
Statusstring Status:   VersionStatus
PropertiesIDictionary<string,object> Property:   PropertyDataCollection

Main base classes/interfaces for model serialization

Below are the base classes/interfaces for model serialization.

3.Serialization.png

IPropertyModel

This is the most basic Interface that needs to be implemented according to the default PropertyModelConverter (see below). It only contains two properties:

Type

Name

Description

string  

Name

The name of Content Api Property Model, usually the name of Episerver Property type

string  

PropertyDataType

The name of the Episerver PropertyData

PropertyModel<TValue,TType>

For convenience, ContentDelivery has a base class for the IPropertyModel interface that is EPiServer.ContentApi.Core.Serialization.Models.PropertyModel<TValue,TType>, where TValue is the value should be ouputed in JSON and TType is the type of PropertyData.

For example, the PropertyNumber is represented by NumberPropertyModel. The NumberPropertyModel has a Value (the numeric value of property) and a PropertyDataType which usually is the name of the value type (in this case "PropertyNumber").

/// <summary>
/// Mapped property model for <see cref="PropertyNumber"/>
/// </summary>
public class NumberPropertyModel : PropertyModel<int?, PropertyNumber>
{
	public NumberPropertyModel(PropertyNumber propertyNumber) : base(propertyNumber)
	{
		Value = propertyNumber.Number;
	}
}

IPersonalizableProperty

If the output of the property depends on personalization, implement the IPersonalizableProperty. The interface only requires a Property called ExcludePersonalizedContent which used to determine if Personalized content should be excluded when retrieving content. By default, property models of ContentArea, ContentReference, ContentReferenceList, and LinkCollection implement this interface. ContentDeliveryAPI also has a base class that is EPiServer.ContentApi.Core.Serialization.Models.PersonalizablePropertyModel<TValue, TType>  where TValue is the value that should be outputed in your JSON, and TType is the type of PropertyData.

IExpandableProperty

This interface is used for properties where you can return a simplified set of data for the initial API Request, so that the server can make further requests to the database to dig deeper into the data. By default, the following property types can be expanded: ContentArea, ContentReference, ContentReferenceList, and LinkCollection.

IPropertyModelConverter

This interface is responsible for mapping data between PropertyData and PropertyModel. The default implementation  DefaultPropertyModelConverter uses reflection to automatically map PropertyData with the corresponding PropertyModel.

[JsonIgnore]

If you have properties that you do not want to be included in the JSON output, just decorate it with the JsonIgnore attribute.

Custom property models

Custom property models can be created to customize how existing PropertyData implementations are converted and serialized in the Content Delivery API or to support custom property types in your solution.

In order to create a custom property model, create a class that inherits from EPiServer.ContentApi.Core.Serialization.Models.PropertyModel and set the Value property in your constructor. It is possible to map your property type to any class, as long as it is serializable and can be properly indexed into Episerver Find.

Example: The following custom property model forces all PropertyLongString instances to lowercase.

public class LowercaseLongStringPropertyModel : PropertyModel<string, PropertyLongString>
{
    public LowercaseLongStringPropertyModel(PropertyLongString propertyLongString) : base(propertyLongString)
    {
        if (propertyLongString != null)
        {
            Value = propertyLongString.ToString().ToLower();
        }
    }
}

Along with EPiServer.ContentApi.Core.Serialization.Models.PropertyModel, custom property models can also inherit from EPiServer.ContentApi.Core.Serialization.Models.PersonalizablePropertyModel. This class is used when custom property models contain data that is dependent on Personalization. It adds an additional constructor parameter, excludePersonalizedContent, which allows you to implement logic in your property model to set the Value property differently in personalized vs. non-personalized contexts.

Registering custom property models

In order for your custom property models to take effect, you need to create a custom implementation of IPropertyModelConverter. The implementation of IPropertyModelConverter has a collection of EPiServer.ContentApi.Core.Serialization.Models.TypeModel called ModelTypes, which maintains a map of which PropertyData instances that the converter is capable of handling.

The simplest method of adding a custom converter is to extend the default one, DefaultPropertyModelConverter, and override the SortOrder and ModelTypes properties.

Example: The following handler registers the LowercaseLongStringPropertyModel from the above example, with a SortOrder higher than the default handler (SortOrder = 0), ensuring that the custom converter is used for all Long String properties.

[ServiceConfiguration(typeof(IPropertyModelConverter), Lifecycle = ServiceInstanceScope.Singleton)]
public class LowercaseLongStringPropertyModelConverter : DefaultPropertyModelConverter
{
    public LowercaseLongStringPropertyModelConverter()
    {
        ModelTypes = new List<TypeModel>
            {
                new TypeModel {
                    ModelType = typeof(LowercaseLongStringPropertyModel), ModelTypeString = nameof(LowercaseLongStringPropertyModel), PropertyType = typeof(PropertyLongString)
                }
            };
    }

    public override int SortOrder { get; } = 100;
}

In some cases, a full implementation of IPropertyModelConverter may be preferable, such as when custom logic is required to choose between different PropertyModel implementations. In that case, your custom converter must also implement HasPropertyModelAssociatedWith, which verifies, based on the provided PropertyData, that the implementation of IPropertyModelConverter is able to handle the provided type. In addition, your custom converter must also implement ConvertToPropertyModel method, which creates and returns any instances of your custom property models based on the provided instance of PropertyData.


Do you have feedback on this documentation? Send an email to documentation@episerver.com. For development-related questions and discussions, refer to our Forums on https://world.episerver.com/forum/