Beispiel #1
0
        /// <summary>
        /// Create a feed
        /// </summary>
        /// <param name="options">Feed configuration options</param>
        /// <returns>true if feed creation is successful, false otherwise</returns>
        public bool CreateFeed(FeedOptions options)
        {
            string feedFile = Path.Combine(options.FeedDataPath, options.FeedFileName);

            if (File.Exists(feedFile) && !options.OverwriteFeedFile)
            {
                UpdateStatus(100, "Feed File Already Exists. You should either chose to overwrite the feed file or provide a different name.", false);
                return(false);
            }

            string criteria = "VisibilityId<>" + (short)CatalogVisibility.Private;

            if (!options.IncludeAllProducts)
            {
                criteria = criteria + " AND ExcludeFromFeed=0";
            }

            string headerRow = GetHeaderRow();

            if (!headerRow.EndsWith("\r\n"))
            {
                headerRow += "\r\n";
            }

            try
            {
                using (StreamWriter feedWriter = File.CreateText(feedFile))
                {
                    feedWriter.Write(headerRow);
                    feedWriter.Close();
                }
            }
            catch (System.UnauthorizedAccessException accessException)
            {
                UpdateStatus(100, "Access restricted on feed data folder. In order to create feeds, the current user (" + Misc.GetProcessIdentity() + ") needs write access to feeds data folder.", false);
                UpdateStatus(100, "Access exception : " + accessException.Message, false);
                return(false);
            }

            bool needTokenReset = false;

            if (Token.Instance.Store == null)
            {
                Store store = StoreDataSource.Load(options.StoreId);
                Token.Instance.InitStoreContext(store);
                needTokenReset = true;
            }

            try
            {
                using (StreamWriter feedWriter = File.AppendText(feedFile))
                {
                    ProductCollection products;
                    int count      = ProductDataSource.CountForCriteria(criteria);
                    int startIndex = 0;
                    while (startIndex < count)
                    {
                        // DETERMINE HOW MANY ROWS LEFT TO INCLUDE IN FEED
                        int rowsRemaining = count - startIndex;

                        // ONLY PROCESS 1000 ROWS AT A TIME
                        int maxRows = (rowsRemaining > 1000) ? 1000 : rowsRemaining;

                        // CALCULATE PROGRESS PERCENTAGE AND DISPLAY PROGRESS
                        int percentDone = startIndex / count * 100;
                        UpdateStatus(percentDone, "Generating feed for products from " + startIndex + " to " + (startIndex + maxRows) + " out of " + count + " products.");

                        // GET THE ROWS TO BE OUTPUT
                        products = ProductDataSource.LoadForCriteria(criteria, maxRows, startIndex);

                        // GENERATE THE FEED DATA
                        string feedData = GetFeedData(products);

                        // WRITE DATA TO THE FEED FILE
                        if (!feedData.EndsWith("\r\n"))
                        {
                            feedData += "\r\n";
                        }
                        feedWriter.Write(feedData);
                        feedWriter.Flush();

                        // LOOP TO THE NEXT BLOCK OF DATA
                        startIndex += 1000;
                    }

                    // CLOSE THE FEED FILE
                    feedWriter.Close();
                }
            }
            catch (Exception e)
            {
                Logger.Warn("Error Feed Creator Thread : " + e.Message, e);
                UpdateStatus(100, "Error while creating feed file." + e.Message, false);
                return(false);
            }
            finally
            {
                if (needTokenReset)
                {
                    Token.ResetInstance();
                }
            }
            UpdateStatus(100, string.Format("Feed file generated at {0}.", options.FeedDataPath), true);
            return(true);
        }
        protected void Page_PreRender(object sender, EventArgs e)
        {
            List <string> alertList;
            DateTime      cacheDate;
            CacheWrapper  alertWrapper = Cache.Get("AdminAlerts") as CacheWrapper;

            if (alertWrapper == null)
            {
                alertList = new List <string>();

                //Check if installation directory still exists
                if (System.IO.Directory.Exists(Request.MapPath("~/Install")))
                {
                    string alertText = "The 'Install' directory still exists in your store. It should be removed immediately after the Installation is complete.";
                    alertList.Add(alertText);
                }

                // CHECK IF EMAIL TEMPLATES ARE CONFIGURED, WITHOUT EMAIL SERVER SETTINGS
                Store store = AbleContext.Current.Store;
                if ((store.EmailTemplates.Count > 0))
                {
                    if (string.IsNullOrEmpty(store.Settings.SmtpServer))
                    {
                        string alertText = "You have email templates configured, but you have not provided an SMTP (mail) server.  Without a serv" +
                                           "er, email notifications cannot be sent.  <a href=\'Store/EmailTemplates/Settings.aspx\'>Click here</a> to configure " +
                                           "email now.";
                        alertList.Add(alertText);
                    }
                }
                //VALIDATE ORDER STATUSES
                //CHECK FOR A STATUS ATTACHED TO THE ORDER PLACED EVENT
                OrderStatus status = OrderStatusTriggerDataSource.LoadForStoreEvent(StoreEvent.OrderPlaced);
                if (status == null)
                {
                    status             = new OrderStatus();
                    status.Name        = "Payment Pending";
                    status.DisplayName = "Payment Pending";
                    status.IsActive    = false;
                    status.IsValid     = true;
                    status.Triggers.Add(new OrderStatusTrigger(StoreEvent.OrderPlaced, status));
                    status.Save();
                    alertList.Add("You did not have an order status assigned to the 'Order Placed' event, so one was created for you.  <a href=\"Store/OrderStatuses/Default.aspx\">Click here</a> to check the order status configuration for your store.");
                }
                //CHECK FOR A STATUS ATTACHED TO THE ORDER CANCELLED EVENT
                status = OrderStatusTriggerDataSource.LoadForStoreEvent(StoreEvent.OrderCancelled);
                if (status == null)
                {
                    status             = new OrderStatus();
                    status.Name        = "Cancelled";
                    status.DisplayName = "Cancelled";
                    status.IsActive    = false;
                    status.IsValid     = false;
                    status.Triggers.Add(new OrderStatusTrigger(StoreEvent.OrderCancelled, status));
                    status.Save();
                    alertList.Add("You did not have an order status assigned to the 'Order Cancelled' event, so one was created for you.  <a href=\"Store/OrderStatuses/Default.aspx\">Click here</a> to check the order status configuration for your store.");
                }

                //MAKE SURE AT LEAST ONE PRODUCT EXISTS
                int productCount = ProductDataSource.CountAll();
                if (productCount == 0)
                {
                    alertList.Add("You have not yet added any products in your store.  <a href=\"Catalog/Browse.aspx\">Click here</a> to manage your catalog now.");
                }

                //MAKE SURE AT LEAST ONE SHIPPING METHOD EXISTS
                int shipMethodCount = ShipMethodDataSource.CountAll();
                if (shipMethodCount == 0)
                {
                    alertList.Add("You do not have any shipping methods configured.  Your customers will not be able to complete checkout if the order contains any shippable products.  <a href=\"Shipping/Methods/Default.aspx\">Click here</a> to manage shipping methods now.");
                }

                //CHECK FOR LOW INVENTORY PRODUCTS
                int lowInventoryProducts = ProductInventoryDataSource.GetLowProductInventoryCount();
                if (lowInventoryProducts > 0)
                {
                    alertList.Add("One or more products are at or below their low inventory warning level.  You can view these products <a href=\"Reports/LowInventory.aspx\">here</a>.");
                }

                //CHECK FOR PRESENCE OF ERRORS
                int errorCount = ErrorMessageDataSource.CountAll();
                if (errorCount > 0)
                {
                    string errorAlert = string.Format("There are {0} messages in your <a href=\"Help/ErrorLog.aspx\">error log</a>.  You should review these messages and take corrective action if necessary.", errorCount);
                    alertList.Add(errorAlert);
                }

                //Check of SSL is not enabled
                StoreSettingsManager storeSettings = AbleContext.Current.Store.Settings;
                if (!storeSettings.SSLEnabled)
                {
                    string alertText = "SSL is not enabled. Your store is currently being accessed over an insecure connection. <a href=\"Store/Security/Default.aspx\">Click Here</a> to change SSL settings.";
                    alertList.Add(alertText);
                }

                //MAKE SURE ORDER NUMBER INCREMENT IS VALID
                if (store.OrderIdIncrement < 1)
                {
                    string alertText = "The order number increment for your store was " + store.OrderIdIncrement + " (invalid).  The increment has been updated to 1.  <a href=\"Store/StoreSettings.aspx\">Click Here</a> to review this setting.";
                    alertList.Add(alertText);
                    store.OrderIdIncrement = 1;
                    store.Save();
                }

                //ALERT FOR ORDER NUMBER PROBLEM
                int maxOrderNumber  = StoreDataSource.GetMaxOrderNumber();
                int nextOrderNumber = StoreDataSource.GetNextOrderNumber(false);
                if (maxOrderNumber >= nextOrderNumber)
                {
                    int newOrderNumber = maxOrderNumber + store.OrderIdIncrement;
                    StoreDataSource.SetNextOrderNumber(newOrderNumber);
                    string alertText = "The next order number of {0} is less than the highest assigned order number of {1}.  We have automatically increased your next order number to {2} to prevent errors.  <a href=\"Store/StoreSettings.aspx\">Click Here</a> to review this setting.";
                    alertList.Add(string.Format(alertText, nextOrderNumber, maxOrderNumber, newOrderNumber));
                }

                //MAKE SURE A VALID ENCRYPTION KEY IS PRESENT
                bool encryptionKeyValid;
                try
                {
                    encryptionKeyValid = EncryptionKeyManager.IsKeyValid(EncryptionKeyManager.Instance.CurrentKey.KeyData);
                }
                catch
                {
                    encryptionKeyValid = false;
                }
                if (!encryptionKeyValid)
                {
                    //ENCRYPTION KEY IS MISSING OR INVALID, SEE WHETHER WE ARE STORING CARD DATA
                    if (storeSettings.EnableCreditCardStorage)
                    {
                        string alertText = "Your store encryption key is missing or invalid, and you have not disabled storage of card data.  You should either <a href=\"Store/Security/EncryptionKey.aspx\">set the encryption key</a> or <a href=\"Store/Security/Default.aspx\">disable credit card storage</a>.";
                        alertList.Add(alertText);
                    }
                }

                // ALERT FOR PRODUCT IMAGE LOOKUP BY SKU
                if (storeSettings.ImageSkuLookupEnabled)
                {
                    // SEARCH FOR PRODUCTS MISSING SKU AND MISSING IMAGE URLs
                    ICriteria productCriteria = NHibernateHelper.CreateCriteria <Product>()
                                                .Add(new Disjunction()
                                                     .Add(Restrictions.IsNull("Sku"))
                                                     .Add(Restrictions.Eq("Sku", string.Empty)))
                                                .Add(new Disjunction()
                                                     .Add(Restrictions.IsNull("ImageUrl"))
                                                     .Add(Restrictions.IsNull("IconUrl"))
                                                     .Add(Restrictions.IsNull("ThumbnailUrl")))
                                                .Add(Restrictions.Eq("VisibilityId", (byte)CatalogVisibility.Public));

                    IList <Product> products = ProductDataSource.LoadForCriteria(productCriteria);
                    if (products != null && products.Count > 0)
                    {
                        StringBuilder textBuilder = new StringBuilder();
                        textBuilder.Append("Following product(s) are missing SKU, and also do not have image paths provided:<br/>");
                        textBuilder.Append("<ul>");

                        int counter = 0; // PRODUCT COUNTER, SHOW ONLY FIRST FIVE PRODUCTS
                        foreach (Product product in products)
                        {
                            counter++;
                            textBuilder.Append("<li><a href=\"products/EditProduct.aspx?ProductId=" + product.Id + "\">" + product.Name + "</a>.</li>");
                            if (counter >= 5)
                            {
                                break;
                            }
                        }
                        textBuilder.Append("<ul>");
                        alertList.Add(textBuilder.ToString());
                    }
                }

                // LOOK FOR UNREAD NOTES
                ICriteria orderNoteCriteria = NHibernateHelper.CreateCriteria <OrderNote>()
                                              .Add(Restrictions.Eq("IsRead", false))
                                              .Add(Restrictions.Not(Restrictions.Eq("NoteTypeId", (byte)NoteType.SystemPublic)))
                                              .Add(Restrictions.Not(Restrictions.Eq("NoteTypeId", (byte)NoteType.SystemPrivate)));
                int unreadNoteCount = OrderNoteDataSource.CountForCriteria(orderNoteCriteria);
                if (unreadNoteCount > 0)
                {
                    string alertText = "There are {0} unread order note(s).  <a href=\"Orders/OrderNotesManager.aspx\">review now</a>";
                    alertList.Add(string.Format(alertText, unreadNoteCount));
                }

                // CHECK ANON USER MAINTENANCE SETTINGS
                if (store.Settings.AnonymousUserLifespan < 1 || store.Settings.AnonymousAffiliateUserLifespan < 1)
                {
                    alertList.Add("You have not configured the number of days to save anonymous user records.  You should visit the <a href=\"Store/Maintenance.aspx\">Configure > Maintenance</a> menu, view the status of the anonymous user database, and update your anonymous user maintenance settings.");
                }

                // ALERT FOR DUPLICATE COUPON CODES
                IList <Coupon> duplicateCoupons = NHibernateHelper.CreateSQLQuery("SELECT * FROM ac_Coupons WHERE CouponCode IN (SELECT LOWER(CouponCode) FROM ac_Coupons GROUP BY CouponCode HAVING COUNT(*) > 1)").AddEntity(typeof(Coupon)).List <Coupon>();
                if (duplicateCoupons.Count > 0)
                {
                    Dictionary <string, List <Coupon> > codeCounts = new Dictionary <string, List <Coupon> >();
                    foreach (Coupon coupon in duplicateCoupons)
                    {
                        string normalizedKey = coupon.CouponCode.ToUpperInvariant();
                        if (!codeCounts.ContainsKey(normalizedKey))
                        {
                            codeCounts[normalizedKey] = new List <Coupon>();
                        }
                        codeCounts[normalizedKey].Add(coupon);
                    }
                    StringBuilder alertText = new StringBuilder();
                    alertText.Append("<p>You have coupons that have duplicate codes.  Duplicates should be eliminated as a unique constraint will be applied in a future release:</p>");
                    foreach (string couponCode in codeCounts.Keys)
                    {
                        alertText.Append("<p><b>" + couponCode + ":</b> ");
                        string delimiter = string.Empty;
                        foreach (Coupon coupon in codeCounts[couponCode])
                        {
                            alertText.Append(delimiter);
                            alertText.Append("<a href=\"Marketing/Coupons/EditCoupon.aspx?CouponId=" + coupon.Id + "\">" + coupon.Name + "</a>");
                            delimiter = ", ";
                        }
                        alertText.Append("</p>");
                    }
                    alertList.Add(alertText.ToString());
                }

                //UPDATE CACHE
                alertWrapper = new CacheWrapper(alertList);
                Cache.Remove("AdminAlerts");
                Cache.Add("AdminAlerts", alertWrapper, null, DateTime.UtcNow.AddMinutes(15), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
            }
            else
            {
                alertList = (List <string>)alertWrapper.CacheValue;
            }
            cacheDate = alertWrapper.CacheDate;

            if (alertList.Count == 0)
            {
                alertList.Add("no action items available");
            }
            AlertList.DataSource = alertList;
            AlertList.DataBind();
            CachedAt.Text = string.Format("{0:g}", cacheDate);
        }
        protected void InitializeCatalogItems()
        {
            String items = Request.QueryString["Objects"];

            if (String.IsNullOrEmpty(items))
            {
                return;
            }
            String[]      itemsArray  = items.Split(',');
            List <String> categoryIds = new List <String>();
            List <String> productIds  = new List <String>();
            List <String> linkIds     = new List <String>();
            List <String> webpageIds  = new List <String>();

            // Sort out items in saperate lists
            foreach (String item in itemsArray)
            {
                String[]        itemValues      = item.Split(':');
                int             catalogNodeId   = AlwaysConvert.ToInt(itemValues[0]);
                CatalogNodeType catalogNodeType = (CatalogNodeType)AlwaysConvert.ToByte(itemValues[1]);
                switch (catalogNodeType)
                {
                case CatalogNodeType.Category:
                    categoryIds.Add(catalogNodeId.ToString());
                    break;

                case CatalogNodeType.Product:
                    productIds.Add(catalogNodeId.ToString());
                    break;

                case CatalogNodeType.Link:
                    linkIds.Add(catalogNodeId.ToString());
                    break;

                case CatalogNodeType.Webpage:
                    webpageIds.Add(catalogNodeId.ToString());
                    break;
                }
            }

            trIncludeContents.Visible = (categoryIds.Count > 0);
            if (categoryIds.Count > 0)
            {
                ICriteria criteria = CommerceBuilder.DomainModel.NHibernateHelper.CreateCriteria <Category>();
                criteria.Add(Restrictions.In("Id", categoryIds.ToArray()));
                _Categories = CategoryDataSource.LoadForCriteria(criteria);
                if (_Categories != null && _Categories.Count > 0)
                {
                    foreach (Category category in _Categories)
                    {
                        _CatalogItems.Add(category);
                    }
                }
            }

            if (productIds.Count > 0)
            {
                ICriteria criteria = CommerceBuilder.DomainModel.NHibernateHelper.CreateCriteria <Product>();
                criteria.Add(Restrictions.In("Id", productIds.ToArray()));
                _Products = ProductDataSource.LoadForCriteria(criteria);
                if (_Products != null && _Products.Count > 0)
                {
                    foreach (Product product in _Products)
                    {
                        _CatalogItems.Add(product);
                    }
                }
            }

            if (linkIds.Count > 0)
            {
                ICriteria criteria = CommerceBuilder.DomainModel.NHibernateHelper.CreateCriteria <Link>();
                criteria.Add(Restrictions.In("Id", linkIds.ToArray()));
                _Links = LinkDataSource.LoadForCriteria(criteria);
                if (_Links != null && _Links.Count > 0)
                {
                    foreach (Link link in _Links)
                    {
                        _CatalogItems.Add(link);
                    }
                }
            }

            if (webpageIds.Count > 0)
            {
                ICriteria criteria = CommerceBuilder.DomainModel.NHibernateHelper.CreateCriteria <Webpage>();
                criteria.Add(Restrictions.In("Id", webpageIds.ToArray()));
                _Webpages = WebpageDataSource.LoadForCriteria(criteria);
                if (_Webpages != null && _Webpages.Count > 0)
                {
                    foreach (Webpage webpage in _Webpages)
                    {
                        _CatalogItems.Add(webpage);
                    }
                }
            }

            if (!Page.IsPostBack)
            {
                if (_CatalogItems.Count == 1)
                {
                    ICatalogable catalogable = _CatalogItems[0];
                    switch (catalogable.Visibility)
                    {
                    case CatalogVisibility.Public:
                        VisPublic.Checked = true;
                        break;

                    case CatalogVisibility.Private:
                        VisPrivate.Checked = true;
                        break;

                    case CatalogVisibility.Hidden:
                        VisHidden.Checked = true;
                        break;

                    default:
                        VisPrivate.Checked = true;
                        break;
                    }
                }
                else if (_CatalogItems.Count > 1)
                {
                    VisPrivate.Checked = false;
                    VisPublic.Checked  = false;
                    VisHidden.Checked  = false;
                }
            }
        }
        /// <summary>
        /// Prepare list of used images
        /// Many be associated with products, as thumbnail, icon, or std. images
        /// or as additional images
        /// or to option swathces
        /// </summary>
        private void InitAssociatedImageUrls()
        {
            associatedImages = new List <string>();

            // ADD PRODUCT IMAGES
            ICriteria criteria = NHibernateHelper.CreateCriteria <Product>();

            criteria.Add(Restrictions.Eq("Store", AbleContext.Current.Store));
            criteria.Add(Restrictions.Disjunction()
                         .Add(Restrictions.Like("ImageUrl", "~/Assets/ProductImages/%"))
                         .Add(Restrictions.Like("ThumbnailUrl", "~/Assets/ProductImages/%"))
                         .Add(Restrictions.Like("IconUrl", "~/Assets/ProductImages/%")));

            IList <Product> products = ProductDataSource.LoadForCriteria(criteria);

            foreach (Product product in products)
            {
                if (product.ImageUrl.StartsWith("~/Assets/ProductImages/"))
                {
                    associatedImages.Add(product.ImageUrl);
                }
                if (product.ThumbnailUrl.StartsWith("~/Assets/ProductImages/"))
                {
                    associatedImages.Add(product.ThumbnailUrl);
                }
                if (product.IconUrl.StartsWith("~/Assets/ProductImages/"))
                {
                    associatedImages.Add(product.IconUrl);
                }
            }

            // ADDITIONAL IMAGES
            ICriteria imageCriteria = NHibernateHelper.CreateCriteria <ProductImage>();

            imageCriteria.Add(Restrictions.Like("ImageUrl", "~/Assets/ProductImages/%"));
            IList <ProductImage> images = ProductImageDataSource.LoadForCriteria(imageCriteria);

            foreach (ProductImage image in images)
            {
                associatedImages.Add(image.ImageUrl);
            }

            // OPTION SWATCHES
            ICriteria choicesCriteria = NHibernateHelper.CreateCriteria <OptionChoice>();

            choicesCriteria.Add(Restrictions.Disjunction()
                                .Add(Restrictions.Like("ImageUrl", "~/Assets/ProductImages/%"))
                                .Add(Restrictions.Like("ThumbnailUrl", "~/Assets/ProductImages/%")));

            IList <OptionChoice> choices = OptionChoiceDataSource.LoadForCriteria(choicesCriteria);

            foreach (OptionChoice choice in choices)
            {
                if (choice.ImageUrl.StartsWith("~/Assets/ProductImages/"))
                {
                    associatedImages.Add(choice.ImageUrl);
                }
                if (choice.ThumbnailUrl.StartsWith("~/Assets/ProductImages/"))
                {
                    associatedImages.Add(choice.ThumbnailUrl);
                }
            }

            // ADD CATEGORY IMAGES
            ICriteria categoryCriteria = NHibernateHelper.CreateCriteria <Category>();

            categoryCriteria.Add(Restrictions.Eq("Store", AbleContext.Current.Store));
            categoryCriteria.Add(Restrictions.Like("ThumbnailUrl", "~/Assets/ProductImages/%"));
            IList <Category> categories = CategoryDataSource.LoadForCriteria(categoryCriteria);

            foreach (Category category in categories)
            {
                if (category.ThumbnailUrl.StartsWith("~/Assets/ProductImages/"))
                {
                    associatedImages.Add(category.ThumbnailUrl);
                }
            }

            // ADD LINK IMAGES
            ICriteria linksCriteria = NHibernateHelper.CreateCriteria <Link>();

            linksCriteria.Add(Restrictions.Eq("Store", AbleContext.Current.Store));
            linksCriteria.Add(Restrictions.Like("ThumbnailUrl", "~/Assets/ProductImages/%"));
            IList <Link> links = LinkDataSource.LoadForCriteria(linksCriteria);

            foreach (Link link in links)
            {
                if (link.ThumbnailUrl.StartsWith("~/Assets/ProductImages/"))
                {
                    associatedImages.Add(link.ThumbnailUrl);
                }
            }

            // ADD GIFT WRAPING IMAGES
            ICriteria wrapstylesCriteria = NHibernateHelper.CreateCriteria <WrapStyle>();

            wrapstylesCriteria.Add(Restrictions.Like("ImageUrl", "~/Assets/ProductImages/%"));

            IList <WrapStyle> wrapStyles = WrapStyleDataSource.LoadForCriteria(wrapstylesCriteria);

            foreach (WrapStyle ws in wrapStyles)
            {
                if (ws.ImageUrl.StartsWith("~/Assets/ProductImages/"))
                {
                    associatedImages.Add(ws.ImageUrl);
                }
                if (ws.ThumbnailUrl.StartsWith("~/Assets/ProductImages/"))
                {
                    associatedImages.Add(ws.ThumbnailUrl);
                }
            }

            // ADD VARIANT IMAGES
            ICriteria variantsCriteria = NHibernateHelper.CreateCriteria <ProductVariant>();

            criteria.Add(Restrictions.Disjunction()
                         .Add(Restrictions.Like("ImageUrl", "~/Assets/ProductImages/%"))
                         .Add(Restrictions.Like("ThumbnailUrl", "~/Assets/ProductImages/%"))
                         .Add(Restrictions.Like("IconUrl", "~/Assets/ProductImages/%")));

            int variantsCount      = ProductVariantDataSource.CountForCriteria(variantsCriteria.Clone() as ICriteria);
            int maxVariantsToCache = 500;

            // avoid loading all variants at same time
            for (int index = 0; index < variantsCount; index += maxVariantsToCache)
            {
                variantsCriteria.SetMaxResults(maxVariantsToCache);
                variantsCriteria.SetFirstResult(index);
                IList <ProductVariant> productVariants = ProductVariantDataSource.LoadForCriteria(variantsCriteria);
                foreach (ProductVariant productVariant in productVariants)
                {
                    if (productVariant.ImageUrl.StartsWith("~/Assets/ProductImages/"))
                    {
                        associatedImages.Add(productVariant.ImageUrl);
                    }
                    if (productVariant.ThumbnailUrl.StartsWith("~/Assets/ProductImages/"))
                    {
                        associatedImages.Add(productVariant.ThumbnailUrl);
                    }
                    if (productVariant.IconUrl.StartsWith("~/Assets/ProductImages/"))
                    {
                        associatedImages.Add(productVariant.IconUrl);
                    }
                }
            }
        }