HotelDetails
HotelDetails
This operation is designed for the comprehensive retrieval of full HotelDetails static data. This operation should be used when hotel information can be retrieved using the hotel code previously retrieved in HotelList Operation.
Models
Step 1: Define the Models of your response (Request and Response models)
These models are crucial because they specify the structure of the objects contained within supplier responses. They'll also play a vital role in serializing and deserializing requests and responses during development.
Request example:
namespace ConnectorsTemplateContent.HotelDetails.HotelDetails.Models.Request;
public class HotelDetailsRequest
{
public string HotelCode { get; set; }
}
Response example:
public class HotelDetailsSupplierResponse
{
public string Code { get; set; }
public string Name { get; set; }
public string CategoryCode { get; set; }
public string City { get; set; }
public string Latitude { get; set; }
public string Longitude { get; set; }
}
Develop
Step 1: Register the serializers and operations
To specify which serializer and operations the developer will be using (based on the seller's API) we can specify it in our "Extensions":
File location: "HotelDetails\HotelDetailsExtensions.cs"
If the seller works with JSON format, we can specify the integration to work with JSON with the following:
using System.Text.Json;
using Connectors.Content.Pull.Api.Extensions.HotelList;
using Connectors.Core.App.Extensions;
using ConnectorsTemplateContent.Common.Constants;
using ConnectorsTemplateContent.HotelsList.HotelDetails.Models.Request;
using ConnectorsTemplateContent.HotelsList.HotelDetails.Models.Response;
using HotelDetailsOperation = ConnectorsTemplateContent.HotelsList.HotelDetails.Operations.HotelDetailsOperation;
namespace ConnectorsTemplateContent.HotelsList.HotelDetails;
public static class HotelDetailsExtensions
{
public static void AddHotelDetailsServices(this IServiceCollection services,
IConfiguration configuration)
{
services.AddJsonSerializer<HotelDetailsRequest, HotelDetailsSupplierResponse>(ConfigureJSONOptions);
services.AddHotelDetailsOperation<HotelDetailsOperation, HotelDetailsRequest, HotelDetailsSupplierResponse, AccessModel>(
TgxPlatform.Name, configuration);
}
private static void ConfigureJSONOptions(JsonSerializerOptions options) { }
}
For details about others serializers, check Extensions.
Step 2: HotelDetailsOperation validators
There are two previous validations that serve as a filter so the buildrequest and the parseresponse are as safe as possible. They can be found in the SearchOperation.cs class:
File location: "HotelDetails\Operations\HotelDetailsOperation.cs"
TryValidateModelRequest
This step validates the incoming request from the client. While most validation is defined in the metadata, this step is used for specific edge cases that cannot be generalized.
public bool TryValidateModelRequest(ContentRequest connectorsRequest,
ContentOperationParameters<AccessModel> connectorParameters,
out IEnumerable<AdviseMessage> adviseMessages)
{
adviseMessages = null;
return true;
}
TryValidateSupplierResponses
Once the supplier's response is received, this step validates it for errors or anomalies. Suppliers may return incomplete or erroneous data, so this step ensures only valid responses are processed further.
Details:
- Check for supplier-specific error fields.
- Ensure required fields (e.g., hotel list) are present.
- Example Use Case: A supplier might return a response with an error code or an empty hotel list. This step would detect and handle such cases.
public bool TryValidateSupplierResponses(ContentOperationParameters<AccessModel> connectorParameters,
IEnumerable<SupplierResponseWrapper<HotelDetailsSupplierResponse>> supplierResponses,
out IEnumerable<AdviseMessage> adviseMessages)
{
var supplierResponseWrappers = supplierResponses as SupplierResponseWrapper<HotelDetailsSupplierResponse>[] ?? supplierResponses.ToArray();
var success = ResponseValidator.TryValidateSupplierResponses(supplierResponseWrappers, out adviseMessages);
if (!success) return false;
if (supplierResponseWrappers.ElementAt(0).Response.HotelSearch?.Hotel is null)
{
adviseMessages =
[
AdviseMessage.BuildSupplierNoResults() // Indicates no results from the supplier.
];
return false;
}
return true; // Validation passes if no issues are found.
}
Step 3: Build the Seller's request
This class will contain a "BuildRequests" method that will have the following args:
- Object of the requests from the models previously created (HotelDetailsRequest).
- The request that the buyer sends (connectorsRequest).
- Parameters (connectorParameters) which will have some helpers.
File location: "HotelDetails\Operations\HotelDetailsOperation.BuildRequest.cs"
Example of Build Request:
using Connectors.Content.Pull.Application.Operations;
using Connectors.Core.Application.Connection;
using ConnectorsTemplateContent.HotelsList.HotelDetails.Models.Request;
namespace ConnectorsTemplateContent.HotelsList.HotelListFull.Operations;
internal partial class HotelDetailsOperation
{
public IEnumerable<SupplierRequestWrapper<HotelDetailsRequest>> BuildRequests(string hotelCode,
ContentRequest connectorsRequest,
ContentOperationParameters<AccessModel> connectorParameters)
{
string genericUrl = connectorParameters.ParametersModel.GenericUrl;
HotelDetailsRequest supplierRequest = new HotelDetailsRequest()
{
HotelCode = hotelCode
}
var request = new SupplierRequestWrapper<HotelDetailsRequest>(
supplierRequest,
new Uri(genericUrl),
HttpMethod.Post);
return new List<SupplierRequestWrapper<HotelDetailsRequest>>()
{
request
};
}
}
Step 4: Parse the Seller's response
Once the request has been sent, we will have to control and parse the response returned by the seller.
We will be implementing the "ParseResponse" step inside HotelDetailsOperation:
File location: "HotelDetails\Operations\HotelDetailsOperation.ParseResponse.cs"
Example of Parse Response:
using Connectors.Content.Pull.Application.Operations;
using Connectors.Content.Pull.Application.Operations.HotelsList.HotelDetails;
using Connectors.Content.Pull.Domain.Contracts.HotelList.Delta;
using Connectors.Core.Application.Connection;
using ConnectorsTemplateContent.HotelsList.HotelDetails.Models.Response;
using Content.Common.Domain.AccumulativeContracts.Hotel;
namespace ConnectorsTemplateContent.HotelsList.HotelDetails.Operations;
internal partial class HotelDetailsOperation
{
public HotelDetailsResponse ParseResponses(ContentRequest connectorsRequest,
ContentOperationParameters<AccessModel> connectorParameters,
IEnumerable<SupplierResponseWrapper<HotelDetailsSupplierResponse>> supplierResponses,
CancellationToken cancellationToken)
{
ParseSupplierHotels(supplierResponses.First().Response);
return new HotelDetailsResponse(new HotelDetailsRs());
}
private void ParseSupplierHotels(HotelDetailsSupplierResponse response)
{
foreach (var hotel in response.Hotels)
{
//Accumulator is used instead of returning an object with the response.
_accumulator.AddValue(new AccumulativeHotel()
{
Code = hotel.Code,
Name = hotel.Name,
CategoryCode = hotel.CategoryCode,
City = hotel.City,
Latitude = hotel.Latitude,
Longitude = hotel.Longitude
});
}
}
}
Code Review
Step 1: Create Pull Request
- Commit your Search changes and push them to a new branch called "HotelDetailsDevelopment" into the original repository.
- Separate the Pull Request into minimum these 4 commits:
- Request and Response models
- BuildRequest
- ParseResponse
Step 2: Wait for Travelgate review
- This step involves waiting for the Travelgate team to review and approve the submitted pull request, for more details, check Code Review Details