Пример #1
0
        public ActionResult AjaxGetKitData(KitAddToCartPostModel model)
        {
            var product = new Product(model.ProductId);

            if (model.VariantId == 0)
            {
                model.VariantId = AppLogic.GetDefaultProductVariant(model.ProductId);
            }

            var variant = new ProductVariant(model.VariantId);

            var customer = HttpContext.GetCustomer();
            var cartType = model.IsWishlist
                                ? CartTypeEnum.WishCart
                                : CartTypeEnum.ShoppingCart;

            if (!product.IsAKit)
            {
                return(Content(string.Empty));
            }

            KitProductData kitData = KitProductData.Find(
                productId: product.ProductID,
                cartRecId: model.CartRecordId.HasValue
                                        ? model.CartRecordId.Value
                                        : 0,
                thisCustomer: customer);

            // Manipulate the default selections to reflect the selections made so far
            var selectedItems = model.GetSelectedItems(kitData);

            foreach (var item in kitData.Groups.SelectMany(g => g.Items))
            {
                if (selectedItems.Contains(item))
                {
                    item.IsSelected = true;
                }
                else
                {
                    item.IsSelected = false;
                }
            }

            var quantity = Math.Max(model.Quantity, 1);

            var kitAddToCartViewModel = BuildDefaultKitAddToCartViewModel(kitData, product, variant, quantity, customer, model.CartRecordId);

            var itemDisplayNames = kitAddToCartViewModel.KitGroups
                                   .SelectMany(group => group.Items)
                                   .ToDictionary(item => item.Id.ToString(), item => item.NameDisplay);

            return(Json(
                       new AjaxKitDataViewModel
            {
                SummaryHtml = ControllerContext.GetHtmlHelper().Partial(
                    partialViewName: ViewNames.KitSummaryPartial,
                    model: kitAddToCartViewModel).ToString(),
                ItemDisplayNames = itemDisplayNames
            }));
        }
