Discover the platform
Several common concepts and conventions apply throughout the Optimizely Community (formerly Social) API. An understanding of these strategies is helpful in discovering the tools available to you.
Services
The primary interaction point with the Optimizely Community API is through service classes, each implementing an interface following the naming convention I{Feature-Name}Service. Examples include:
ICommentServiceIRatingServiceIGroupService
For Optimizely Content Management System (CMS) sites with the feature's site integration package installed, you can get an instance of a service from the inversion of control (IoC) container.
Example
var commentService = EPiServer.ServiceLocation.ServiceLocator.Current.GetInstance<ICommentService>();For non-Optimizely CMS sites, you can get an instance of a service from the default factory classes provided within the package.
Example
var factory = new EPiServer.Social.Moderation.Factories.DefaultWorkflowServiceFactory();
var workflowService = factory.Create();Data models
Data models consumed and returned by the Community API's services are found under the "core" namespace for each platform feature, following the convention EPiServer.Social.{Feature-Name}.Core. For example:
EPiServer.Social.Comments.CoreEPiServer.Social.Ratings.Core
Exceptions
Exceptions thrown by the Community API's services are located in the Core namespace (EPiServer.Social.{Feature-Name}.Core) for feature-specific exceptions, and in EPiServer.Social.Common for shared platform exceptions.
Platform exceptions
The Optimizely Community API features share several exception types to communicate general platform error situations.
SocialAuthenticationException
A SocialAuthenticationException is thrown when a request is deemed unauthentic.
This error most commonly occurs when:
- The application's configuration is missing one or more of its authentication settings.
- The application's configuration contains inaccurate authentication settings.
- The application's server time is inaccurate.
For information regarding configuration and authentication, see "Get connected" in Install Optimizely Community.
MaximumDataSizeExceededException
A MaximumDataSizeExceededException is thrown when a request exceeds the platform's size restriction of 10 kilobytes for social content.
This restriction applies to any given social entity, including native properties, optional extension data, and any overhead.
For example, consider a simple comment containing an author, body, and parent reference. Consider that you also composed this comment with custom extension data. The content associated with each of those native comment properties and the extension data contribute to the total size of the request.
The platform does not explicitly restrict the amount of content associated with any individual property of a social content model. This lets you prioritize content size for native content models versus custom extension data.
NoteApplications should enforce content limits to minimize this exception.
RateLimitExceededException
A RateLimitExceededException is thrown when an application issues too many requests over a short period. All requests are tallied and compared against the rate limit. When an application exceeds the rate limit, the Optimizely Community API stops processing requests until a certain time has elapsed (a "request interval").
The exception provides additional information to help regulate the application's request rate. That information includes:
RequestInterval– The length of time in which requests are tallied.RequestsIssued– The number of requests already issued in the request interval.RequestLimit– The maximum number of requests allowed in a given request interval.RetryAfter– The time remaining until the application may resume issuing requests.
If your application regularly encounters this exception, consider:
- Optimize your code to minimize unnecessary API calls.
- Cache frequently accessed data.
- Actively regulate the application's request rate to ensure the application never encounters the issue.
- Implement logic to pause and retry requests after reaching the limit.
SocialCommunicationException
A SocialCommunicationException is thrown when a request encounters a fundamental communication issue.
This error most commonly occurs when:
- The application cannot connect or communicate with Optimizely Community API cloud services.
- A request from the application exceeds the configured timeout.
SocialException
A SocialException is thrown when a request encounters an unexpected error scenario. The exception contains a message, status code, error code, and additional reasoning to describe the error.
This error most commonly occurs when:
- The application's configuration is missing or malformed.
- The platform encountered an unexpected service error.
Feature exceptions
Individual services may also throw exceptions unique to the feature they support. Details can be found in the documentation for each API.
Reference and IDs
The Optimizely Community API identifies data by Id and Reference, with important semantic distinctions. See also: Work with Optimizely Community API References.
Ids
Id classes are specific to a feature's entities ({Feature-Name}Id convention), with internally-generated values used to distinguish individual entities. Examples include:
CommentIdGroupIdWorkflowId
They are accepted by services for retrieving specific data instances.
Reference
The Reference class identifies users or resources outside the platform, establishing relationships between social content and external entities.
The developer defines the value within a reference class. It contains the information necessary to identify or classify the resource or user to which social content is related.
The platform provides a Reference class that is used to identify any target entity in your application. For example, a resource, like Optimizely CMS content, or a product or a user, like an Optimizely CMS user.
Best practices for defining references
Ensure your reference scheme is:
- Capable of uniquely identifying entities.
- Interpretable by your application.
- Robust for future enhancements.
Consider factors like: Platform, Provider, Classification, Categorization, and Facets. A URI or similar namespace scheme is recommended.
Example for ecommerce content:
resource://optimizely/commerce/{product-identifier}/{variant-identifier}/{facet-identifier}Criteria
The Optimizely Community API services allow retrieval of custom result sets using criteria. A Criteria<TFilter> class encapsulates specifications for retrieving a collection of results.
Filter
The TFilter type parameter identifies the class encapsulating filter specifications. The Filter property accepts an instance of this class to refine a result set.
PageInfo
The PageInfo property accepts an instance of a class defining pagination specifications:
- Page size: Maximum number of results (default 10 if not specified, must be >= 0).
- Page offset: Zero-based index to start retrieving results (must be >= 0).
- CalculateTotalCount: Specifies if a total result count should be calculated. If
true, theTotalCountproperty onResultPagewill be populated; otherwise, it defaults to -1.
Best practices for paginating results
Large page sizes or deep offsets can negatively impact performance. Balance request size, volume, and user experience. Retrieving TotalCount when not needed adversely affects return time.
OrderBy
The OrderBy property accepts a collection of SortInfo rules describing how to sort the result set.
SortInfo identifies the field and direction for sorting.
A subset of fields on data models is available for sorting, exposed statically on classes named {Feature-Name}SortFields (e.g., CommentSortFields, RatingSortFields).
Sorting rules are processed in order, with subsequent rules acting as fallbacks for matching values.
Best practices for sorting results
Specify fallback sorting rules if consistency in result ordering is important, especially when navigating multiple pages. Sorting of string values is based on Unicode value; standardize data in code and store as duplicate property on extension data if alternative ordering is required.
Result sets
Services with bulk retrieval capabilities deliver results in a paginated fashion, represented by a ResultPage<T> class.
Results
The T type parameter identifies the model for the returned data (e.g., Comment, Rating). The Results property gets the collection of individual result items.
TotalCount
The TotalCount property provides the total count of items from the query. It is calculated only if CalculateTotalCount in PageInfo is set to true. If CalculateTotalCount is false, TotalCount is -1.
Info
The Info property refers to the paging specifications used when the request was issued.
HasMore
The HasMore property is a boolean indicating if more items exist beyond the current page. This helps determine if an additional query with an incremented PageOffset would return more results.
Composites
The Optimizely Community API supports data extensibility by allowing native entities to be composed with custom data models, known as Composites.
What is a composite?
A Composite represents a pairing of a native platform entity and its associated extension data. Extension data is a .NET class defined within your application to capture additional details.
Define extension data
Extension data is a .NET class for additional details. Considerations:
- Queryability: Design for filtering and sorting by primitive value types within extension data.
- Maintainability: Anticipate future enhancements and changes.
- Performance: Keep extension data light.
Constraints for extension data classes:
- Public, parameter-less constructor.
- No nested data in a polymorphic manner (e.g., child as the
Objecttype). - No self-references or referential loops.
- Class name, assembly names, and namespaces must remain stable.
- Minimize size to avoid exceeding platform size restrictions.
Additional caveats:
DateTimevalues are stored and returned as UTC.DateTimeprecision is up to the millisecond.Decimaltype is not supported; stored asdoubleand subject to rounding errors.
Composite criteria
Services supporting Composites provide methods for retrieving them, accepting CompositeCriteria<TFilter, TExtension>. This class extends Criteria, incorporating its capabilities while adding enhancements.
ExtensionFilter
The TExtension type parameter implicitly filters for composites with extension data of this type. The ExtensionFilter property accepts a Boolean expression (represented as a tree structure) to filter by values in your extension data.
IncludeSubclasses
A boolean indicating whether to include items where TExtension appears anywhere in the type hierarchy of their associated extension data (true by default), or only explicit TExtension types (false).
Filter composites
Filter Expressions are Boolean expressions (tree structures) used to filter Composites by values in their extension data. The FilterExpressionBuilder<TExtension> class provides methods and operator overloads for constructing these expressions.
Boolean operators can compare fields of String, Boolean, Int, Long, Double, DateTime.
Example of Filter Expression construction:
var luckyNumberOf7 = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.LuckyNumber).EqualTo(7);
var bornBefore1990 = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.Birthday).LessThan(new DateTime(1990, 1, 1));
var combinedExpression = FilterExpressionBuilder<MyCommentExtension>.And(luckyNumberOf7, bornBefore1990);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
ExtensionFilter = combinedExpression
};Best practices for defining filter expressions
- Minimize complexity and depth for optimal performance.
- Changes to extension data classes may result in malformed expressions.
- Malformed expressions can lead to unexpected or empty results.
Filter expressions
The examples for each filter expression below assume the following comment extension:
public class MyCommentExtension {
public int LuckyNumber {
get;
set;
}
public List<string> FavoriteTeams {
get;
set;
}
public DateTime Birthday {
get;
set;
}
}Any expression
Use the Any expression to filter both single-value and multi-value extension fields by a list of values. As an example of using the Any expression with a single-value extension field, assume that you want to read all comments for which the single-value LuckyNumber extension field matches any of three drawn lucky numbers. The following code shows how this is done with the Any expression:
var drawnLuckyNumbers = new List<long>{3, 7, 9};
var commentsWithDrawnLuckyNumbers = FilterExpressionBuilder<MyCommentExtension>.Field(ext => ext.LuckyNumber).Any(drawnLuckyNumbers);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
ExtensionFilter = commentsWithDrawnLuckyNumbers
};As an example of using the Any expression with a multi-value extension field, assume that you want to read all comments for which the multi-value favoriteTeams extension field contains either "New England Patriots" or "Boston Red Sox". The following code shows how this is done with the Any expression.
var mostFavoriteTeams = new List<string>{"New England Patriots", "Boston Red Sox"};
var commentsWithMostFavoriteTeams = FilterExpressionBuilder<MyCommentExtension>.Field(ext => ext.FavoriteTeams).Any(mostFavoriteTeams);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
ExtensionFilter = commentsWithMostFavoriteTeams
};Contains expression
The Contains expression can be used to filter both single-value and multi-value extension fields by a single value. As an example of using the Contains expression with a single-value extension field, assume that you want to read all comments for which the single-value LuckyNumber extension field matches drawn lucky number 7. The following code shows how this is done with the Contains expression:
var luckyNumber = 7;
var commentsWithLuckNumber = FilterExpressionBuilder<MyCommentExtension>.Field(ext => ext.LuckyNumber).Contains(luckyNumber);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
ExtensionFilter = commentsWithLuckNumber
};As an example of using the Contains expression with a multi-value extension field, assume that you want to read all comments for which the multi-value favoriteTeams extension field contains "Boston Celtics". The following code shows how this is done with the Contains expression.
var favoriteTeam = "Boston Celtics";
var commentsWithFavoriteTeam = FilterExpressionBuilder<MyCommentExtension>.Field(ext => ext.FavoriteTeams).Contains(favoriteTeam);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
ExtensionFilter = commentsWithFavoriteTeam
};EqualTo expression
The EqualTo expression is used to filter documents by an extension field whose value equals a given value. The EqualTo expression in the following example will match any comments with a Birthday on new year 2000.
var newYear2000 = new DateTime(2000, 1, 1);
var commentsWithMatchingBirthday = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.Birthday).EqualTo(newYear2000);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
ExtensionFilter = commentsWithMatchingBirthday
};LessThanOrEqualTo expression
The LessThanOrEqualTo expression filters documents by an extension field whose value is less than or equal to a given value. The LessThanOrEqualTo expression in the following example will match any comments with a Birthday on or before new year 2000.
var newYear2000 = new DateTime(2000, 1, 1);
var commentsWithMatchingBirthday = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.Birthday).LessThanOrEqualTo(newYear2000);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
ExtensionFilter = commentsWithMatchingBirthday
};GreaterThanOrEqualTo expression
The GreaterThanOrEqualTo expression filters documents by an extension field whose value is greater than or equal to a given value. The GreaterThanOrEqualTo expression in the following example will match any comments with a Birthday on or after new year 2000.
var newYear2000 = new DateTime(2000, 1, 1);
var commentsWithMatchingBirthday = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.Birthday).GreaterThanOrEqualTo(newYear2000);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
ExtensionFilter = commentsWithMatchingBirthday
};LessThan expression
The LessThan expression in the following example matches any comments with a Birthday before 2000.
var newYear2000 = new DateTime(2000, 1, 1);
var commentsWithMatchingBirthday = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.Birthday).LessThan(newYear2000);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
ExtensionFilter = commentsWithMatchingBirthday
};GreaterThan expression
The GreaterThan expression filters documents by an extension field whose value exceeds a given value. The GreaterThan expression in the following example will match any comments with a Birthday after new year 2000.
var newYear2000 = new DateTime(2000, 1, 1);
var commentsWithMatchingBirthday = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.Birthday).GreaterThan(newYear2000);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
ExtensionFilter = commentsWithMatchingBirthday
};And expression
The And expression filters documents by one or more sub-expressions where a document is matched by all the sub-expressions. The And expression in the following example will match any comments with a Birthday in the year 2000.
var startYear2000 = new DateTime(2000, 1, 1);
var endYear2000 = new DateTime(2000, 12, 31);
var commentsMatchingBirthday1 = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.Birthday).GreaterThanOrEqualTo(startYear2000);
var commentsMatchingBirthday2 = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.Birthday).LessThanOrEqualTo(endYear2000);
var commentsWithBirthdayInYear2000 = FilterExpressionBuilder<MyCommentExtension>.And(commentsMatchingBirthday1, commentsMatchingBirthday2);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
ExtensionFilter = commentsWithBirthdayInYear2000
};Or expression
The Or expression is used to filter documents by one or more sub-expressions where any of the sub-expressions matches a document. The Or expression in the following example will match any comments with a Birthday in year 2000 Or LuckyNumber 7.
var startYear2000 = new DateTime(2000, 1, 1);
var endYear2000 = new DateTime(2000, 12, 31);
var commentsMatchingBirthday1 = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.Birthday).GreaterThanOrEqualTo(startYear2000);
var commentsMatchingBirthday2 = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.Birthday).LessThanOrEqualTo(endYear2000);
var commentsWithBirthdayInYear2000 = FilterExpressionBuilder<MyCommentExtension>.And(commentsMatchingBirthday1, commentsMatchingBirthday2);
var luckyNumber = 7;
var commentsWithLuckyNumber = FilterExpressionBuilder<MyCommentExtension>.Field(ext => ext.LuckyNumber).Contains(luckyNumber);
var theWinner = FilterExpressionBuilder<MyCommentExtension>.Or(commentsWithBirthdayInYear2000, commentsWithLuckyNumber);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
ExtensionFilter = theWinner
};Sort composites
Fields within extension data can also be used for sorting composite result sets. Sorting rules are defined using the OrderBy property of CompositeCriteria, accepting a collection of SortInfo instances.
SortInfo identifies the field and direction for sorting.
Consider an example where an application composes a comment with extension data with the following definition:
public class MyCommentExtension {
public int LuckyNumber {
get;
set;
}
public string FavoriteTeam {
get;
set;
}
public DateTime Birthday {
get;
set;
}
}The snippet below demonstrates the construction of an instance of SortInfo, targeting the LuckyNumber field of such an extension:
var sortField = new SortField(FilterExpressionBuilder<MyCommentExtension>.Field(d => d.LuckyNumber));
var sortingRule = new SortInfo(sortField, true);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
OrderBy = new List<SortInfo> { sortingRule }
};In this example, an instance of SortField is constructed. It accepts a FieldExpression representing the LuckyNumber field of your extension data. Next, an instance of SortInfo is constructed to refer to this SortField, and assigned to the criteria as a sorting rule.
Sorting rules targeting extension data fields can be combined with those targeting standard platform entities.
Asynchronous methods
Optimizely Community API services provide asynchronous method overloads (ending with Async suffix and returning a .NET Task object) for non-blocking operations. This improves application responsiveness and performance by allowing parallel execution of tasks. Developers can use C#'s async and await keywords.
For more details, refer to Microsoft's documentation for Task-based Asynchronous Programming and Asynchronous Programming with async and await.
Updated 16 days ago