top of page
  • Hina Garg

Data Exchange B/w Sitecore XC and XP by using Service Proxy - Part 3

Hello Everyone,


In today's blog, I am going to explain the third step that would complete the data exchange between Sitecore XP and XC.


Objective: Create a SXA component for our storefront that would consume the rest service endpoint that has been created in commerce engine (Part 1). For creating a SXA component, we need following things:


Basic building blocks of a SXA component:

1. Controller: It provides useful properties and logic to automatically resolve the view name and provide the model. 
2. Model : A class that defines the properties to be used by a controller.
3. View : A view is used to display data using the model class object.

If you have used MVC design pattern, you are already familiar with above blocks. Let's talk about the rest 2 that are used by SXA.
 
4. Repository: SXA uses repositories to provide model for the MVC views. So we must inject the repository into the controller to access the model.
5. Configurator: We need to register the repository into the DI (Dependency Injection) container. We can do this by either using a config file or by defining a class that extends IServicesConfigurator.

For this exercise, I am going to create one more class:

6. Manager:  This class is going to access the Sitecore Commerce Engine container and fetch the products. 

Let's say we have to build a page in our storefront as shown in below image:





















If you have read Part 1 and Part 2, you would understand the data structure of a product and the ways in which this small exercise could be helpful for a big task.


Let's Code this:









  1. Manager Interface and Class: Let's start by creating a manager class that would interact with the end point in commerce and get results.


IProductInformationManager.cs
    
public interface IProductInformationManager
    {
       ManagerResponse<GetProductInformationResult, ProductsList>      GetProductInformation(
            string CommonProductID,
            IStorefrontContext storefrontContext, IVisitorContext visitorContext);
    }

As seen below, we are providing the CommonProductID as the payload of our request.

ProductInformationManager.cs

 public virtual ManagerResponse<GetProductInformationResult, ProductsList> GetProductInformation(
           string CommonProductID,
            IStorefrontContext storefrontContext, IVisitorContext visitorContext)
        {
            GetProductInformationResult serviceResult = new GetProductInformationResult();
            ProductsList productDataResult = null;
            try
            {
                //get the Sitecore XC engine container
                var container = EngineConnectUtility.GetShopsContainer(shopName: storefrontContext.CurrentStorefront.ControlPanel.Name, customerId: visitorContext.CustomerId);

                var response = Proxy.DoCommand(container.GetProductInformation(CommonProductID));

                if (response != null)
                {
                    if (response.Models.Count > 0)
                    {
                        var productsModel = response.Models.OfType<ProductsList>().FirstOrDefault<ProductsList>();
                        if (productsModel != null)
                        {
                            productDataResult = productsModel;
                            serviceResult.ProductInformation = productsModel;
                            serviceResult.Success = true;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                //catching & logging exceptions
                Log.Error(ex.Message, this);
            }

            return new ManagerResponse<GetProductInformationResult, ProductsList>(serviceResult, productDataResult);

        }



2. Model: Model classes used in this blog are the one's created in the commerce engine(Part 1). As per the requirement you can create additional models if required.


3. Repository: It gets the response from the manager and sets the model(ProductsList) to inject into the controller.

IProductsRepository.cs

public interface IProductsRepository : IModelRepository
    {
        ProductsList GetProductInformationModel(
                    IStorefrontContext storefrontContext, IVisitorContext visitorContext);
    }


 public class ProductsRepository : ModelRepository, IProductsRepository
    {

        private readonly Managers.IGetProductInformationManager _getProductInformationManager;
        private readonly IModelProvider _modelProvider;

        public ProductsRepository(
            IGetProductInformationManager getProductInformationManager,
            IModelProvider modelProvider) : base()
        {
            Assert.ArgumentNotNull(modelProvider, nameof(modelProvider));
            this._getProductInformationManager = getProductInformationManager;
            _modelProvider = modelProvider;

        }

        /// <param name="storefrontContext"></param>
        /// <param name="visitorContext"></param>
        /// <returns></returns>
        public ProductsList GetProductInformationModel(IStorefrontContext storefrontContext, IVisitorContext visitorContext)
        {

            ProductsList model = new ProductsList();

            string commonProductID = GetCommonProductID();

            ManagerResponse<GetProductsInformationResult, ProductsList> result = this._getProductInformationManager.GetProductInformation(commonProductID,
                storefrontContext, visitorContext);

            if (result.ServiceProviderResult.Success)
            {
                model = result.Result;
            }

            return model;

        }


        /// <summary>
        /// Create a product temaplte.
        /// Get the common product id.
        /// </summary>
        /// <returns></returns>
        private string GetCommonProductID()
        {
            return PageContext.Current.Parent.Fields[Templates.Products.Fields.CommonProductID].Value;
        }

    }
}


4. Controller: Gets products information and returns to the view.


 public class ProductsController : BaseCommerceStandardController
    {
        private IProductsRepository _productsRepository;
        private IVisitorContext _visitorContext;
        private IModelProvider _modelProvider;

        public ProductsController(
            IProductsRepository productsRepository,
            IVisitorContext visitorContext,
            IStorefrontContext storefrontContext,
            IModelProvider modelProvider,
            IContext iContext) :
            base(storefrontContext, iContext)
        {
            _productsRepository = productsRepository;
            _visitorContext = visitorContext;
            _modelProvider = modelProvider;
        }


        /// <summary>
        /// Gets products information and returns to the view.
        /// </summary>
        /// <returns></returns>
        public ActionResult GetProductInformation()
        {
            return View("GetProductInformation", _productsRepository.GetProductInformationModel(StorefrontContext, _visitorContext));
        }
    }

5. Views: Just providing here a sample of the view.


@model Plugin.Example.Products.Models.ProductsList

<div>
    <div class="wrapper">
    <div class="row">
                <div class="col-8">
                    @Model.BaseLevelProduct.ProductName
                    @Model.BaseLevelProduct.ProductDescription
                </div>
            </div>
        @foreach (var item in Model.FirstLevelProducts)
        {
            <div class="row">
                <div class="col-8">
                    @item.ProductName
                    @item.ProductDescription
                </div>
            </div>
        }
        @foreach (var item1 in Model.SecondLevelProducts)
        {
            <div class="row">
                <div class="col-8">
                    @item1.ProductName
                    @item1.ProductDescription
                </div>
            </div>
        }
    </div>
</div>

Hope this blog helps. Thank you!


56 views0 comments

Comments


bottom of page