Пример #2
0
        public ActionResult Detail(string name, bool?disableTemplate = null)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new HttpException(404, null);
            }

            var customer   = HttpContext.GetCustomer();
            var xmlPackage = new XmlPackage(
                packageName: name,
                customer: customer,
                htmlHelper: ControllerContext.GetHtmlHelper());

            // Make sure the engine is allowed to render this package
            if (!xmlPackage.AllowEngine)
            {
                throw new Exception("This XmlPackage is not allowed to be run from the engine. Set the package element's allowengine attribute to true to enable this package to run.");
            }

            var packageOutput = AppLogic.RunXmlPackage(xmlPackage, null, customer, customer.SkinID, true, false);

            if (disableTemplate ?? false)
            {
                return(Content(
                           packageOutput,
                           string.IsNullOrEmpty(xmlPackage.ContentType)
                                                ? "text/html"
                                                : xmlPackage.ContentType));
            }
            else
            {
                return(View(new XmlPackageViewModel
                {
                    Name = xmlPackage.PackageName,
                    MetaTitle = xmlPackage.SETitle,
                    MetaDescription = xmlPackage.SEDescription,
                    MetaKeywords = xmlPackage.SEKeywords,
                    PageTitle = xmlPackage.SectionTitle,
                    PageContent = packageOutput,
                }));
            }
        }
        public ActionResult Detail(int id, string entityType, string searchEngineName, int?productTypeFilterId)
        {
            var normalizedEntityType = AppLogic.ro_SupportedEntities
                                       .Intersect(new[] { entityType }, StringComparer.OrdinalIgnoreCase)
                                       .FirstOrDefault();

            if (normalizedEntityType == null)
            {
                throw new HttpException(404, string.Format("Unsupported entity type: {0}", entityType));
            }

            var entity   = new Entity(id, normalizedEntityType);
            var customer = ControllerContext.HttpContext.GetCustomer();

            //Make sure we've got a valid entity
            if (entity == null ||
                entity.ID == 0 ||
                entity.Published == false ||
                entity.Deleted == true)
            {
                throw new HttpException(404, null);
            }

            //Make sure that this entity is mapped to this store
            var store = new CachelessStore();

            store.StoreID = AppLogic.StoreID();
            var storeMapping = store.GetMapping(entity.EntityType, entity.ID);

            if (AppLogic.GlobalConfigBool("AllowEntityFiltering") == true && !storeMapping.IsMapped)
            {
                throw new HttpException(404, null);
            }

            //301 Redirect to the correct search engine name in the url if it is wrong
            if (!StringComparer.OrdinalIgnoreCase.Equals(searchEngineName, entity.SEName))
            {
                return(RedirectPermanent(Url.BuildEntityLink(normalizedEntityType, id, entity.SEName)));
            }

            //Set last seen values on the profile
            HttpContext.Profile.SetPropertyValue("LastViewedEntityName", entity.EntityType);
            HttpContext.Profile.SetPropertyValue("LastViewedEntityInstanceID", entity.ID.ToString());
            HttpContext.Profile.SetPropertyValue("LastViewedEntityInstanceName", XmlCommon.GetLocaleEntry(entity.Name, customer.LocaleSetting, true));

            //Build up the runtime parameters for the xmlpackage
            var runtimeParameters = string.Format("EntityName={0}&EntityID={1}&ProductTypeFilterID={2}",
                                                  entity.EntityType,
                                                  entity.ID,
                                                  productTypeFilterId ?? 0);

            var entityTypeSpecificRuntimeParamName = "CatID";

            if (entity.EntityType.Equals("manufacturer", StringComparison.InvariantCultureIgnoreCase))
            {
                entityTypeSpecificRuntimeParamName = "ManID";
            }
            else if (entity.EntityType.Equals("section", StringComparison.InvariantCultureIgnoreCase))
            {
                entityTypeSpecificRuntimeParamName = "SecID";
            }
            else if (entity.EntityType.Equals("distributor", StringComparison.InvariantCultureIgnoreCase))
            {
                entityTypeSpecificRuntimeParamName = "DistID";
            }
            else if (entity.EntityType.Equals("genre", StringComparison.InvariantCultureIgnoreCase))
            {
                entityTypeSpecificRuntimeParamName = "GenreID";
            }
            else if (entity.EntityType.Equals("vector", StringComparison.InvariantCultureIgnoreCase))
            {
                entityTypeSpecificRuntimeParamName = "VectorID";
            }
            else if (entity.EntityType.Equals("section", StringComparison.InvariantCultureIgnoreCase))
            {
                entityTypeSpecificRuntimeParamName = "DistID";
            }

            runtimeParameters += string.Format("&{0}={1}", entityTypeSpecificRuntimeParamName, entity.ID);

            //Get a default xmlpackage if we don't have one specified in the database
            var xmlPackageName = string.IsNullOrEmpty(entity.XmlPackage)
                                ? AppLogic.ro_DefaultEntityXmlPackage
                                : entity.XmlPackage;

            //Setup Meta tags
            var metaTitle = XmlCommon.GetLocaleEntry(entity.SETitle, customer.LocaleSetting, true);

            if (string.IsNullOrEmpty(metaTitle))
            {
                metaTitle = string.Format("{0} - {1}", AppLogic.AppConfig("StoreName"), entity.LocaleName);
            }

            var metaDescription = XmlCommon.GetLocaleEntry(entity.SEDescription, customer.LocaleSetting, true);

            if (string.IsNullOrEmpty(metaDescription))
            {
                metaDescription = entity.LocaleName;
            }

            var metaKeywords = XmlCommon.GetLocaleEntry(entity.SEKeywords, customer.LocaleSetting, true);

            if (string.IsNullOrEmpty(metaKeywords))
            {
                metaKeywords = entity.LocaleName;
            }

            //Setup the breadcrumb
            var pageTitle = Breadcrumb.GetEntityBreadcrumb(entity.ID, entity.LocaleName, entity.EntityType, customer);

            //Get the page content from the xmlpackage
            var pageContent = string.Empty;
            var xmlPackage  = new XmlPackage(
                packageName: xmlPackageName,
                customer: customer,
                additionalRuntimeParms: runtimeParameters,
                htmlHelper: ControllerContext.GetHtmlHelper());

            var parser = new Parser();

            pageContent = AppLogic.RunXmlPackage(xmlPackage, parser, customer, customer.SkinID, true, true);
            //override the meta tags from the xmlpackage
            if (xmlPackage.SETitle != string.Empty)
            {
                metaTitle = xmlPackage.SETitle;
            }
            if (xmlPackage.SEDescription != string.Empty)
            {
                metaDescription = xmlPackage.SEDescription;
            }
            if (xmlPackage.SEKeywords != string.Empty)
            {
                metaKeywords = xmlPackage.SEKeywords;
            }
            if (xmlPackage.SectionTitle != string.Empty)
            {
                pageTitle = xmlPackage.SectionTitle;
            }

            var payPalAd = new PayPalAd(PayPalAd.TargetPage.Entity);

            //Build the view model
            var entityViewModel = new EntityViewModel
            {
                Name            = XmlCommon.GetLocaleEntry(entity.Name, customer.LocaleSetting, true),
                MetaTitle       = metaTitle,
                MetaDescription = metaDescription,
                MetaKeywords    = metaKeywords,
                PageTitle       = pageTitle,
                PageContent     = pageContent,
                PayPalAd        = payPalAd.ImageMarkup,
                XmlPackageName  = xmlPackageName
            };

            AppLogic.eventHandler("ViewEntityPage").CallEvent("&ViewEntityPage=true");


            //Override the layout
            var layoutName = string.Empty;

            if (AppLogic.AppConfigBool("TemplateSwitching.Enabled"))
            {
                layoutName = AppLogic.GetCurrentEntityTemplateName(entity.EntityType, entity.ID);
            }

            if (!string.IsNullOrEmpty(layoutName))
            {
                return(View(ActionNames.Detail, layoutName, entityViewModel));
            }
            else
            {
                return(View(entityViewModel));
            }
        }
