OData compliance

Abstract

Overview of OData compliance.

Note

Sitecore Experience Commerce (XC) release 10.0 and later is based on Microsoft.AspNetCore.Odata version 7.3.1.

The Commerce Service API is based on the Open Data Protocol (OData). OData provides metadata that allows external systems to discover Commerce capabilities and data structures. OData also supports annotations on metadata, which provides basic validation requirements and enumerations so that smarter clients can prevalidate and provide drop-down support for enumerable properties.

Most Microsoft products can natively consume OData. For example, Excel can connect to an OData source allowing the use of Power Pivot or other Excel-based analytic tools to be easily integrated. Other Microsoft products, including Microsoft Dynamics AX, support OData in their service layers.

Controllers

Sitecore XC controllers inherit from the ODataController class. The base class is CommerceODataController, and is shown in the following example:

...
[Authorize(Policy = "RoleRequirement")]
public class ComerceODataController : ODataController, IActionFilter, IAzynActionFilter, IDisposable

ODataRoutes

ODataRoutes use the ODataRoute attribute and the ODataRoutePrefix attribute.

The ODataRoute attribute

The ODataRoute attribute defines controller actions, for example:

[HttpGet]
[ODataRoute]
[EnableQuery(MaxExpansionDepth = 0)]
public async Task<IEnumerable<CommerceEnvironment>> Get()
[HttpGet]
[EnableQuery(MaxExpansionDepth = 0)]
ODataRoute("({Id})]
public async Task<IActionResult> Get([FromODataUri] string id) 

Note

If you do not specify a RouteName, the action is available for both the CommerceAPI and the CommerceOps routes.

Note

We recommend the use of MaxExpansionDepth = 0 in the EnableQuery attribute for any GET action where the expand filter is used for more than 2 levels.

ODataRoute attribute examples for controller actions

The following action is only available through the CommerceOps route:

[HttpPost]
[ODataRoute("RunMinion", RouteName = CoreConstants.CommercepsApi)]
public <IActionResult RunMinion([FromBody] ODataActionParameters value)

The following action is only available through the CommerceAPI route:

[HttpGet]
[ODataRoute("GetListMetadata(listName={listName})", RouteName = CoreConstants.CommerceAPI)]
public async Task<IActionResult> GetListMetadata([FromODataUri] string listName)

The following action does not specify a route and, as a result, is available through both the CommerceAPI and the CommerceOps routes:

[HttpPost]
[ODataRoute("AddPolicy")]
public async Task<IactionResult> AddPolicy([FromBody] ODataActionParameters value)

The ODataRoutePrefix attribute

For entity OData controllers, the ODataRoutePrefix attribute specifies the prefix that is used for all actions of that controller. The ODataRoutePrefix attribute value must match the entity set names.

In the following example, the ODataRoutePrefix is based on the entity set defined as arg.EntitySet<CommerceEnvironment>("Environments"):

...
[ODataRoutePrefx("Environments")]
public class EnvironmentsController : CommerceOdataController

The OData Model Builder

The ODataConventionModelBuilder uses a strict discovery mechanism. Because the discovery mechanism is stricter, you must add your classes in the IEdmModel.

XC uses the following pipelines to build the IEdmModel:

  • IConfigureServiceApiPipeline

  • IConfigureOpsServiceApiPipeline

To facilitate the discovery of derived classes, you can use the following extensions to the ODataConventionModelBuilder:

  • AddCommerceComplexType: this extension maps a CLR class and all its derived classes as ComplexTypes. This action is available through both the CommerceAPI route and the CommerceOps route.

    For example:

    arg.AddCommerceCompletexType(typeof(Model));
    arg.AddCommerceCompletexType(typeof(Policy));
    arg.AddCompletexType(typeof(CommandMessage));
    arg.AddCompletexType(typeof(EntityReference));
    arg.AddCompletexType(typeof(Dictionary<string, string>));
    arg.AddCompletexType(typeof(List<Task<CommerceCommand>>));
    arg.AddCompletexType(typeof(ConcurrentDictionary<string, string>));
    
  • AddCommerceEntity: this extension maps a CLR class and all its derived classes as entities. For example:

    arg.AddCommerceEntity(typeof(CommerceEntity));
    arg.AddCommerceEntity(typeof(Component));