Magelia WebStore

  • Summary

How to access Catalog Information

Overview: Catalog OData Service

Download the code sample of this tutorial:
How to access catalog information - ZIP - 28.0 mo

As has already been evoked in the section How to use Magelia WebStore in a Visual Studio project, Magelia WebStore puts forth different WCF services: customerService, sotreService, etc. However the Catalog part is put forth via an OData service.

What is OData?

The Open Data Protocol (OData) is a Web protocol for querying and updating data that provides a way to unlock your data and free it from silos that exist in applications today. OData does this by applying and building upon Web technologies such as HTTP, Atom Publishing Protocol (AtomPub) and JSON to provide access to information from a variety of applications, services, and stores. The protocol emerged from experiences implementing AtomPub clients and servers in a variety of products over the past several years. OData is being used to expose and access information from a variety of sources including, but not limited to, relational databases, file systems, content management systems and traditional Web sites (Source : http://www.odata.org/).

The following class diagram shows you the OData model put forth by the service catalogService from Magelia WebStore.

Odata

How to Get a List of Catalogs

Magelia WebStore allows you to define several catalogs within a given store. For example, we could imagine having a Summer Catalog and a separate Winter Catalog, each offering different products.

It is possible to retrieve the list of different catalogs defined for our boutique. To do so, initially we add the methods and properties to our context which afterwards enables us to more easily access this data:

using Magelia.WebStore.Client.Web.UI.Sample.Resources;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
 
public class SampleSiteContext : WebStoreContext
{
    // ...
 
    /// <summary>
    /// Set the catalog id in session
    /// </summary>
    /// <param name="catalogId"></param>
    public void SetCatalog(Guid catalogId)
    {
        HttpContext.Current.Session["CatalogId"] = catalogId;
    }
 
    /// <summary>
    /// Get catalog
    /// </summary>
    public Catalog Catalog
    {
        get
        {
            Catalog catalog = null;
            Guid catalogId;
            if (HttpContext.Current.Session["CatalogId"] == null)
            {
                catalog = this.CatalogClient.Catalogs.OrderBy(c => c.Name).FirstOrDefault();
                if (catalog == null)
                {
                    return null;
                }
                catalogId = catalog.CatalogId;
                HttpContext.Current.Session["CatalogId"] = catalogId;
            }
            else
            {
                catalogId = (Guid)HttpContext.Current.Session["CatalogId"];
            }
 
            if (catalog == null)
            {
                catalog = this.CatalogClient.Catalogs.Where(c => c.CatalogId == catalogId).FirstOrDefault();
            }
            return catalog;
        }
    }
 
    /// <summary>
    /// Get list of all available catalogs
    /// </summary>
    public IEnumerable<SelectListItem> Catalogs
    {
        get
        {
            IEnumerable<SelectListItem> catalogs = this.CatalogClient.Catalogs
                                                        .OrderBy(c => c.Name)
                                                        .ToList()
                                                        .Select(c => new SelectListItem
                                                        {
                                                            Text = c.Name,
                                                            Value = c.CatalogId.ToString(),
                                                            Selected = c.CatalogId == this.Catalog.CatalogId
                                                        });
            return catalogs;
        }
    }
}

Here we have defined, within our context, a Catalog property that allows us to retrieve the current catalog in function of its identifier, then a Catalogs property that makes it possible to retrieve the list of available catalogs.

The different available catalogs are retrieved via the OData CatalogClient service and the Catalogs property.

We can also offer the user the possibility of choosing the catalog that he/she wishes to view:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
 
namespace Magelia.WebStore.Client.Web.UI.Sample.Models.Shared
{
    public class CatalogsViewModel
    {
        private IEnumerable<SelectListItem> _catalogs;
 
        /// <summary>
        /// List of available catalogs
        /// </summary>
        public IEnumerable<SelectListItem> Catalogs
        {
            get
            {
                if (this._catalogs == default(IEnumerable<SelectListItem>))
                {
                    this._catalogs = Enumerable.Empty<SelectListItem>();
                }
                return this._catalogs;
            }
            set
            {
                this._catalogs = value;
            }
        }
    }
}
@model Magelia.WebStore.Client.Web.UI.Sample.Models.Shared.CatalogsViewModel
@Html.DropDownList("catalog", this.Model.Catalogs, new { id = "ddlCatalogs" })
<script type="text/javascript">
    //<![CDATA[
    $(document).ready(
        function () {
            $('#ddlCatalogs').change(
                function () {
                    document.location.href = '@Url.Action("SetCatalog", "Shared")/' + $(this).val();
                }
            );
        }
    );
    //]]>           
</script>
using Magelia.WebStore.Client.Web.UI.Sample.Models.Shared;
using Magelia.WebStore.Client.Web.UI.Sample.Runtime;
using Magelia.WebStore.Client.Web.UI.Sample.Runtime.MVC;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Mvc;
 
public class SharedController : BaseController
{
    public SharedController(SampleSiteContext sampleSiteContext)
        : base(sampleSiteContext)
    { }
 
    [ActionName("Catalogs")]
    public PartialViewResult CatalogsAction()
    {
        return this.PartialView(new CatalogsViewModel { Catalogs = this.SampleSiteContext.Catalogs });
    }
 
    public ActionResult SetCatalog(Guid id)
    {
        this.SampleSiteContext.SetCatalog(id);
        return this.RedirectToAction("Index", "Home");
    }
}

Access Catalog Information Access Catalog Information

How to Get a List of Categories

In order to allow users to navigate through your catalog, it is useful to list and display the entirety of the categories in the catalog. Here is an example allowing you to retrieve the entirety of the first and second level categories of the selected catalog and to display a corresponding menu:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
 
namespace Magelia.WebStore.Client.Web.UI.Sample.Models.Shared
{
    public class MenuViewModel
    {
        public class Category
        {
            public Guid CategoryId { get; set; }
            public String Name { get; set; }
 
            private IEnumerable<SubCategory> _subCategories;
            public IEnumerable<SubCategory> SubCategories
            {
                get
                {
                    if (this._subCategories == default(IEnumerable<SubCategory>))
                    {
                        this._subCategories = Enumerable.Empty<SubCategory>();
                    }
                    return this._subCategories;
                }
                set
                {
                    this._subCategories = value;
                }
            }
        }
 
        public class SubCategory
        {
            public Guid CategoryId { get; set; }
            public String Name { get; set; }
        }
 
        private IEnumerable<Category> _categories;
        public IEnumerable<Category> Categories
        {
            get
            {
                if (this._categories == default(IEnumerable<Category>))
                {
                    this._categories = Enumerable.Empty<Category>();
                }
                return this._categories;
            }
            set
            {
                this._categories = value;
            }
        }
    }
}
@model Magelia.WebStore.Client.Web.UI.Sample.Models.Shared.MenuViewModel
 <ul>
 @foreach (var category in this.Model.Categories)
 {
     <li>@Html.ActionLink(category.Name, "Category", "Catalog", new { categoryId = category.CategoryId }, null)
         @if (category.SubCategories.Count() > 0){
             <ul class="sub-menu">
                 @foreach (var subCategory in category.SubCategories)
                 {
                     <li>@Html.ActionLink(subCategory.Name, "Category", "Catalog", new { categoryId = subCategory.CategoryId }, null)</li>
                 }
             </ul>
         }
     </li>
 }
 </ul>
using Magelia.WebStore.Client.Web.UI.Sample.Models.Shared;
using Magelia.WebStore.Client.Web.UI.Sample.Runtime;
using Magelia.WebStore.Client.Web.UI.Sample.Runtime.MVC;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Mvc;
 
namespace Magelia.WebStore.Client.Web.UI.Sample.Controllers
{
    public class SharedController : BaseController
    {
        public SharedController(SampleSiteContext sampleSiteContext)
            : base(sampleSiteContext)
        { }
 
        [ActionName("Catalogs")]
        public PartialViewResult CatalogsAction()
        {
            return this.PartialView(new CatalogsViewModel { Catalogs = this.SampleSiteContext.Catalogs });
        }
 
        public PartialViewResult Context()
        {
            return this.PartialView(
                new ContextViewModel
                {
                    Cultures = this.SampleSiteContext.StoreContext.AvailableCultures.Select(c => new SelectListItem 
                        { Text = c.Name, Value = c.LCID.ToString(), Selected = c.LCID == Thread.CurrentThread.CurrentCulture.LCID }),
                    Currencies = this.SampleSiteContext.StoreContext.AvailableCurrencies.Select(c => new SelectListItem 
                        { Text = c.Name, Value = c.CurrencyId.ToString(), Selected = c.CurrencyId == this.SampleSiteContext.Currency.CurrencyId }),
                    Countries = this.SampleSiteContext.StoreContext.AvailableCountries.Select(c => new SelectListItem 
                        { Text = c.Name, Value = c.CountryId.ToString(), Selected = c.CountryId == this.SampleSiteContext.Location.CountryId })
                }
            );
        }
 
        public ActionResult SetCatalog(Guid id)
        {
            this.SampleSiteContext.SetCatalog(id);
            return this.RedirectToAction("Index", "Home");
        }
 
        public ActionResult SetCulture(Int32 id)
        {
            this.SampleSiteContext.SetCulture(id);
            if (this.Request.UrlReferrer == default(Uri))
            {
                return this.RedirectToAction("Index", "Home");
            }
            else
            {
                return this.Redirect(this.Request.UrlReferrer.ToString());
            }
        }
 
        public ActionResult SetCountry(Int32 id)
        {
            this.SampleSiteContext.SetLocation(id);
            return this.RedirectToAction("Index", "Home");
        }
 
        public ActionResult SetCurrency(Int32 id)
        {
            this.SampleSiteContext.SetCurrency(id);
            return this.RedirectToAction("Index", "Home");
        }
 
        public PartialViewResult Menu()
        {
            return this.PartialView(
                new MenuViewModel
                {
                    Categories = this.SampleSiteContext.RootCategories.Select(
                        rc => new MenuViewModel.Category
                        {
                            CategoryId = rc.CategoryId,
                            Name = rc.Name,
                            SubCategories = rc.ChildCategoryHierarchies
                                                                    .OrderBy(cch => cch.Order)
                                                                    .Select(
                                                                        cch => new MenuViewModel.SubCategory
                                                                        {
                                                                            CategoryId = cch.CategoryId,
                                                                            Name = cch.Category.Name
                                                                        }
                                                                    )
                        }
                    )
                }
            );
        }
    }
}

Access Catalog Information Access Catalog Information

How to Get a List of Products

In the same manner, when a user selects a category, it is useful to list the entirety of the products of the category. The code sample below enabes listing the products of the category selected by the user:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
 
namespace Magelia.WebStore.Client.Web.UI.Sample.Models.Catalog
{
    public class CategoryViewModel
    {
        public class Category
        {
            public Guid CategoryId { get; set; }
            public String Name { get; set; }
        }
 
        public String CatalogCode { get; set; }
        public String CatalogName { get; set; }
        private List<ProductViewModel> _products;
 
        public List<ProductViewModel> Products
        {
            get
            {
                if (this._products == default(List<ProductViewModel>))
                {
                    this._products = new List<ProductViewModel>();
                }
                return this._products;
            }
            set
            {
                this._products = value;
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
 
namespace Magelia.WebStore.Client.Web.UI.Sample.Models.Catalog
{
    public class ProductViewModel
    {
        public Guid ProductId { get; set; }
        public Guid? VariantProductId { get; set; }
        public String Name { get; set; }
        public String ImageUrl { get; set; }
        public String ImageAlternateText { get; set; }
        public Guid? BrandId { get; set; }
        public String BrandName { get; set; }
        public String Description { get; set; }
        public Decimal? SalePrice { get; set; }
        public Decimal? CutPrice { get; set; }
        public Boolean IsVariable { get; set; }
        public String CatalogName { get; set; }
        public String CatalogCode { get; set; }
        private IEnumerable<SelectListItem> _quantities;
 
        public IEnumerable<SelectListItem> Quantities
        {
            get
            {
                if (this._quantities == default(IEnumerable<SelectListItem>))
                {
                    this._quantities = Enumerable.Empty<SelectListItem>();
                }
                return this._quantities;
            }
            set
            {
                this._quantities = value;
            }
        }
    }
}
@model Magelia.WebStore.Client.Web.UI.Sample.Models.Catalog.CategoryViewModel
@{
    ViewBag.Title = Magelia.WebStore.Client.Web.UI.Sample.Resources.Views.Catalog.Category.PageTitle;
}
 
<article id="grid">
    @if (this.Model.Products.Count > 0){
        <ul id="items">
            @foreach (var product in this.Model.Products)
            {
                <li>
                    <a href="@Url.Action("Product", "Catalog", new { productId = product.VariantProductId ?? product.ProductId, variantId = product.IsVariable ? (Guid?)product.ProductId : null }, null)">
                        @Html.Image(product.ImageUrl, product.ImageAlternateText)
                    </a>
                    <a href="@Url.Action("Product", "Catalog", new { productId = product.VariantProductId ?? product.ProductId, variantId = product.IsVariable ? (Guid?)product.ProductId : null }, null)" class="title">
                        @product.Name
                    </a>
                    <strong>@product.SalePrice.Value.ToString("C")</strong>
                </li>
            }
        </ul>
    }
</article>
using Magelia.WebStore.Client.Web.UI.Sample.Models.Catalog;
using Magelia.WebStore.Client.Web.UI.Sample.Runtime;
using Magelia.WebStore.Client.Web.UI.Sample.Runtime.MVC;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
 
namespace Magelia.WebStore.Client.Web.UI.Sample.Controllers
{
    public class CatalogController : BaseController
    {
        public CatalogController(SampleSiteContext sampleSiteContext)
            : base(sampleSiteContext)
        { }
 
        [HttpGet]
        public ActionResult Category(Guid categoryId)
        {
            CategoryViewModel viewModel = new CategoryViewModel { 
                CatalogName = this.SampleSiteContext.Catalog.Name, 
                CatalogCode = this.SampleSiteContext.Catalog.Code 
            };
 
            Magelia.WebStore.Client.Category category = this.SampleSiteContext.CatalogClient.Categories
                                                            .Expand("ParentCategoryHierarchies/ParentCategory/ParentCategoryHierarchies/ParentCategory")
                                                            .Expand("ParentCategoryHierarchies/ParentCategory/ChildCategoryHierarchies/Category")
                                                            .Expand("ChildCategoryHierarchies/Category")
                                                            .Where(c => c.CategoryId == categoryId)
                                                            .FirstOrDefault();
 
            IQueryable<Magelia.WebStore.Client.CategoryProduct> categoryProductsQuery = 
                this.SampleSiteContext.CatalogClient.CategoryProducts
                    .Expand("Product/Brand")
                    .Expand(String.Format("Product/{0}/Attributes/Files", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                    .Expand(String.Format("Product/{0}/Prices", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                    .Expand(String.Format("Product/{0}/PriceWithLowerQuantity/DiscountDetails", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                    .Expand(String.Format("Product/{0}/PriceWithLowerQuantity/DiscountDetails/Discount", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                    .Expand(String.Format("Product/{0}/DefaultVariantProduct/Brand", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                    .Expand(String.Format("Product/{0}/DefaultVariantProduct/Prices", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                    .Expand(String.Format("Product/{0}/DefaultVariantProduct/PriceWithLowerQuantity/DiscountDetails", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                    .Expand(String.Format("Product/{0}/DefaultVariantProduct/PriceWithLowerQuantity/DiscountDetails/Discount", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                    .Expand(String.Format("Product/{0}/DefaultVariantProduct/Attributes/Files", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                    .Where(cp => cp.CategoryId == categoryId && !(cp.Product is Magelia.WebStore.Client.VariantProduct));
     
 
            List<Magelia.WebStore.Client.CategoryProduct> categoryProducts = categoryProductsQuery.ToList();
 
            viewModel.Products = categoryProducts
                .Select(
                    cp =>
                    {
                        ProductViewModel product = new ProductViewModel
                        {
                            BrandId = cp.Product.Brand != null ? cp.Product.Brand.BrandId : new Nullable<Guid>(),
                            BrandName = cp.Product.Brand != null ? cp.Product.Brand.Code : null,
                            CatalogCode = this.SampleSiteContext.Catalog.Code,
                            CatalogName = this.SampleSiteContext.Catalog.Name,
                            Description = cp.Product.ShortDescription,
                            IsVariable = cp.Product is Magelia.WebStore.Client.VariableProduct,
                            Name = cp.Product.Name,
                            ProductId = cp.Product.ProductId
                        };
                        Magelia.WebStore.Client.ReferenceProduct referenceProduct = product.IsVariable ? (cp.Product as Magelia.WebStore.Client.VariableProduct).DefaultVariantProduct : (Magelia.WebStore.Client.ReferenceProduct)cp.Product;
                        Magelia.WebStore.Client.File mainImage = referenceProduct.Attributes.Where(pr => pr.Code.Equals("MainImage", StringComparison.OrdinalIgnoreCase)).SelectMany(pr => pr.Files).FirstOrDefault();
                        if (mainImage != default(Magelia.WebStore.Client.File))
                        {
                            product.ImageUrl = mainImage.Path;
                            product.ImageAlternateText = mainImage.AlternateText;
                        }
                        if (referenceProduct.BrandId.HasValue)
                        {
                            product.BrandId = referenceProduct.BrandId;
                            product.BrandName = referenceProduct.Brand.Code;
                        }
                        product.CutPrice = referenceProduct.PriceWithLowerQuantity.CutPriceIncludingTaxes;
                        product.SalePrice = referenceProduct.PriceWithLowerQuantity.SalePriceIncludingDiscountAndTaxes;
                        product.Quantities = this.GetProductAvailableQuantities(referenceProduct).ToList();
                        return product;
                    }
            )
            .ToList();
            return this.View(viewModel);
        }
 
        private IEnumerable<SelectListItem> GetProductAvailableQuantities(Magelia.WebStore.Client.ReferenceProduct referenceProduct)
        {
            for (Int32 i = 1; i <= 50; i++)
            {
                Int32 quantity = i;
                foreach (Magelia.WebStore.Client.Price price in referenceProduct.Prices.OrderByDescending(p => p.Quantity))
                {
                    quantity -= (quantity / price.Quantity) * price.Quantity;
                }
                if (quantity == 0)
                {
                    String stringifiedQuantity = i.ToString();
                    yield return new SelectListItem { Value = stringifiedQuantity, Text = stringifiedQuantity };
                }
            }
        }
    }
}

Access Catalog Information

How to Build a Product Page

For catalog navigation to be complete, we will need to display product details when the user selects a product from a product list. It is possible for a product to retrieve certain information such as: details, variants (size, color, etc.) price and promotions or even merchanidising relations (cross-selling and up-selling).

How to obtain product information

Iniitally, it is useful to retrieve selected product details, including the name, the brand, the description, but also the associated visuals. We retrieve this information with the help of the selected product identifier:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
 
namespace Magelia.WebStore.Client.Web.UI.Sample.Models.Catalog
{
    public class ProductViewModel
    {
        public Guid ProductId { get; set; }
        public String Name { get; set; }
        public String ImageUrl { get; set; }
        public String ImageAlternateText { get; set; }
        public Guid? BrandId { get; set; }
        public String BrandName { get; set; }
        public String Description { get; set; }
        public String CatalogName { get; set; }
        public String CatalogCode { get; set; }
    }
}
@model Magelia.WebStore.Client.Web.UI.Sample.Models.Catalog.ProductViewModel
@{
    ViewBag.Title = Magelia.WebStore.Client.Web.UI.Sample.Resources.Views.Catalog.Product.PageTitle;
}
 
<article id="mainview">
    <div id="description">
        <h1>@this.Model.Name</h1>
        <p>@this.Model.BrandName</p>
        <p>@this.Model.Description</p>
    </div>
    <div id="images">
        @Html.Image(this.Model.ImageUrl, this.Model.ImageAlternateText)
    </div>
</article>
using Magelia.WebStore.Client.Web.UI.Sample.Models.Catalog;
using Magelia.WebStore.Client.Web.UI.Sample.Runtime;
using Magelia.WebStore.Client.Web.UI.Sample.Runtime.MVC;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
 
public class CatalogController : BaseController
{
    // …
 
    [HttpGet]
    public ActionResult Product(Guid productId, Nullable<Guid> variantId)
    {
        Magelia.WebStore.Client.ReferenceProduct referenceProduct;
        Magelia.WebStore.Client.BaseProduct product = this.SampleSiteContext.CatalogClient.Products
                                                        .Expand("Brand")
                                                        .Expand(String.Format("{0}/Attributes/Files", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand(String.Format("{0}/PriceWithLowerQuantity", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand(String.Format("{0}/Prices", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand(String.Format("{0}/Prices/DiscountDetails", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand(String.Format("{0}/Prices/DiscountDetails/Discount", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand("ProductCategories/Category/ParentCategoryHierarchies/ParentCategory/ParentCategoryHierarchies")
                                                        .Expand(String.Format("{0}/VariantProducts/Brand", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/PriceWithLowerQuantity", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/Prices", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/Prices/DiscountDetails", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/Prices/DiscountDetails/Discount", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/Attributes/Files", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Where(p => p.ProductId == productId)
                                                        .FirstOrDefault();
 
        ProductViewModel viewModel = new ProductViewModel
        {
            Name = product.Name,
            Description = product.LongDescription,
            CatalogCode = this.SampleSiteContext.Catalog.Code,
            CatalogName = this.SampleSiteContext.Catalog.Name
        };
 
        referenceProduct = product as Magelia.WebStore.Client.ReferenceProduct;
 
        if (referenceProduct.BrandId.HasValue)
        {
            viewModel.BrandId = referenceProduct.BrandId;
            viewModel.BrandName = referenceProduct.Brand.Code;
        }
 
        viewModel.ProductId = referenceProduct.ProductId;
 
        Magelia.WebStore.Client.File mainImage = referenceProduct.Attributes.Where(a => a.Code.Equals("MainImage", StringComparison.OrdinalIgnoreCase)).SelectMany(p => p.Files).FirstOrDefault();
        if (mainImage != default(Magelia.WebStore.Client.File))
        {
            viewModel.ImageUrl = mainImage.Path;
            viewModel.ImageAlternateText = mainImage.AlternateText;
        }
 
        return this.View(viewModel);
    }
}

How to obtain stock information

An important piece of information in any e-commerce site concerning the products, is the stock. Indeed, it is useful to retrieve information regarding product availability, status, available quantities, or bundles.

In Magelia WebStore, the stock information is retrieved via the service GetInventory. The service allows you to get stock information for one or more product identifiers and a location.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
 
namespace Magelia.WebStore.Client.Web.UI.Sample.Models.Catalog
{
    public class ProductViewModel
    {
        public Guid ProductId { get; set; }
        public String Name { get; set; }
        public String ImageUrl { get; set; }
        public String ImageAlternateText { get; set; }
        public Guid? BrandId { get; set; }
        public String BrandName { get; set; }
        public String Description { get; set; }
        public String CatalogName { get; set; }
        public String CatalogCode { get; set; }
        private IEnumerable<SelectListItem> _quantities;
 
        public IEnumerable<SelectListItem> Quantities
        {
            get
            {
                if (this._quantities == default(IEnumerable<SelectListItem>))
                {
                    this._quantities = Enumerable.Empty<SelectListItem>();
                }
                return this._quantities;
            }
            set
            {
                this._quantities = value;
            }
        }
    }
}
@model Magelia.WebStore.Client.Web.UI.Sample.Models.Catalog.ProductViewModel
@{
    ViewBag.Title = Magelia.WebStore.Client.Web.UI.Sample.Resources.Views.Catalog.Product.PageTitle;
}
 
<article id="mainview">
    <div id="description">
        <h1>@this.Model.Name</h1>
        <p>@this.Model.BrandName</p>
 
        <p>
            @if (this.Model.Quantities.Count() > 0 && this.Model.SalePrice.HasValue)
            {
                String ddlQuantityId = Guid.NewGuid().ToString("N");
                <label for="@ddlQuantityId">
                    @Magelia.WebStore.Client.Web.UI.Sample.Resources.Views.Catalog.Product.QuantityLabelText
                </label>
                <select name="quantity" id="@ddlQuantityId">
                    @foreach (var quantity in this.Model.Quantities)
                    {
                        <option value="@quantity.Value">@quantity.Text</option>
                    }
                </select>
            }
            else
            { 
                @Magelia.WebStore.Client.Web.UI.Sample.Resources.Views.Catalog.Product.OutOfStock
            }
        </p>
 
        <p>@this.Model.Description</p>
    </div>
    <div id="images">
        @Html.Image(this.Model.ImageUrl, this.Model.ImageAlternateText)
    </div>
</article>
using Magelia.WebStore.Client.Web.UI.Sample.Models.Catalog;
using Magelia.WebStore.Client.Web.UI.Sample.Runtime;
using Magelia.WebStore.Client.Web.UI.Sample.Runtime.MVC;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
 
public class CatalogController : BaseController
{
    // ...
 
    private IEnumerable<SelectListItem> GetProductAvailableQuantities(Magelia.WebStore.Client.ReferenceProduct referenceProduct)
    {
        for (Int32 i = 1; i <= 50; i++)
        {
            Int32 quantity = i;
            foreach (Magelia.WebStore.Client.Price price in referenceProduct.Prices.OrderByDescending(p => p.Quantity))
            {
                quantity -= (quantity / price.Quantity) * price.Quantity;
            }
            if (quantity == 0)
            {
                String stringifiedQuantity = i.ToString();
                yield return new SelectListItem { Value = stringifiedQuantity, Text = stringifiedQuantity };
            }
        }
    }
 
    [HttpGet]
    public ActionResult Product(Guid productId, Nullable<Guid> variantId)
    {
        Magelia.WebStore.Client.ReferenceProduct referenceProduct;
        Magelia.WebStore.Client.BaseProduct product = this.SampleSiteContext.CatalogClient.Products
                                                        .Expand("Brand")
                                                        .Expand(String.Format("{0}/Attributes/Files", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand(String.Format("{0}/PriceWithLowerQuantity", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand(String.Format("{0}/Prices", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand(String.Format("{0}/Prices/DiscountDetails", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand(String.Format("{0}/Prices/DiscountDetails/Discount", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand("ProductCategories/Category/ParentCategoryHierarchies/ParentCategory/ParentCategoryHierarchies")
                                                        .Expand(String.Format("{0}/VariantProducts/Brand", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/PriceWithLowerQuantity", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/Prices", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/Prices/DiscountDetails", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/Prices/DiscountDetails/Discount", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/Attributes/Files", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Where(p => p.ProductId == productId)
                                                        .FirstOrDefault();
 
        ProductViewModel viewModel = new ProductViewModel
        {
            Name = product.Name,
            Description = product.LongDescription,
            CatalogCode = this.SampleSiteContext.Catalog.Code,
            CatalogName = this.SampleSiteContext.Catalog.Name
        };
 
        referenceProduct = product as Magelia.WebStore.Client.ReferenceProduct;
 
        if (referenceProduct.BrandId.HasValue)
        {
            viewModel.BrandId = referenceProduct.BrandId;
            viewModel.BrandName = referenceProduct.Brand.Code;
        }
 
        viewModel.ProductId = referenceProduct.ProductId;
 
        Magelia.WebStore.Client.File mainImage = referenceProduct.Attributes.Where(a => a.Code.Equals("MainImage", StringComparison.OrdinalIgnoreCase)).SelectMany(p => p.Files).FirstOrDefault();
        if (mainImage != default(Magelia.WebStore.Client.File))
        {
            viewModel.ImageUrl = mainImage.Path;
            viewModel.ImageAlternateText = mainImage.AlternateText;
        }
  
        if (this.SampleSiteContext.StoreClient.GetInventory(new Guid[] { referenceProduct.ProductId }, this.SampleSiteContext.Location).Any(s => s.Available))
        {
            viewModel.Quantities = this.GetProductAvailableQuantities(referenceProduct);
        }
        return this.View(viewModel);
    }
}

How to obtain price information

Another piece of important information concerning the products is the price. There exists two ways for retrieving the prices of a product in Magelia WebStore. The first is via the service GetPrices allowing you to retrieve price information from one or several product identifiers, a currency identifier, a culture identifier, and a location. For example:

this.SampleSiteContext.StoreClient.GetPrices(new Guid[] {referenceProduct.ProductId },
this.SampleSiteContext.Currency.CurrencyId,
this.SampleSiteContext.Culture.LCID,
this.SampleSiteContext.Location);

La seconde, est d'utiliser la propriétés, associées au prix, sur le produit lui-même :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
 
namespace Magelia.WebStore.Client.Web.UI.Sample.Models.Catalog
{
    public class ProductViewModel
    {
        public Guid ProductId { get; set; }
        public String Name { get; set; }
        public String ImageUrl { get; set; }
        public String ImageAlternateText { get; set; }
        public Guid? BrandId { get; set; }
        public String BrandName { get; set; }
        public String Description { get; set; }
        public Decimal? SalePrice { get; set; }
        public Decimal? CutPrice { get; set; }
        public String CatalogName { get; set; }
        public String CatalogCode { get; set; }
        private IEnumerable<SelectListItem> _quantities;
 
        public IEnumerable<SelectListItem> Quantities
        {
            get
            {
                if (this._quantities == default(IEnumerable<SelectListItem>))
                {
                    this._quantities = Enumerable.Empty<SelectListItem>();
                }
                return this._quantities;
            }
            set
            {
                this._quantities = value;
            }
        }
    }
}
@model Magelia.WebStore.Client.Web.UI.Sample.Models.Catalog.ProductViewModel
@{
    ViewBag.Title = Magelia.WebStore.Client.Web.UI.Sample.Resources.Views.Catalog.Product.PageTitle;
}
 
<article id="mainview">
    <div id="description">
        <h1>@this.Model.Name</h1>
        <p>@this.Model.BrandName</p>
 
        <p>
            @if (this.Model.Quantities.Count() > 0 && this.Model.SalePrice.HasValue)
            {
                String ddlQuantityId = Guid.NewGuid().ToString("N");
                <label for="@ddlQuantityId">
                    @Magelia.WebStore.Client.Web.UI.Sample.Resources.Views.Catalog.Product.QuantityLabelText
                </label>
                <select name="quantity" id="@ddlQuantityId">
                    @foreach (var quantity in this.Model.Quantities)
                    {
                        <option value="@quantity.Value">@quantity.Text</option>
                    }
                </select>
            }
            else
            { 
                @Magelia.WebStore.Client.Web.UI.Sample.Resources.Views.Catalog.Product.OutOfStock
            }
        </p>
 
        <strong id="price">@this.Model.SalePrice.Value.ToString("C")</strong>
        <p>@this.Model.Description</p>
    </div>
    <div id="images">
        @Html.Image(this.Model.ImageUrl, this.Model.ImageAlternateText)
    </div>
</article>
using Magelia.WebStore.Client.Web.UI.Sample.Models.Catalog;
using Magelia.WebStore.Client.Web.UI.Sample.Runtime;
using Magelia.WebStore.Client.Web.UI.Sample.Runtime.MVC;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
 
public class CatalogController : BaseController
{
    // ...
 
    private IEnumerable<SelectListItem> GetProductAvailableQuantities(Magelia.WebStore.Client.ReferenceProduct referenceProduct)
    {
        for (Int32 i = 1; i <= 50; i++)
        {
            Int32 quantity = i;
            foreach (Magelia.WebStore.Client.Price price in referenceProduct.Prices.OrderByDescending(p => p.Quantity))
            {
                quantity -= (quantity / price.Quantity) * price.Quantity;
            }
            if (quantity == 0)
            {
                String stringifiedQuantity = i.ToString();
                yield return new SelectListItem { Value = stringifiedQuantity, Text = stringifiedQuantity };
            }
        }
    }
 
    [HttpGet]
    public ActionResult Product(Guid productId, Nullable<Guid> variantId)
    {
        Magelia.WebStore.Client.ReferenceProduct referenceProduct;
        Magelia.WebStore.Client.BaseProduct product = this.SampleSiteContext.CatalogClient.Products
                                                        .Expand("Brand")
                                                        .Expand(String.Format("{0}/Attributes/Files", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand(String.Format("{0}/PriceWithLowerQuantity", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand(String.Format("{0}/Prices", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand(String.Format("{0}/Prices/DiscountDetails", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand(String.Format("{0}/Prices/DiscountDetails/Discount", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand("ProductCategories/Category/ParentCategoryHierarchies/ParentCategory/ParentCategoryHierarchies")
                                                        .Expand(String.Format("{0}/VariantProducts/Brand", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/PriceWithLowerQuantity", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/Prices", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/Prices/DiscountDetails", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/Prices/DiscountDetails/Discount", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/Attributes/Files", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Where(p => p.ProductId == productId)
                                                        .FirstOrDefault();
 
        ProductViewModel viewModel = new ProductViewModel
        {
            Name = product.Name,
            Description = product.LongDescription,
            CatalogCode = this.SampleSiteContext.Catalog.Code,
            CatalogName = this.SampleSiteContext.Catalog.Name
        };
 
        referenceProduct = product as Magelia.WebStore.Client.ReferenceProduct;
        
        if (referenceProduct.BrandId.HasValue)
        {
            viewModel.BrandId = referenceProduct.BrandId;
            viewModel.BrandName = referenceProduct.Brand.Code;
        }
 
        viewModel.ProductId = referenceProduct.ProductId;
 
        Magelia.WebStore.Client.File mainImage = referenceProduct.Attributes.Where(a => a.Code.Equals("MainImage", StringComparison.OrdinalIgnoreCase)).SelectMany(p => p.Files).FirstOrDefault();
        if (mainImage != default(Magelia.WebStore.Client.File))
        {
            viewModel.ImageUrl = mainImage.Path;
            viewModel.ImageAlternateText = mainImage.AlternateText;
        }
 
        viewModel.SalePrice = referenceProduct.PriceWithLowerQuantity.SalePriceIncludingDiscountAndTaxes;
        viewModel.CutPrice = referenceProduct.PriceWithLowerQuantity.CutPriceIncludingTaxes;
 
        if (this.SampleSiteContext.StoreClient.GetInventory(new Guid[] { referenceProduct.ProductId }, this.SampleSiteContext.Location).Any(s => s.Available))
        {
            viewModel.Quantities = this.GetProductAvailableQuantities(referenceProduct);
        }
        return this.View(viewModel);
    }
}

Access Catalog Information

How to obtain products with variants

A product can have one or several variants like size, color, etc. It is thus necessary to be able to list the different variants for a product, their price, and their availability. For this, we have VariableProduct type products in Magelia WebStore:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
 
namespace Magelia.WebStore.Client.Web.UI.Sample.Models.Catalog
{
    public class ProductViewModel
    {
        public Guid ProductId { get; set; }
        public Guid? VariantProductId { get; set; }
        public String Name { get; set; }
        public String ImageUrl { get; set; }
        public String ImageAlternateText { get; set; }
        public Guid? BrandId { get; set; }
        public String BrandName { get; set; }
        public String Description { get; set; }
        public Decimal? SalePrice { get; set; }
        public Decimal? CutPrice { get; set; }
        public Boolean IsVariable { get; set; }
        public String CatalogName { get; set; }
        public String CatalogCode { get; set; }
        private IEnumerable<SelectListItem> _quantities;
        private IEnumerable<SelectListItem> _variants;
 
        public IEnumerable<SelectListItem> Quantities
        {
            get
            {
                if (this._quantities == default(IEnumerable<SelectListItem>))
                {
                    this._quantities = Enumerable.Empty<SelectListItem>();
                }
                return this._quantities;
            }
            set
            {
                this._quantities = value;
            }
        }
 
        public IEnumerable<SelectListItem> Variants
        {
            get
            {
                if (this._variants == default(IEnumerable<SelectListItem>))
                {
                    this._variants = Enumerable.Empty<SelectListItem>();
                }
                return this._variants;
            }
            set
            {
                this._variants = value;
            }
        }
    }
}
@model Magelia.WebStore.Client.Web.UI.Sample.Models.Catalog.ProductViewModel
@{
    ViewBag.Title = Magelia.WebStore.Client.Web.UI.Sample.Resources.Views.Catalog.Product.PageTitle;
}
 
<article id="mainview">
    <div id="description">
        <h1>@this.Model.Name</h1>
        <p>@this.Model.BrandName</p>
 
        <p>
            @if (this.Model.Quantities.Count() > 0 && this.Model.SalePrice.HasValue)
            {
                String ddlQuantityId = Guid.NewGuid().ToString("N");
                <label for="@ddlQuantityId">
                    @Magelia.WebStore.Client.Web.UI.Sample.Resources.Views.Catalog.Product.QuantityLabelText
                </label>
                <select name="quantity" id="@ddlQuantityId">
                    @foreach (var quantity in this.Model.Quantities)
                    {
                        <option value="@quantity.Value">@quantity.Text</option>
                    }
                </select>
            }
            else
            { 
                @Magelia.WebStore.Client.Web.UI.Sample.Resources.Views.Catalog.Product.OutOfStock
            }
        </p>
 
        @if (this.Model.IsVariable && this.Model.Variants.Any())
        {
            String ddlVariantsId = Guid.NewGuid().ToString("N");
        <p>
                <label for="@ddlVariantsId">
                @Magelia.WebStore.Client.Web.UI.Sample.Resources.Views.Catalog.Product.VariantsLabelText
            </label>
            @Html.DropDownList("VariantsChoice", this.Model.Variants, new { id = ddlVariantsId })
            <script type="text/javascript">
                //<![CDATA[
                $('#@ddlVariantsId').change(function () { document.location.href = '@Url.Action("Product", new { productId = this.Model.VariantProductId })' + '/' + $(this).val(); });
                //]]>
            </script>
        </p>
        }
 
        <strong id="price">@this.Model.SalePrice.Value.ToString("C")</strong>
        <p>@this.Model.Description</p>
    </div>
    <div id="images">
        @Html.Image(this.Model.ImageUrl, this.Model.ImageAlternateText)
    </div>
</article>
using Magelia.WebStore.Client.Web.UI.Sample.Models.Catalog;
using Magelia.WebStore.Client.Web.UI.Sample.Runtime;
using Magelia.WebStore.Client.Web.UI.Sample.Runtime.MVC;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
 
public class CatalogController : BaseController
{
    // ...
 
    private IEnumerable<SelectListItem> GetProductAvailableQuantities(Magelia.WebStore.Client.ReferenceProduct referenceProduct)
    {
        for (Int32 i = 1; i <= 50; i++)
        {
            Int32 quantity = i;
            foreach (Magelia.WebStore.Client.Price price in referenceProduct.Prices.OrderByDescending(p => p.Quantity))
            {
                quantity -= (quantity / price.Quantity) * price.Quantity;
            }
            if (quantity == 0)
            {
                String stringifiedQuantity = i.ToString();
                yield return new SelectListItem { Value = stringifiedQuantity, Text = stringifiedQuantity };
            }
        }
    }
 
    [HttpGet]
    public ActionResult Product(Guid productId, Nullable<Guid> variantId)
    {
        Magelia.WebStore.Client.ReferenceProduct referenceProduct;
        Magelia.WebStore.Client.BaseProduct product = this.SampleSiteContext.CatalogClient.Products
                                                        .Expand("Brand")
                                                        .Expand(String.Format("{0}/Attributes/Files", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand(String.Format("{0}/PriceWithLowerQuantity", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand(String.Format("{0}/Prices", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand(String.Format("{0}/Prices/DiscountDetails", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand(String.Format("{0}/Prices/DiscountDetails/Discount", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand("ProductCategories/Category/ParentCategoryHierarchies/ParentCategory/ParentCategoryHierarchies")
                                                        .Expand(String.Format("{0}/VariantProducts/Brand", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/PriceWithLowerQuantity", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/Prices", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/Prices/DiscountDetails", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/Prices/DiscountDetails/Discount", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/Attributes/Files", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Where(p => p.ProductId == productId)
                                                        .FirstOrDefault();
 
        ProductViewModel viewModel = new ProductViewModel
        {
            Name = product.Name,
            Description = product.LongDescription,
            IsVariable = product is Magelia.WebStore.Client.VariableProduct,
            CatalogCode = this.SampleSiteContext.Catalog.Code,
            CatalogName = this.SampleSiteContext.Catalog.Name
        };
 
        if (viewModel.IsVariable)
        {
            Magelia.WebStore.Client.VariableProduct variableProduct = product as Magelia.WebStore.Client.VariableProduct;
            Magelia.WebStore.Client.VariantProduct variant = variableProduct.VariantProducts.OrderByDescending(vp => vp.ProductId == variantId).ThenByDescending(vp => vp.IsDefault).First();
            viewModel.VariantProductId = product.ProductId;
            referenceProduct = variant;
 
viewModel.VariantProductId = product.ProductId;
viewModel.Variants = variableProduct.VariantProducts
                                                                .OrderBy(vp => vp.Order)
                                                                .Select(
                                                                    v => new SelectListItem
                                                                    {
                                                                        Value = v.ProductId.ToString(),
                                                                        Selected = v.ProductId == referenceProduct.ProductId,
                                                                        Text = String.Join(
                                                                                        " - ",
                                                                                        v.Attributes
                                                                                            .Select(
                                                                                                a =>
                                                                                                {
                                                                                                    String value = String.Empty;
                                                                                                    switch (a.TypeCode.ToLowerInvariant())
                                                                                                    {
                                                                                                        case "boolean":
                                                                                                            value = a.BooleanValue.HasValue && a.BooleanValue.Value ? 
                                                                                                                Magelia.WebStore.Client.Web.UI.Sample.Resources.Controllers.CatalogController.Yes :
                                                                                                                Magelia.WebStore.Client.Web.UI.Sample.Resources.Controllers.CatalogController.No;
                                                                                                            break;
                                                                                                        case "integer":
                                                                                                            value = a.IntValue.ToString();
                                                                                                            break;
                                                                                                        case "decimal":
                                                                                                            value = a.DecimalValue.ToString();
                                                                                                            break;
                                                                                                        case "datetime":
                                                                                                            value = a.DateTimeValue.ToString();
                                                                                                            break;
                                                                                                        case "list":
                                                                                                            value = a.ListValue;
                                                                                                            break;
                                                                                                        case "string":
                                                                                                            value = a.StringValue;
                                                                                                            break;
                                                                                                        default:
                                                                                                            return value;
                                                                                                    }
                                                                                                    return String.IsNullOrEmpty(value) ? String.Empty : String.Format("{0} : {1}", String.IsNullOrEmpty(a.Name) ? a.Code : a.Name, value);
                                                                                                }
                                                                                            )
                                                                                            .Where(s => !String.IsNullOrEmpty(s))
                                                                                            .OrderBy(s => s)
                                                                                )
                                                                    }
                                                                );
        }
        else
        {
            referenceProduct = product as Magelia.WebStore.Client.ReferenceProduct;
        }
 
        if (referenceProduct.BrandId.HasValue)
        {
            viewModel.BrandId = referenceProduct.BrandId;
            viewModel.BrandName = referenceProduct.Brand.Code;
        }
 
        viewModel.ProductId = referenceProduct.ProductId;
 
        Magelia.WebStore.Client.File mainImage = referenceProduct.Attributes.Where(a => a.Code.Equals("MainImage", StringComparison.OrdinalIgnoreCase)).SelectMany(p => p.Files).FirstOrDefault();
        if (mainImage != default(Magelia.WebStore.Client.File))
        {
            viewModel.ImageUrl = mainImage.Path;
            viewModel.ImageAlternateText = mainImage.AlternateText;
        }
 
        viewModel.SalePrice = referenceProduct.PriceWithLowerQuantity.SalePriceIncludingDiscountAndTaxes;
        viewModel.CutPrice = referenceProduct.PriceWithLowerQuantity.CutPriceIncludingTaxes;
 
        if (this.SampleSiteContext.StoreClient.GetInventory(new Guid[] { referenceProduct.ProductId }, this.SampleSiteContext.Location).Any(s => s.Available))
        {
            viewModel.Quantities = this.GetProductAvailableQuantities(referenceProduct);
        }
        return this.View(viewModel);
    }
}

You will also need to add the following route to you MVC application:

routes.MapRoute("Product", "Catalog/Product/{productId}/{variantId}", new { controller = "Catalog", action = "Product", variantId = UrlParameter.Optional });

Access Catalog Information

How to obtain cross- and up- selling products

You can also retrieve products linked to another product to implement upselling and cross-selling strategies.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
 
namespace Magelia.WebStore.Client.Web.UI.Sample.Models.Catalog
{
    public class ProductViewModel
    {
        public Guid ProductId { get; set; }
        public Guid? VariantProductId { get; set; }
        public String Name { get; set; }
        public String ImageUrl { get; set; }
        public String ImageAlternateText { get; set; }
        public Guid? BrandId { get; set; }
        public String BrandName { get; set; }
        public String Description { get; set; }
        public Decimal? SalePrice { get; set; }
        public Decimal? CutPrice { get; set; }
        public Boolean IsVariable { get; set; }
        public String CatalogName { get; set; }
        public String CatalogCode { get; set; }
        private IEnumerable<SelectListItem> _quantities;
        private IEnumerable<SelectListItem> _variants;
        private IEnumerable<RelatedProduct> _relatedProducts;
 
        public IEnumerable<SelectListItem> Quantities
        {
            get
            {
                if (this._quantities == default(IEnumerable<SelectListItem>))
                {
                    this._quantities = Enumerable.Empty<SelectListItem>();
                }
                return this._quantities;
            }
            set
            {
                this._quantities = value;
            }
        }
 
        public IEnumerable<SelectListItem> Variants
        {
            get
            {
                if (this._variants == default(IEnumerable<SelectListItem>))
                {
                    this._variants = Enumerable.Empty<SelectListItem>();
                }
                return this._variants;
            }
            set
            {
                this._variants = value;
            }
        }
 
        public IEnumerable<RelatedProduct> RelatedProducts
        {
            get
            {
                if (this._relatedProducts == default(IEnumerable<RelatedProduct>))
                {
                    this._relatedProducts = Enumerable.Empty<RelatedProduct>();
                }
                return this._relatedProducts;
            }
            set
            {
                this._relatedProducts = value;
            }
        }
 
        public class RelatedProduct
        {
            public Guid ProductId { get; set; }
            public String Name { get; set; }
            public String ImageUrl { get; set; }
            public String ImageAlternateText { get; set; }
            public Nullable<Guid> BrandId { get; set; }
            public String BrandName { get; set; }
            public Nullable<Decimal> SalePrice { get; set; }
            public Nullable<Decimal> CutPrice { get; set; }
            public Boolean IsVariable { get; set; }
            public Boolean IsVariant { get; set; }
            public Nullable<Guid> VariableProductId { get; set; }
        }
    }
}
@model Magelia.WebStore.Client.Web.UI.Sample.Models.Catalog.ProductViewModel
@{
    ViewBag.Title = Magelia.WebStore.Client.Web.UI.Sample.Resources.Views.Catalog.Product.PageTitle;
}
 
<article id="mainview">
    <div id="description">
        <h1>@this.Model.Name</h1>
        <p>@this.Model.BrandName</p>
 
        <p>
            @if (this.Model.Quantities.Count() > 0 && this.Model.SalePrice.HasValue)
            {
                String ddlQuantityId = Guid.NewGuid().ToString("N");
                <label for="@ddlQuantityId">
                    @Magelia.WebStore.Client.Web.UI.Sample.Resources.Views.Catalog.Product.QuantityLabelText
                </label>
                <select name="quantity" id="@ddlQuantityId">
                    @foreach (var quantity in this.Model.Quantities)
                    {
                        <option value="@quantity.Value">@quantity.Text</option>
                    }
                </select>
            }
            else
            { 
                @Magelia.WebStore.Client.Web.UI.Sample.Resources.Views.Catalog.Product.OutOfStock
            }
        </p>
 
        @if (this.Model.IsVariable && this.Model.Variants.Any())
        {
            String ddlVariantsId = Guid.NewGuid().ToString("N");
        <p>
                <label for="@ddlVariantsId">
                @Magelia.WebStore.Client.Web.UI.Sample.Resources.Views.Catalog.Product.VariantsLabelText
            </label>
            @Html.DropDownList("VariantsChoice", this.Model.Variants, new { id = ddlVariantsId })
            <script type="text/javascript">
                //<![CDATA[
                $('#@ddlVariantsId').change(function () { document.location.href = '@Url.Action("Product", new { productId = this.Model.VariantProductId })' + '/' + $(this).val(); });
                //]]>
            </script>
        </p>
        }
 
        <strong id="price">@this.Model.SalePrice.Value.ToString("C")</strong>
        <p>@this.Model.Description</p>
    </div>
    <div id="images">
        @Html.Image(this.Model.ImageUrl, this.Model.ImageAlternateText)
    </div>
</article>
 
@if (this.Model.RelatedProducts.Count() > 0)
{
    <h4 class="clear related">
        @Magelia.WebStore.Client.Web.UI.Sample.Resources.Views.Catalog.Product.RelatedTitleText
    </h4>
    <article id="grid">
        <ul id="items">
            @foreach (var relatedProduct in this.Model.RelatedProducts)
            { 
                <li>
                <a href="@Url.Action("Product", "Catalog", new { productId = relatedProduct.VariableProductId, variantId = relatedProduct.ProductId }, null)">
                    @Html.Image(relatedProduct.ImageUrl, relatedProduct.ImageAlternateText)
                </a>
                <a href="@Url.Action("Product", "Catalog", new { productId = relatedProduct.VariableProductId, variantId = relatedProduct.ProductId }, null)" class="title">
                    @relatedProduct.Name
                </a>
                <strong>@relatedProduct.SalePrice.Value.ToString("C")</strong>
            </li>
            }
        </ul>
    </article>
}
using Magelia.WebStore.Client.Web.UI.Sample.Models.Catalog;
using Magelia.WebStore.Client.Web.UI.Sample.Runtime;
using Magelia.WebStore.Client.Web.UI.Sample.Runtime.MVC;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
 
public class CatalogController : BaseController
{
    // ...
 
    private IEnumerable<SelectListItem> GetProductAvailableQuantities(Magelia.WebStore.Client.ReferenceProduct referenceProduct)
    {
        for (Int32 i = 1; i <= 50; i++)
        {
            Int32 quantity = i;
            foreach (Magelia.WebStore.Client.Price price in referenceProduct.Prices.OrderByDescending(p => p.Quantity))
            {
                quantity -= (quantity / price.Quantity) * price.Quantity;
            }
            if (quantity == 0)
            {
                String stringifiedQuantity = i.ToString();
                yield return new SelectListItem { Value = stringifiedQuantity, Text = stringifiedQuantity };
            }
        }
    }
 
    [HttpGet]
    public ActionResult Product(Guid productId, Nullable<Guid> variantId)
    {
        Magelia.WebStore.Client.ReferenceProduct referenceProduct;
        Magelia.WebStore.Client.BaseProduct product = this.SampleSiteContext.CatalogClient.Products
                                                        .Expand("Brand")
                                                        .Expand(String.Format("{0}/Attributes/Files", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand(String.Format("{0}/PriceWithLowerQuantity", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand(String.Format("{0}/Prices", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand(String.Format("{0}/Prices/DiscountDetails", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand(String.Format("{0}/Prices/DiscountDetails/Discount", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                                        .Expand("ProductCategories/Category/ParentCategoryHierarchies/ParentCategory/ParentCategoryHierarchies")
                                                        .Expand(String.Format("{0}/VariantProducts/Brand", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/PriceWithLowerQuantity", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/Prices", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/Prices/DiscountDetails", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/Prices/DiscountDetails/Discount", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Expand(String.Format("{0}/VariantProducts/Attributes/Files", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                                        .Where(p => p.ProductId == productId)
                                                        .FirstOrDefault();
 
        ProductViewModel viewModel = new ProductViewModel
        {
            Name = product.Name,
            Description = product.LongDescription,
            IsVariable = product is Magelia.WebStore.Client.VariableProduct,
            CatalogCode = this.SampleSiteContext.Catalog.Code,
            CatalogName = this.SampleSiteContext.Catalog.Name,
 RelatedProducts = ((DataServiceQuery<Magelia.WebStore.Client.CrossSellingProductLink>)this.SampleSiteContext.CatalogClient.ProductLinks
                                        .OfType<Magelia.WebStore.Client.CrossSellingProductLink>())
                                        .Expand("LinkedProduct/Brand")
                                        .Expand(String.Format("LinkedProduct/{0}/PriceWithLowerQuantity", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                        .Expand(String.Format("LinkedProduct/{0}/Attributes/Files", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.ReferenceProduct))))
                                        .Expand(String.Format("LinkedProduct/{0}/DefaultVariantProduct/PriceWithLowerQuantity", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                        .Expand(String.Format("LinkedProduct/{0}/DefaultVariantProduct/Attributes/Files", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariableProduct))))
                                        .Expand(String.Format("LinkedProduct/{0}/VariableProduct", this.SampleSiteContext.CatalogClient.ResolveName(typeof(Magelia.WebStore.Client.VariantProduct))))
                                        .Where(pl => pl.ProductId == productId)
                                        .ToList()
                                        .Select(pl =>
                                        {
                                            Magelia.WebStore.Client.ReferenceProduct relatedReferenceProduct;
                                            ProductViewModel.RelatedProduct relatedProduct = new ProductViewModel.RelatedProduct { ProductId = pl.LinkedProductId, IsVariable = pl.LinkedProduct is Magelia.WebStore.Client.VariableProduct, IsVariant = pl.LinkedProduct is Magelia.WebStore.Client.VariantProduct };
                                            if (relatedProduct.IsVariable)
                                            {
                                                relatedReferenceProduct = (pl.LinkedProduct as Magelia.WebStore.Client.VariableProduct).DefaultVariantProduct;
                                            }
                                            else
                                            {
                                                relatedReferenceProduct = pl.LinkedProduct as Magelia.WebStore.Client.ReferenceProduct;
                                            }
                                            if (relatedProduct.IsVariant)
                                            {
                                                Magelia.WebStore.Client.VariantProduct variant = pl.LinkedProduct as Magelia.WebStore.Client.VariantProduct;
                                                relatedProduct.VariableProductId = variant.VariableProductId;
                                                relatedProduct.Name = variant.Name;
                                            }
                                            else
                                            {
                                                relatedProduct.Name = pl.LinkedProduct.Name;
                                            }
                                            if (pl.LinkedProduct.BrandId.HasValue)
                                            {
                                                relatedProduct.BrandId = pl.LinkedProduct.BrandId.Value;
                                                relatedProduct.BrandName = pl.LinkedProduct.Brand.Code;
                                            }
                                            Magelia.WebStore.Client.File relatedProductMainImage = relatedReferenceProduct.Attributes.Where(a => a.Code.Equals("MainImage", StringComparison.OrdinalIgnoreCase)).SelectMany(p => p.Files).FirstOrDefault();
                                            if (relatedProductMainImage != default(Magelia.WebStore.Client.File))
                                            {
                                                relatedProduct.ImageUrl = relatedProductMainImage.Path;
                                                relatedProduct.ImageAlternateText = relatedProductMainImage.AlternateText;
                                            }
                                            relatedProduct.SalePrice = relatedReferenceProduct.PriceWithLowerQuantity.SalePriceIncludingDiscountAndTaxes;
                                            relatedProduct.CutPrice = relatedReferenceProduct.PriceWithLowerQuantity.CutPriceIncludingTaxes;
                                            return relatedProduct;
                                        })
 
        };
 
        if (viewModel.IsVariable)
        {
            Magelia.WebStore.Client.VariableProduct variableProduct = product as Magelia.WebStore.Client.VariableProduct;
            Magelia.WebStore.Client.VariantProduct variant = variableProduct.VariantProducts.OrderByDescending(vp => vp.ProductId == variantId).ThenByDescending(vp => vp.IsDefault).First();
            viewModel.VariantProductId = product.ProductId;
            referenceProduct = variant;
 
viewModel.VariantProductId = product.ProductId;
viewModel.Variants = variableProduct.VariantProducts
                                                                .OrderBy(vp => vp.Order)
                                                                .Select(
                                                                    v => new SelectListItem
                                                                    {
                                                                        Value = v.ProductId.ToString(),
                                                                        Selected = v.ProductId == referenceProduct.ProductId,
                                                                        Text = String.Join(
                                                                                        " - ",
                                                                                        v.Attributes
                                                                                            .Select(
                                                                                                a =>
                                                                                                {
                                                                                                    String value = String.Empty;
                                                                                                    switch (a.TypeCode.ToLowerInvariant())
                                                                                                    {
                                                                                                        case "boolean":
                                                                                                            value = a.BooleanValue.HasValue && a.BooleanValue.Value ? 
                                                                                                                Magelia.WebStore.Client.Web.UI.Sample.Resources.Controllers.CatalogController.Yes :
                                                                                                                Magelia.WebStore.Client.Web.UI.Sample.Resources.Controllers.CatalogController.No;
                                                                                                            break;
                                                                                                        case "integer":
                                                                                                            value = a.IntValue.ToString();
                                                                                                            break;
                                                                                                        case "decimal":
                                                                                                            value = a.DecimalValue.ToString();
                                                                                                            break;
                                                                                                        case "datetime":
                                                                                                            value = a.DateTimeValue.ToString();
                                                                                                            break;
                                                                                                        case "list":
                                                                                                            value = a.ListValue;
                                                                                                            break;
                                                                                                        case "string":
                                                                                                            value = a.StringValue;
                                                                                                            break;
                                                                                                        default:
                                                                                                            return value;
                                                                                                    }
                                                                                                    return String.IsNullOrEmpty(value) ? String.Empty : String.Format("{0} : {1}", String.IsNullOrEmpty(a.Name) ? a.Code : a.Name, value);
                                                                                                }
                                                                                            )
                                                                                            .Where(s => !String.IsNullOrEmpty(s))
                                                                                            .OrderBy(s => s)
                                                                                )
                                                                    }
                                                                );
        }
        else
        {
            referenceProduct = product as Magelia.WebStore.Client.ReferenceProduct;
        }
 
        if (referenceProduct.BrandId.HasValue)
        {
            viewModel.BrandId = referenceProduct.BrandId;
            viewModel.BrandName = referenceProduct.Brand.Code;
        }
 
        viewModel.ProductId = referenceProduct.ProductId;
 
        Magelia.WebStore.Client.File mainImage = referenceProduct.Attributes.Where(a => a.Code.Equals("MainImage", StringComparison.OrdinalIgnoreCase)).SelectMany(p => p.Files).FirstOrDefault();
        if (mainImage != default(Magelia.WebStore.Client.File))
        {
            viewModel.ImageUrl = mainImage.Path;
            viewModel.ImageAlternateText = mainImage.AlternateText;
        }
 
        viewModel.SalePrice = referenceProduct.PriceWithLowerQuantity.SalePriceIncludingDiscountAndTaxes;
        viewModel.CutPrice = referenceProduct.PriceWithLowerQuantity.CutPriceIncludingTaxes;
 
        if (this.SampleSiteContext.StoreClient.GetInventory(new Guid[] { referenceProduct.ProductId }, this.SampleSiteContext.Location).Any(s => s.Available))
        {
            viewModel.Quantities = this.GetProductAvailableQuantities(referenceProduct);
        }
        return this.View(viewModel);
    }
}

Access Catalog Information

Download the code sample of this tutorial:
How to access catalog information - ZIP - 28.0 mo