Пример #4
0
        MinicartAjaxData GetMinicartData(Customer customer, ShoppingCart cart, IEnumerable <AjaxNotice> messages = null)
        {
            var newCart = cart;
            var inventoryTrimmedReason = CartActionProvider.ValidateCartQuantitiesAgainstInventory(customer, cart.CartType);

            if (inventoryTrimmedReason != InventoryTrimmedReason.None)
            {
                //If inventory was trimmed, we need to update the cart object so the cart items are current
                newCart = CachedShoppingCartProvider.Get(customer, cart.CartType, AppLogic.StoreID());

                messages = new[] {
                    new AjaxNotice(
                        message: newCart.GetInventoryTrimmedUserMessage(inventoryTrimmedReason),
                        type: AjaxNoticeType.info)
                };
            }

            var viewName = newCart.CartType == CartTypeEnum.ShoppingCart
                                ? "_MiniCartContents"
                                : "_MiniWishContents";

            var cartViewModel = GetShoppingCartViewModel(newCart, customer);

            var orderTotal = newCart.Total(true);

            var subtotal = newCart.SubTotal(
                includeDiscount: false,
                onlyIncludeTaxableItems: false,
                includeDownloadItems: true,
                includeFreeShippingItems: true,
                includeSystemItems: true,
                useCustomerCurrencySetting: true);

            var taxTotal = newCart.TaxTotal();

            var shippingTotal = newCart.ShippingTotal(
                includeDiscount: true,
                includeTax: true);

            var displayTotal = orderTotal - taxTotal - shippingTotal;

            var discountTotal = Math.Round(displayTotal - subtotal, 2);

            var miniCartData = new MinicartAjaxData(
                cartCount: newCart.CartItems.Sum(item => item.Quantity),
                minicartContentsHtml: ControllerContext.GetHtmlHelper().Partial(viewName, cartViewModel).ToString(),
                messages: messages ?? Enumerable.Empty <AjaxNotice>(),
                subTotal: Localization.CurrencyStringForDisplayWithExchangeRate(
                    subtotal,
                    customer.CurrencySetting),
                discount: discountTotal != 0
                                        ? Localization.CurrencyStringForDisplayWithExchangeRate(
                    discountTotal,
                    customer.CurrencySetting)
                                        : null,
                total: Localization.CurrencyStringForDisplayWithExchangeRate(
                    displayTotal,
                    customer.CurrencySetting)
                );

            return(miniCartData);
        }
