I am indexing Sitecore Commerce 9.0.2 sellable items through a regular SitecoreItemCrawler
. The HabitatHome demo sellable items are in my content tree at /sitecore/content/Habitat Sites/Habitat Home/home/Catalogs/Habitat_Master
. Items synchronized there from Sitecore Commerce do not have a any price field, not even a list price. Thus, I am trying to build a computed index field to get the list price from Sitecore Commerce.
I know Sitecore Commerce APIs have a GetBulkPrices()
method that returns the information I want. I can call it using Postman with the "CatalogAPISamples/Catalog - Pricing/Get bulk prices" request:
- URL: https://localhost:5000/api/GetBulkPrices()
- Method: PUT
- HTTP Headers
- ShopName: CommerceEngineDefaultStorefront
- ShopperId: ShopperId
- Language: en-US
- Currency: USD
- Environment: HabitatAuthoring
- GeoLocation: IpAddress=1.0.0.0
- Authorization: Bearer + Access_Token
- Body:
{ "itemIds": ["habitat_master|productSku|"] }
However, I cannot find the way to call this method from Sitecore code without crafting my own HTTP request. I have looked in Sitecore.Commerce.Connect
and other places without success. I have tried the following approaches:
PricingServiceProvider + GetProductPricesRequest
PricingServiceProvider pricingServiceProvider = new PricingServiceProvider(); GetProductPricesRequest getProductPricesRequest = new GetProductPricesRequest(productSku); getProductPricesRequest.SetShopName("CommerceEngineDefaultStorefront"); GetProductPricesResult productPricesResult = pricingServiceProvider.GetProductPrices(getProductPricesRequest); return productPricesResult.Prices.ContainsKey("List") ? productPricesResult.Prices["List"].Amount.ToString(CultureInfo.InvariantCulture) : null;
It ends with this exception that does not provide much insight:
ManagedPoolThread #4 16:16:43 ERROR An exception occurred while trying to process the item {E1E4CDD3-01C1-0854-7EBC-6F64C1A01F1F}: Default Control Panel Storefront Exception: System.InvalidOperationException Message: Default Control Panel Storefront Source: Sitecore.Commerce.XA.Foundation.Common at Sitecore.Commerce.XA.Foundation.Common.Models.CommerceStorefront.get_ControlPanel() at Sitecore.Commerce.XA.Foundation.Common.Models.CommerceStorefront.get_CurrencyConfiguration() at Sitecore.Commerce.XA.Foundation.Common.Models.CommerceStorefront.get_CurrencySet() at Sitecore.Commerce.XA.Foundation.Common.Models.CommerceStorefront.get_DefaultCurrency() at Sitecore.Commerce.XA.Foundation.Common.Providers.CurrencyProvider.GetSelectedCurrency() at Sitecore.Commerce.Services.ServiceProvider.RunPipeline[TRequest,TResult](String pipelineName, TRequest request) at Sitecore.HabitatHome.Foundation.CoveoIndexing.ComputedFields.ListPriceComputedField.GetPriceFromApi(IItem p_Item, String productSku) at Sitecore.HabitatHome.Foundation.CoveoIndexing.ComputedFields.ListPriceComputedField.GetListPrice(IItem p_Item) at Sitecore.HabitatHome.Foundation.CoveoIndexing.ComputedFields.ListPriceComputedField.ComputeFieldValue(IIndexable p_Indexable) at Coveo.SearchProvider.Documents.AbstractDocumentBuilder.AddComputedFields() at Coveo.SearchProvider.Documents.DocumentFactory.<>c__DisplayClass3_0.<CreateIndexableItem>b__3() at Coveo.SearchProvider.Documents.AbstractDocumentFactory.TryBuildDocument(Action p_Action, IIndexable p_Indexable)
PricingServiceProvider + GetProductBulkPricesRequest
PricingServiceProvider pricingServiceProvider = new PricingServiceProvider(); GetProductBulkPricesRequest getProductBulkPricesRequest = new GetProductBulkPricesRequest(new List<string> { productSku }); getProductBulkPricesRequest.SetShopName("CommerceEngineDefaultStorefront"); GetProductBulkPricesResult productBulkPricesResult = pricingServiceProvider.GetProductBulkPrices(getProductBulkPricesRequest); Price listPrice = productBulkPricesResult.Prices["List"]; if (listPrice != null) { return listPrice.Amount.ToString(CultureInfo.InvariantCulture); }
It ends with a very similar exception than the first approach.
PricingManager.GetProductPrices()
IConnectServiceProvider connectServiceProvider = new ConnectServiceProvider(); IItemTypeProvider itemTypeProvider = new ItemTypeProvider(); ISiteContext siteContext = new SiteContext(itemTypeProvider) { CurrentCatalogItem = p_Item.SitecoreItem }; PricingServiceProvider pricingServiceProvider = new PricingServiceProvider(); IPricingManager pricingManager = new PricingManager(connectServiceProvider) { PricingServiceProvider = pricingServiceProvider }; IModelProvider modelProvider = new ModelProvider(); IStorefrontUrlManager storefrontUrlManager = new StorefrontUrlManager(siteContext); IContext defaultContext = new DefaultContext { Item = p_Item.SitecoreItem, Database = p_Item.SitecoreItem.Database }; IStorefrontContext storefrontContext = new StorefrontContext(modelProvider, storefrontUrlManager, defaultContext); ICurrencyProvider currencyProvider = new CurrencyProvider(storefrontContext, defaultContext); CommerceStorefront commerceStorefront = new CommerceStorefront(currencyProvider, defaultContext); ICartManager cartManager = new CartManager(connectServiceProvider); IAccountManager accountManager = new AccountManager(connectServiceProvider, cartManager, storefrontContext, modelProvider); IVisitorContext visitorContext = new VisitorContext(accountManager); ManagerResponse<GetProductPricesResult, IDictionary<string, Price>> managerResponse = pricingManager.GetProductPrices(commerceStorefront, visitorContext, HABITAT_CATALOG_NAME, productSku, false, "List"); return managerResponse.Result.ContainsKey("List") ? managerResponse.Result["List"].Amount.ToString(CultureInfo.InvariantCulture) : null;
It ends with this exception because there is no
HttpContext
:Exception: System.NullReferenceException Message: Object reference not set to an instance of an object. Source: Sitecore.Commerce.XA.Foundation.Common at Sitecore.Commerce.XA.Foundation.Common.Context.SiteContext.set_CurrentCatalogItem(Item value) at Sitecore.HabitatHome.Foundation.CoveoIndexing.ComputedFields.ListPriceComputedField.GetPriceFromApi(IItem p_Item, String productSku) at Sitecore.HabitatHome.Foundation.CoveoIndexing.ComputedFields.ListPriceComputedField.GetListPrice(IItem p_Item) at Sitecore.HabitatHome.Foundation.CoveoIndexing.ComputedFields.ListPriceComputedField.ComputeFieldValue(IIndexable p_Indexable) at Coveo.SearchProvider.Documents.AbstractDocumentBuilder.AddComputedFields() at Coveo.SearchProvider.Documents.DocumentFactory.<>c__DisplayClass3_0.<CreateIndexableItem>b__3() at Coveo.SearchProvider.Documents.AbstractDocumentFactory.TryBuildDocument(Action p_Action, IIndexable p_Indexable)
All of my approaches seems to require an HttpContext
that is a request to the storefront site matching a Sitecore site element.
Is there a way to call the Sitecore Commerce Engine to get the price of a product without a Sitecore site context?