Day 2: Open data feeds
Objective for Day 2
Create open data RPDE feeds live from your application.
Rationale
Open Booking API is built on top of open data feed publishing, and RPDE feeds are therefore a prerequisite to implementing the rest of the API.
Step 1 - Understand the RPDE specification
Before continuing with this tutorial, the following video offers a good theoretical understanding of the RPDE specification. Further information can be found in the developers guide and RPDE specification.
Step 2 - Set up your Opportunity and Offer pair ID structure
In order for opportunities and offers within open RPDE feeds to be bookable via the Open Booking API, they must have IDs.
The Open Booking API is based on JSON-LD. JSON-LD IDs always take the form of a URL, and hence all IDs within the Open Booking API also take the form of a URL. The StoreBookingEngine automatically constructs and parses these URLs for you, and deserialises them into POCOs. It also handles routing based on the URL template to the relevant store depending on the type of opportunity.
In order to take advantage of these features, you need to configure the URL structure specifically for your application.
The first URLs we'll set up are for the Opportunity and Offer pairs, such as the IDs found in the Open Booking API request snippet below:
IBookablePairIdTemplate and IBookableIdComponents
There are two key components that handle JSON-LD ID serialisation and deserialisation within the StoreBookingEngine:
IBookablePairIdTemplateinstances specify the ID URL templates used by your application and associates them with OpenActive opportunity types, as well as the hierarchy of types that are in use from the OpenActive data model. They also define the types of opportunities that are bookable, and which feeds are used to publish the opportunities.IBookableIdComponentsare POCO objects that you define specifically based on the underlying data model within your booking system, used to deserialise the ID URL. The properties within these are mapped by name to the placeholders within the associatedIBookablePairIdTemplateURL templates.IBookableIdComponentsrepresents an Opportunity and Offer pair, and hence includes both the Opportunity ID and Offer ID, with their matching overlapping components.
Note that the JSON-LD IDs do not need to resolve to actual endpoints, provided they are unique and exist within your domain.
Configuring IBookablePairIdTemplates
IBookablePairIdTemplate instances are configured in Startup.cs or ServiceConfig.cs within BookingEngineSettings:
Where you these referenced in the example above...
The following annotations apply...
SessionOpportunity and EventOpportunity
Examples of an IBookableIdComponents POCO used to map to placeholders within the ID templates defined
BookablePairIdTemplate
A template that contains a hierarchy of up to three OpenActive types, in order from child to parent (e.g. ScheduledSession β SessionSeries β EventSeries). BookablePairIdTemplate accepts the generic parameter of an IBookableIdComponents type, which binds the placeholders within the URL templates specified to the properties defined within the IBookableIdComponents POCO.
BookablePairIdTemplateWithOfferInheritance
A specialism of BookablePairIdTemplate designed for the special case of ScheduledSession β SessionSeries where Offers may be inherited from SessionSeries to ScheduledSession.
OpportunityType
The OpenActive opportunity type represented
AssignedFeed
The feed within which this opportunity type is published (for example, the EventSeries may be embedded within a SessionSeries feed as shown in this example).
OpportunityUriTemplate
OfferUriTemplate
The URL Templates used to serialise/deserialise the POCO for an Opportunity ID and Offer ID. Note that the Opportunity ID and Offer ID are deserialised into the same POCO, as an Opportunity and Offer pair, and hence any shared components within these must match (e.g. an Offer is specific to an Event, and hence will include both the Event ID and and
Bookable
Whether the specified Opportunity and Offer pair is bookable within this booking system using the Open Booking API. Note that SessionSeries and FacilityUse are not bookable within the Open Booking API, which instead prefers ScheduledSessions or Slots.
BaseUrl
This is a placeholder within the ID templates that has a special function of ensuring conformity with the JsonLdIdBaseUrl setting within BookingEngineSettings, both for serialisation and deserialisation.
Configuring IBookableIdComponents
IBookableIdComponents are defined by the classes in the IdComponents directory.
These classes must be created by the booking system. There is a choice of string, long? and Uri available as the type for each component of the ID, as well as any enum type. The names of the components must exactly match the placeholders within the associated IBookablePairIdTemplates.
In the example above
Description
OpportunityType
The OpportunityType represents the type in the hierarchy that the Opportunity and Offer pair represents (e.g. HeadlineEvent or its child Event). This property is available by the class extending either IBookableIdComponents or IBookableIdComponentsWithInheritance.
OfferOpportunityType
For SessionSeries, where the Offer can be inherited to the child ScheduledSession, OfferOpportunityType indicates which Offer is being referenced - the parent or the child. This property is only available by the class extending IBookableIdComponentsWithInheritance.
Step 3 - Set up your Seller ID structure
The Seller IDs are configured slightly differently to the Opportunity and Offer pair IDs, for simplicity.
There is a built-in POCO named SellerIdComponentsthat is defined as follows:
Within BookingEngineSettings the SellerIdTemplate setting controls how the Seller ID is serialised and deserialised. There are two options for Seller IDs: Single Seller and Multiple Seller.
Booking systems supporting Multiple Sellers
Depending on the type of your internal Seller ID, you may use either SellerIdLong or SellerIdString within the URL template. Once you have chosen which one to use, simply reference that same property consistently wherever you use the Seller ID throughout your code, and ignore the other property.
The following example demonstrates BookingSystemSettings for Multiple Sellers:
Booking systems supporting a Single Sellers
To use Single Seller mode, simply use neither SellerIdLong or SellerIdString within the URL template, and set HasSingleSeller to true. Then simply do not reference SellerIdComponents anywhere in your code, as both SellerIdLong and SellerIdString will be null. RenderSingleSellerId is provided for scenarios where a Single Seller ID needs to be rendered.
The following example demonstrates BookingSystemSettings for a Single Seller:
Step 4 - Create RPDE Feed Generators
The StoreBookingEngine handles the serialisation and parameter validation that would usually be required when implementing an RPDE feed. All that is required for each feed is to implement a single method within an IOpportunityDataRPDEFeedGenerator class.
Within BookingEngineSettings within EngineConfig.cs the OpenDataFeeds setting configures the routing to the different feed generators from the GetOpenDataRPDEPageForFeed method being called in the controller.
Three implementations of IOpportunityDataRPDEFeedGenerator are available depending on your prefered RPDE Ordering Strategy, and whether your ID is a long or string.
Using the example of the IBookableIdComponents class SessionOpportunity from Step 2, and the OpenActive feed root type of ScheduledSession, a generator is created by subclassing one of the following:
RPDEFeedModifiedTimestampAndIDLong<SessionOpportunity, ScheduledSession>RPDEFeedModifiedTimestampAndIDString<SessionOpportunity, ScheduledSession>RPDEFeedIncrementingUniqueChangeNumber<SessionOpportunity, ScheduledSession>
Any of the above would require the same GetRPDEItems method be implemented, as below:
The appropriate query for the database for your chosen RPDE Ordering Strategy must be used, and the ordering of the items returned from your overridden method is automatically validated to ensure consistency with the specification.
Within the mapping of your data to the OpenActive model, there are a few helper methods available from the base class to construct IDs specific for the feed:
Method
Example
RenderOpportunityId
Id = this.RenderOpportunityId(new SessionOpportunity
{
OpportunityType = OpportunityType.SessionSeries,
SessionSeriesId = @class.Id
}),
RenderOfferId
Id = this.RenderOfferId(new SessionOpportunity
{
OfferOpportunityType = OpportunityType.SessionSeries,
SessionSeriesId = @class.Id,
OfferId = 0
}),
RenderSellerId
(for Multiple Sellers)
Id = this.RenderSellerId(new SellerIdComponents
{
SellerIdLong = seller.Id
}),
RenderSingleSellerId
(for Single Seller)
Id = this.RenderSingleSellerId(),
Step 5 - Configure Dataset Site
The DatasetSiteGeneratorSettings within EngineConfig.cs can be used to configure your dataset site.
Only the OpenDataFeedBaseUrl is used by the StoreBookingEngine, so this must be accurate to proceed with testing.
All other settings are described within the documentation for OpenActive.DatasetSite.NET.
Step 6 - Test data feeds and dataset site
If you run your application and navigate to the dataset site endpoint (e.g. https://localhost:44307/openactive), you should find it now reflects your updated settings, and the links to the RPDE pages on that page work as expected.
Last updated
Was this helpful?