Пример #5
0
        public ActionResult Detail(int id, string searchEngineName, int?cartRecordId = null)
        {
            var product = new Product(id);


            // Make sure we should show the product
            if (product.ProductID == 0 ||
                !product.Published ||
                !product.IsMappedToStore())
            {
                throw new HttpException(404, null);
            }

            var outOfStockLevel = AppLogic.AppConfigNativeInt("HideProductsWithLessThanThisInventoryLevel");

            if (AppLogic.AppConfigBool("ProductPageOutOfStockRedirect") &&
                outOfStockLevel != -1)
            {
                if (AppLogic.DeterminePurchasableQuantity(product.ProductID,
                                                          AppLogic.GetProductsDefaultVariantID(product.ProductID),
                                                          AppLogic.ProductTracksInventoryBySizeAndColor(product.ProductID),
                                                          "Product") < outOfStockLevel)
                {
                    throw new HttpException(404, null);
                }
            }

            // 301 Redirect to the correct search engine name in the url if it is wrong
            if (!string.IsNullOrEmpty(product.SEName) &&
                !StringComparer.OrdinalIgnoreCase.Equals(searchEngineName, product.SEName))
            {
                return(RedirectPermanent(Url.BuildProductLink(id, product.SEName)));
            }
            else
            {
                SysLog.LogMessage(
                    message: "Invalid product se name.",
                    details: string.Format("Product {0} does not have an SE Name set.", product.ProductID),
                    messageType: MessageTypeEnum.Informational,
                    messageSeverity: MessageSeverityEnum.Alert);
            }

            // Set the xmlpackage
            var xmlpackageName = !string.IsNullOrEmpty(product.XmlPackage)
                                ? product.XmlPackage
                                : AppLogic.ro_DefaultProductXmlPackage;

            // Kits always get the default kit xmlpackage
            if (product.IsAKit)
            {
                xmlpackageName = "page.kitheader.xml.config";
            }

            var customer = HttpContext.GetCustomer();

            // Get the context of where we've come from
            var sourceEntityInfo = GetSourceEntityInfo(product.ProductID, customer.LocaleSetting);

            // Save source entity info to the profile
            Profile["LastViewedEntityName"]         = sourceEntityInfo.Type;
            Profile["LastViewedEntityInstanceID"]   = sourceEntityInfo.Id.ToString();
            Profile["LastViewedEntityInstanceName"] = sourceEntityInfo.Name;

            if (!product.RequiresRegistration || customer.IsRegistered)
            {
                //Log views to generate dynamic related product results
                if (AppLogic.AppConfigBool("DynamicRelatedProducts.Enabled") && !AppLogic.UserAgentIsKnownBot())
                {
                    customer.LogProductView(product.ProductID);
                }

                //Fire an event
                AppLogic.eventHandler("ViewProductPage").CallEvent("&ViewProductPage=true");

                //Update Product looks(views count)
                DB.ExecuteSQL("update product set Looks=Looks+1 where ProductID = @ProductId", new SqlParameter[] { new SqlParameter("ProductId", product.ProductID) });
            }

            // Additional runtime parameters
            var runtimeParameters = string.Format("EntityName={0}&EntityID={1}", sourceEntityInfo.Type, sourceEntityInfo.Id);

            if (Request.Url.Query.Contains("cartrecid"))
            {
                runtimeParameters += string.Format("&cartrecid={0}", CommonLogic.QueryStringUSInt("cartrecid"));
            }

            // Add a showproduct runtime node
            runtimeParameters += "&showproduct=1";

            // Breadcrumb and meta tags
            var pageTitle   = Breadcrumb.GetProductBreadcrumb(product.ProductID, product.LocaleName, sourceEntityInfo.Type, sourceEntityInfo.Id, customer);
            var pageContent = string.Empty;

            var metaTitle = XmlCommon.GetLocaleEntry(product.SETitle, customer.LocaleSetting, true);

            if (string.IsNullOrEmpty(metaTitle))
            {
                metaTitle = Server.HtmlEncode(string.Format("{0} - {1}", AppLogic.AppConfig("StoreName"), product.LocaleName));
            }

            var metaDescription = XmlCommon.GetLocaleEntry(product.SEDescription, customer.LocaleSetting, true);

            if (string.IsNullOrEmpty(metaDescription))
            {
                metaDescription = Server.HtmlEncode(product.LocaleName);
            }

            var metaKeywords = XmlCommon.GetLocaleEntry(product.SEKeywords, customer.LocaleSetting, true);

            if (string.IsNullOrEmpty(metaKeywords))
            {
                metaKeywords = Server.HtmlEncode(product.LocaleName);
            }

            var parser = new Parser();

            var xmlpackage = new XmlPackage(
                packageName: xmlpackageName,
                customer: customer,
                additionalRuntimeParms: runtimeParameters,
                htmlHelper: ControllerContext.GetHtmlHelper());

            pageContent = AppLogic.RunXmlPackage(xmlpackage, parser, customer, customer.SkinID, true, true);
            if (!string.IsNullOrEmpty(xmlpackage.SectionTitle))
            {
                pageTitle = xmlpackage.SectionTitle;
            }

            if (!string.IsNullOrEmpty(xmlpackage.SETitle))
            {
                metaTitle = xmlpackage.SETitle;
            }

            if (!string.IsNullOrEmpty(xmlpackage.SEDescription))
            {
                metaDescription = xmlpackage.SEDescription;
            }

            if (xmlpackage.SEKeywords != string.Empty)
            {
                metaKeywords = xmlpackage.SEKeywords;
            }

            // Build the view model
            var productViewModel = new ProductViewModel
            {
                Id               = product.ProductID,
                Name             = XmlCommon.GetLocaleEntry(product.LocaleName, customer.LocaleSetting, true),
                MetaTitle        = metaTitle,
                MetaDescription  = metaDescription,
                MetaKeywords     = metaKeywords,
                PageTitle        = pageTitle,
                PageContent      = pageContent,
                LoginRequired    = product.RequiresRegistration && !customer.IsRegistered,
                IsAKit           = product.IsAKit,
                XmlPackageName   = xmlpackageName,
                CartRecordId     = cartRecordId,
                SchemaProductUrl = string.Format("{0}://schema.org/Product", Request.Url.Scheme)
            };

            // Override the layout
            var layoutName = string.Empty;

            if (AppLogic.AppConfigBool("TemplateSwitching.Enabled"))
            {
                layoutName = AppLogic.GetCurrentEntityTemplateName(sourceEntityInfo.Type, sourceEntityInfo.Id);
            }

            // Kits use a separate view
            var viewName = product.IsAKit
                                ? ViewNames.KitDetail
                                : ViewNames.Detail;

            return(!string.IsNullOrEmpty(layoutName)
                                ? View(viewName, layoutName, productViewModel)
                                : View(viewName, productViewModel));
        }
Пример #6
0
        public ActionResult Index(int categoryid, string searchEngineName)

        {
            var entity   = new Entity(categoryid, "category");
            var customer = ControllerContext.HttpContext.GetCustomer();

            //Make sure we've got a valid entity
            if (entity == null ||
                entity.ID == 0 ||
                entity.Published == false ||
                entity.Deleted == true)
            {
                throw new HttpException(404, null);
            }

            //Make sure that this entity is mapped to this store
            var store = new CachelessStore();

            store.StoreID = AppLogic.StoreID();
            var storeMapping = store.GetMapping(entity.EntityType, entity.ID);

            if (AppLogic.GlobalConfigBool("AllowEntityFiltering") == true && !storeMapping.IsMapped)
            {
                throw new HttpException(404, null);
            }

            //Set last seen values on the profile
            HttpContext.Profile.SetPropertyValue("LastViewedEntityName", entity.EntityType);
            HttpContext.Profile.SetPropertyValue("LastViewedEntityInstanceID", entity.ID.ToString());
            HttpContext.Profile.SetPropertyValue("LastViewedEntityInstanceName", XmlCommon.GetLocaleEntry(entity.Name, customer.LocaleSetting, true));

            //Build up the runtime parameters for the xmlpackage
            var runtimeParameters = string.Format("EntityName={0}&EntityID={1}&ProductTypeFilterID=0",
                                                  entity.EntityType,
                                                  entity.ID);

            var entityTypeSpecificRuntimeParamName = "CatID";

            runtimeParameters += string.Format("&{0}={1}", entityTypeSpecificRuntimeParamName, entity.ID);

            //Get a default xmlpackage if we don't have one specified in the database
            var xmlPackageName = string.IsNullOrEmpty(entity.XmlPackage)
                ? "category.xml.config"
                : entity.XmlPackage;

            //Setup Meta tags
            var metaTitle = XmlCommon.GetLocaleEntry(entity.SETitle, customer.LocaleSetting, true);

            if (string.IsNullOrEmpty(metaTitle))
            {
                metaTitle = Security.HtmlEncode(string.Format("{0} - {1}", AppLogic.AppConfig("StoreName"), entity.LocaleName));
            }

            var metaDescription = XmlCommon.GetLocaleEntry(entity.SEDescription, customer.LocaleSetting, true);

            if (string.IsNullOrEmpty(metaDescription))
            {
                metaDescription = Security.HtmlEncode(entity.LocaleName);
            }

            var metaKeywords = XmlCommon.GetLocaleEntry(entity.SEKeywords, customer.LocaleSetting, true);

            if (string.IsNullOrEmpty(metaKeywords))
            {
                metaKeywords = Security.HtmlEncode(entity.LocaleName);
            }

            //Setup the breadcrumb
            var pageTitle = Breadcrumb.GetEntityBreadcrumb(entity.ID, entity.LocaleName, entity.EntityType, customer);

            //Get the page content from the xmlpackage
            var pageContent = string.Empty;
            var xmlPackage  = new XmlPackage(
                packageName: xmlPackageName,
                customer: customer,
                additionalRuntimeParms: runtimeParameters,
                htmlHelper: ControllerContext.GetHtmlHelper());

            var parser = new Parser();

            pageContent = AppLogic.RunXmlPackage(xmlPackage, parser, customer, customer.SkinID, true, true);
            //override the meta tags from the xmlpackage
            if (xmlPackage.SETitle != string.Empty)
            {
                metaTitle = xmlPackage.SETitle;
            }
            if (xmlPackage.SEDescription != string.Empty)
            {
                metaDescription = xmlPackage.SEDescription;
            }
            if (xmlPackage.SEKeywords != string.Empty)
            {
                metaKeywords = xmlPackage.SEKeywords;
            }
            if (xmlPackage.SectionTitle != string.Empty)
            {
                pageTitle = xmlPackage.SectionTitle;
            }

            var payPalAd = new PayPalAd(PayPalAd.TargetPage.Entity);

            //Build the view model
            var entityViewModel = new EntityViewModel
            {
                Name            = XmlCommon.GetLocaleEntry(entity.Name, customer.LocaleSetting, true),
                MetaTitle       = metaTitle,
                MetaDescription = metaDescription,
                MetaKeywords    = metaKeywords,
                PageTitle       = pageTitle,
                PageContent     = pageContent,
                PayPalAd        = payPalAd.Show ? payPalAd.ImageScript : string.Empty,
                XmlPackageName  = xmlPackageName
            };

            AppLogic.eventHandler("ViewEntityPage").CallEvent("&ViewEntityPage=true");

            //Override the layout
            var layoutName = string.Empty;

            return(View(entityViewModel));
        }
Пример #7
0
        public ActionResult Detail(int id, string searchEngineName, int?cartRecordId = null)
        {
            var product = new Product(id);

            // Make sure we should show the product
            if (product.ProductID == 0 ||
                !product.Published ||
                !product.IsMappedToStore())
            {
                throw new HttpException(404, null);
            }

            var outOfStockLevel = AppLogic.AppConfigNativeInt("HideProductsWithLessThanThisInventoryLevel");

            if (AppLogic.AppConfigBool("ProductPageOutOfStockRedirect") &&
                outOfStockLevel != -1)
            {
                if (AppLogic.DeterminePurchasableQuantity(product.ProductID,
                                                          AppLogic.GetProductsDefaultVariantID(product.ProductID),
                                                          AppLogic.ProductTracksInventoryBySizeAndColor(product.ProductID),
                                                          "Product") < outOfStockLevel)
                {
                    throw new HttpException(404, null);
                }
            }

            // If the search engine name in the URL is incorrect, 301 Redirect to the correct search engine name URL
            if (!string.IsNullOrEmpty(product.SEName) &&
                !StringComparer.OrdinalIgnoreCase.Equals(searchEngineName, product.SEName))
            {
                // The search engine name in the URL is incorrect
                // We should redirect to the correct search engine name, which should be stored in the database 'SEName' field

                // First, let's make sure the SEName field in the database has not been tampered with
                // If the Product.SEName field has been manually modified, we can't redirect properly
                var expectedSENameForURL = SearchEngineNameProvider.GenerateSeName(product.SEName);

                if (expectedSENameForURL == product.SEName)
                {
                    // SEName in the database is in the expected format - let's redirect to the expected SEName URL
                    return(RedirectPermanent(Url.BuildProductLink(id, product.SEName)));
                }
                else
                {
                    // SEName contains invalid characters, or otherwise is not in the correct format in the database
                    // This should only happen if the user is manually modifying their database, or modifying products improperly using Wsi
                    // Let's blow up to prevent infinite redirect.  An Admin will need to fix their manually modified SEName field(s)
                    throw new HttpException(500, $"Invalid SEName in the database for ProductID {product.ProductID}");
                }
            }

            // Set the xmlpackage
            var xmlpackageName = !string.IsNullOrEmpty(product.XmlPackage)
                                ? product.XmlPackage
                                : AppLogic.ro_DefaultProductXmlPackage;

            // Kits always get the default kit xmlpackage
            if (product.IsAKit)
            {
                xmlpackageName = "page.kitheader.xml.config";
            }

            var customer = HttpContext.GetCustomer();

            // Get the context of where we've come from
            var sourceEntityInfo = GetSourceEntityInfo(product.ProductID, customer.LocaleSetting);

            // Save source entity info to the profile
            Profile["LastViewedEntityName"]         = sourceEntityInfo.Type;
            Profile["LastViewedEntityInstanceID"]   = sourceEntityInfo.Id.ToString();
            Profile["LastViewedEntityInstanceName"] = sourceEntityInfo.Name;

            if (!product.RequiresRegistration || customer.IsRegistered)
            {
                //Log views to generate dynamic related product results
                if (AppLogic.AppConfigBool("DynamicRelatedProducts.Enabled") && !AppLogic.UserAgentIsKnownBot())
                {
                    customer.LogProductView(product.ProductID);
                }

                //Fire an event
                AppLogic.eventHandler("ViewProductPage").CallEvent("&ViewProductPage=true");

                //Update Product looks(views count)
                DB.ExecuteSQL("update product set Looks=Looks+1 where ProductID = @ProductId", new SqlParameter[] { new SqlParameter("ProductId", product.ProductID) });
            }

            // Additional runtime parameters
            var runtimeParameters = string.Format("EntityName={0}&EntityID={1}", sourceEntityInfo.Type, sourceEntityInfo.Id);

            if (Request.Url.Query.Contains("cartrecid"))
            {
                runtimeParameters += string.Format("&cartrecid={0}", CommonLogic.QueryStringUSInt("cartrecid"));
            }

            // Add a showproduct runtime node
            runtimeParameters += "&showproduct=1";

            // Breadcrumb and meta tags
            var pageTitle   = Breadcrumb.GetProductBreadcrumb(product.ProductID, product.LocaleName, sourceEntityInfo.Type, sourceEntityInfo.Id, customer);
            var pageContent = string.Empty;

            var metaTitle = XmlCommon.GetLocaleEntry(product.SETitle, customer.LocaleSetting, true);

            if (string.IsNullOrEmpty(metaTitle))
            {
                metaTitle = string.Format("{0} - {1}", AppLogic.AppConfig("StoreName"), product.LocaleName);
            }

            var metaDescription = XmlCommon.GetLocaleEntry(product.SEDescription, customer.LocaleSetting, true);

            if (string.IsNullOrEmpty(metaDescription))
            {
                metaDescription = product.LocaleName;
            }

            var metaKeywords = XmlCommon.GetLocaleEntry(product.SEKeywords, customer.LocaleSetting, true);

            if (string.IsNullOrEmpty(metaKeywords))
            {
                metaKeywords = product.LocaleName;
            }

            var parser = new Parser();

            var xmlpackage = new XmlPackage(
                packageName: xmlpackageName,
                customer: customer,
                additionalRuntimeParms: runtimeParameters,
                htmlHelper: ControllerContext.GetHtmlHelper());

            pageContent = AppLogic.RunXmlPackage(xmlpackage, parser, customer, customer.SkinID, true, true);
            if (!string.IsNullOrEmpty(xmlpackage.SectionTitle))
            {
                pageTitle = xmlpackage.SectionTitle;
            }

            if (!string.IsNullOrEmpty(xmlpackage.SETitle))
            {
                metaTitle = xmlpackage.SETitle;
            }

            if (!string.IsNullOrEmpty(xmlpackage.SEDescription))
            {
                metaDescription = xmlpackage.SEDescription;
            }

            if (xmlpackage.SEKeywords != string.Empty)
            {
                metaKeywords = xmlpackage.SEKeywords;
            }

            // Build the view model
            var productViewModel = new ProductViewModel
            {
                Id              = product.ProductID,
                Name            = XmlCommon.GetLocaleEntry(product.LocaleName, customer.LocaleSetting, true),
                MetaTitle       = metaTitle,
                MetaDescription = metaDescription,
                MetaKeywords    = metaKeywords,
                PageTitle       = pageTitle,
                PageContent     = pageContent,
                LoginRequired   = product.RequiresRegistration && !customer.IsRegistered,
                IsAKit          = product.IsAKit,
                XmlPackageName  = xmlpackageName,
                CartRecordId    = cartRecordId
            };

            // Override the layout
            var layoutName = string.Empty;

            if (AppLogic.AppConfigBool("TemplateSwitching.Enabled"))
            {
                layoutName = AppLogic.GetCurrentEntityTemplateName(sourceEntityInfo.Type, sourceEntityInfo.Id);
            }

            // Kits use a separate view
            var viewName = product.IsAKit
                                ? ViewNames.KitDetail
                                : ViewNames.Detail;

            return(!string.IsNullOrEmpty(layoutName)
                                ? View(viewName, layoutName, productViewModel)
                                : View(viewName, productViewModel));
        }