Torna al Thread
public partial class ProductController : BasePublicController
{
#region Fields
private readonly ICategoryService _categoryService;
private readonly IManufacturerService _manufacturerService;
private readonly IProductService _productService;
private readonly IVendorService _vendorService;
private readonly IProductTemplateService _productTemplateService;
private readonly IProductAttributeService _productAttributeService;
private readonly IWorkContext _workContext;
private readonly IStoreContext _storeContext;
private readonly ITaxService _taxService;
private readonly ICurrencyService _currencyService;
private readonly IPictureService _pictureService;
private readonly ILocalizationService _localizationService;
private readonly IPriceCalculationService _priceCalculationService;
private readonly IPriceFormatter _priceFormatter;
private readonly IWebHelper _webHelper;
private readonly ISpecificationAttributeService _specificationAttributeService;
private readonly IDateTimeHelper _dateTimeHelper;
private readonly IRecentlyViewedProductsService _recentlyViewedProductsService;
private readonly ICompareProductsService _compareProductsService;
private readonly IWorkflowMessageService _workflowMessageService;
private readonly IProductTagService _productTagService;
private readonly IOrderReportService _orderReportService;
private readonly IBackInStockSubscriptionService _backInStockSubscriptionService;
private readonly IAclService _aclService;
private readonly IStoreMappingService _storeMappingService;
private readonly IPermissionService _permissionService;
private readonly ICustomerActivityService _customerActivityService;
private readonly IProductAttributeParser _productAttributeParser;
private readonly IShippingService _shippingService;
private readonly MediaSettings _mediaSettings;
private readonly CatalogSettings _catalogSettings;
private readonly VendorSettings _vendorSettings;
private readonly ShoppingCartSettings _shoppingCartSettings;
private readonly LocalizationSettings _localizationSettings;
private readonly CustomerSettings _customerSettings;
private readonly CaptchaSettings _captchaSettings;
private readonly SeoSettings _seoSettings;
private readonly ICacheManager _cacheManager;
#endregion
#region Constructors
public ProductController(ICategoryService categoryService,
IManufacturerService manufacturerService,
IProductService productService,
IVendorService vendorService,
IProductTemplateService productTemplateService,
IProductAttributeService productAttributeService,
IWorkContext workContext,
IStoreContext storeContext,
ITaxService taxService,
ICurrencyService currencyService,
IPictureService pictureService,
ILocalizationService localizationService,
IPriceCalculationService priceCalculationService,
IPriceFormatter priceFormatter,
IWebHelper webHelper,
ISpecificationAttributeService specificationAttributeService,
IDateTimeHelper dateTimeHelper,
IRecentlyViewedProductsService recentlyViewedProductsService,
ICompareProductsService compareProductsService,
IWorkflowMessageService workflowMessageService,
IProductTagService productTagService,
IOrderReportService orderReportService,
IBackInStockSubscriptionService backInStockSubscriptionService,
IAclService aclService,
IStoreMappingService storeMappingService,
IPermissionService permissionService,
ICustomerActivityService customerActivityService,
IProductAttributeParser productAttributeParser,
IShippingService shippingService,
MediaSettings mediaSettings,
CatalogSettings catalogSettings,
VendorSettings vendorSettings,
ShoppingCartSettings shoppingCartSettings,
LocalizationSettings localizationSettings,
CustomerSettings customerSettings,
CaptchaSettings captchaSettings,
SeoSettings seoSettings,
ICacheManager cacheManager)
{
this._categoryService = categoryService;
this._manufacturerService = manufacturerService;
this._productService = productService;
this._vendorService = vendorService;
this._productTemplateService = productTemplateService;
this._productAttributeService = productAttributeService;
this._workContext = workContext;
this._storeContext = storeContext;
this._taxService = taxService;
this._currencyService = currencyService;
this._pictureService = pictureService;
this._localizationService = localizationService;
this._priceCalculationService = priceCalculationService;
this._priceFormatter = priceFormatter;
this._webHelper = webHelper;
this._specificationAttributeService = specificationAttributeService;
this._dateTimeHelper = dateTimeHelper;
this._recentlyViewedProductsService = recentlyViewedProductsService;
this._compareProductsService = compareProductsService;
this._workflowMessageService = workflowMessageService;
this._productTagService = productTagService;
this._orderReportService = orderReportService;
this._backInStockSubscriptionService = backInStockSubscriptionService;
this._aclService = aclService;
this._storeMappingService = storeMappingService;
this._permissionService = permissionService;
this._customerActivityService = customerActivityService;
this._productAttributeParser = productAttributeParser;
this._shippingService = shippingService;
this._mediaSettings = mediaSettings;
this._catalogSettings = catalogSettings;
this._vendorSettings = vendorSettings;
this._shoppingCartSettings = shoppingCartSettings;
this._localizationSettings = localizationSettings;
this._customerSettings = customerSettings;
this._captchaSettings = captchaSettings;
this._seoSettings = seoSettings;
this._cacheManager = cacheManager;
}
#endregion
#region Utilities
[NonAction]
protected virtual IEnumerable<ProductOverviewModel> PrepareProductOverviewModels(IEnumerable<Product> products,
bool preparePriceModel = true, bool preparePictureModel = true,
int? productThumbPictureSize = null, bool prepareSpecificationAttributes = false,
bool forceRedirectionAfterAddingToCart = false)
{
return this.PrepareProductOverviewModels(_workContext,
_storeContext, _categoryService, _productService, _specificationAttributeService,
_priceCalculationService, _priceFormatter, _permissionService,
_localizationService, _taxService, _currencyService,
_pictureService, _webHelper, _cacheManager,
_catalogSettings, _mediaSettings, products,
preparePriceModel, preparePictureModel,
productThumbPictureSize, prepareSpecificationAttributes,
forceRedirectionAfterAddingToCart);
}
[NonAction]
protected virtual ProductDetailsModel PrepareProductDetailsPageModel(Product product,
ShoppingCartItem updatecartitem = null, bool isAssociatedProduct = false)
{
if (product == null)
throw new ArgumentNullException("product");
var customerRolesIds = _workContext.CurrentCustomer.CustomerRoles
.Where(cr => cr.Active)
.Select(cr => cr.Id)
.ToList();
#region Standard properties
var model = new ProductDetailsModel()
{
Id = product.Id,
Name = product.GetLocalized(x => x.Name),
ShortDescription = product.GetLocalized(x => x.ShortDescription),
FullDescription = product.GetLocalized(x => x.FullDescription),
MetaKeywords = product.GetLocalized(x => x.MetaKeywords),
MetaDescription = product.GetLocalized(x => x.MetaDescription),
MetaTitle = product.GetLocalized(x => x.MetaTitle),
SeName = product.GetSeName(),
ShowSku = _catalogSettings.ShowProductSku,
Sku = product.Sku,
ShowManufacturerPartNumber = _catalogSettings.ShowManufacturerPartNumber,
FreeShippingNotificationEnabled = _catalogSettings.ShowFreeShippingNotification,
ManufacturerPartNumber = product.ManufacturerPartNumber,
ShowGtin = _catalogSettings.ShowGtin,
Gtin = product.Gtin,
StockAvailability = product.FormatStockMessage(_localizationService),
HasSampleDownload = product.IsDownload && product.HasSampleDownload,
};
//automatically generate product description?
if (_seoSettings.GenerateProductMetaDescription && String.IsNullOrEmpty(model.MetaDescription))
{
//based on short description
model.MetaDescription = model.ShortDescription;
}
//shipping info
model.IsShipEnabled = product.IsShipEnabled;
if (product.IsShipEnabled)
{
model.IsFreeShipping = product.IsFreeShipping;
//delivery date
var deliveryDate = _shippingService.GetDeliveryDateById(product.DeliveryDateId);
if (deliveryDate != null)
{
model.DeliveryDate = deliveryDate.GetLocalized(dd => dd.Name);
}
}
//email a friend
model.EmailAFriendEnabled = _catalogSettings.EmailAFriendEnabled;
//compare products
model.CompareProductsEnabled = _catalogSettings.CompareProductsEnabled;
#endregion
#region Vendor details
//vendor
if (_vendorSettings.ShowVendorOnProductDetailsPage)
{
var vendor = _vendorService.GetVendorById(product.VendorId);
if (vendor != null && !vendor.Deleted && vendor.Active)
{
model.ShowVendor = true;
model.VendorModel = new VendorBriefInfoModel()
{
Id = vendor.Id,
Name = vendor.GetLocalized(x => x.Name),
SeName = vendor.GetSeName(),
};
}
}
#endregion
#region Page sharing
if (_catalogSettings.ShowShareButton && !String.IsNullOrEmpty(_catalogSettings.PageShareCode))
{
var shareCode = _catalogSettings.PageShareCode;
if (_webHelper.IsCurrentConnectionSecured())
{
//need to change the addthis link to be https linked when the page is, so that the page doesnt ask about mixed mode when viewed in https...
shareCode = shareCode.Replace("http://", "https://");
}
model.PageShareCode = shareCode;
}
#endregion
#region Back in stock subscriptions
if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock &&
product.BackorderMode == BackorderMode.NoBackorders &&
product.AllowBackInStockSubscriptions &&
product.StockQuantity <= 0)
{
//out of stock
model.DisplayBackInStockSubscription = true;
}
#endregion
#region Breadcrumb
//do not prepare this model for the associated products. any it's not used
if (_catalogSettings.CategoryBreadcrumbEnabled && !isAssociatedProduct)
{
var breadcrumbCacheKey = string.Format(ModelCacheEventConsumer.PRODUCT_BREADCRUMB_MODEL_KEY, product.Id, _workContext.WorkingLanguage.Id, string.Join(",", customerRolesIds), _storeContext.CurrentStore.Id);
model.Breadcrumb = _cacheManager.Get(breadcrumbCacheKey, () =>
{
var breadcrumbModel = new ProductDetailsModel.ProductBreadcrumbModel()
{
Enabled = _catalogSettings.CategoryBreadcrumbEnabled,
ProductId = product.Id,
ProductName = product.GetLocalized(x => x.Name),
ProductSeName = product.GetSeName()
};
var productCategories = _categoryService.GetProductCategoriesByProductId(product.Id);
if (productCategories.Count > 0)
{
var category = productCategories[0].Category;
if (category != null)
{
foreach (var catBr in category.GetCategoryBreadCrumb(_categoryService, _aclService, _storeMappingService))
{
breadcrumbModel.CategoryBreadcrumb.Add(new CategorySimpleModel()
{
Id = catBr.Id,
Name = catBr.GetLocalized(x => x.Name),
SeName = catBr.GetSeName()
});
}
}
}
return breadcrumbModel;
});
}
#endregion
#region Product tags
//do not prepare this model for the associated products. any it's not used
if (!isAssociatedProduct)
{
var productTagsCacheKey = string.Format(ModelCacheEventConsumer.PRODUCTTAG_BY_PRODUCT_MODEL_KEY, product.Id, _workContext.WorkingLanguage.Id, _storeContext.CurrentStore.Id);
model.ProductTags = _cacheManager.Get(productTagsCacheKey, () =>
{
return product.ProductTags
//filter by store
.Where(x => _productTagService.GetProductCount(x.Id, _storeContext.CurrentStore.Id) > 0)
.Select(x =>
{
var ptModel = new ProductTagModel()
{
Id = x.Id,
Name = x.GetLocalized(y => y.Name),
SeName = x.GetSeName(),
ProductCount = _productTagService.GetProductCount(x.Id, _storeContext.CurrentStore.Id)
};
return ptModel;
})
.ToList();
});
}
#endregion
#region Templates
var templateCacheKey = string.Format(ModelCacheEventConsumer.PRODUCT_TEMPLATE_MODEL_KEY, product.ProductTemplateId);
model.ProductTemplateViewPath = _cacheManager.Get(templateCacheKey, () =>
{
var template = _productTemplateService.GetProductTemplateById(product.ProductTemplateId);
if (template == null)
template = _productTemplateService.GetAllProductTemplates().FirstOrDefault();
if (template == null)
throw new Exception("No default template could be loaded");
return template.ViewPath;
});
#endregion
#region Pictures
model.DefaultPictureZoomEnabled = _mediaSettings.DefaultPictureZoomEnabled;
//default picture
var defaultPictureSize = isAssociatedProduct ?
_mediaSettings.AssociatedProductPictureSize :
_mediaSettings.ProductDetailsPictureSize;
//prepare picture models
var productPicturesCacheKey = string.Format(ModelCacheEventConsumer.PRODUCT_DETAILS_PICTURES_MODEL_KEY, product.Id, defaultPictureSize, isAssociatedProduct, _workContext.WorkingLanguage.Id, _webHelper.IsCurrentConnectionSecured(), _storeContext.CurrentStore.Id);
var cachedPictures = _cacheManager.Get(productPicturesCacheKey, () =>
{
var pictures = _pictureService.GetPicturesByProductId(product.Id);
var defaultPictureModel = new PictureModel()
{
ImageUrl = _pictureService.GetPictureUrl(pictures.FirstOrDefault(), defaultPictureSize, !isAssociatedProduct),
FullSizeImageUrl = _pictureService.GetPictureUrl(pictures.FirstOrDefault(), 0, !isAssociatedProduct),
Title = string.Format(_localizationService.GetResource("Media.Product.ImageLinkTitleFormat.Details"), model.Name),
AlternateText = string.Format(_localizationService.GetResource("Media.Product.ImageAlternateTextFormat.Details"), model.Name),
};
//all pictures
var pictureModels = new List<PictureModel>();
foreach (var picture in pictures)
{
pictureModels.Add(new PictureModel()
{
ImageUrl = _pictureService.GetPictureUrl(picture, _mediaSettings.ProductThumbPictureSizeOnProductDetailsPage),
FullSizeImageUrl = _pictureService.GetPictureUrl(picture),
Title = string.Format(_localizationService.GetResource("Media.Product.ImageLinkTitleFormat.Details"), model.Name),
AlternateText = string.Format(_localizationService.GetResource("Media.Product.ImageAlternateTextFormat.Details"), model.Name),
});
}
return new { DefaultPictureModel = defaultPictureModel, PictureModels = pictureModels };
});
model.DefaultPictureModel = cachedPictures.DefaultPictureModel;
model.PictureModels = cachedPictures.PictureModels;
#endregion
#region Product price
model.ProductPrice.ProductId = product.Id;
if (_permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
{
model.ProductPrice.HidePrices = false;
if (product.CustomerEntersPrice)
{
model.ProductPrice.CustomerEntersPrice = true;
}
else
{
if (product.CallForPrice)
{
model.ProductPrice.CallForPrice = true;
}
else
{
decimal taxRate = decimal.Zero;
decimal oldPriceBase = _taxService.GetProductPrice(product, product.OldPrice, out taxRate);
decimal finalPriceWithoutDiscountBase = _taxService.GetProductPrice(product, _priceCalculationService.GetFinalPrice(product, false), out taxRate);
decimal finalPriceWithDiscountBase = _taxService.GetProductPrice(product, _priceCalculationService.GetFinalPrice(product, true), out taxRate);
decimal oldPrice = _currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, _workContext.WorkingCurrency);
decimal finalPriceWithoutDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithoutDiscountBase, _workContext.WorkingCurrency);
decimal finalPriceWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithDiscountBase, _workContext.WorkingCurrency);
if (finalPriceWithoutDiscountBase != oldPriceBase && oldPriceBase > decimal.Zero)
model.ProductPrice.OldPrice = _priceFormatter.FormatPrice(oldPrice);
model.ProductPrice.Price = _priceFormatter.FormatPrice(finalPriceWithoutDiscount);
if (finalPriceWithoutDiscountBase != finalPriceWithDiscountBase)
model.ProductPrice.PriceWithDiscount = _priceFormatter.FormatPrice(finalPriceWithDiscount);
model.ProductPrice.PriceValue = finalPriceWithoutDiscount;
model.ProductPrice.PriceWithDiscountValue = finalPriceWithDiscount;
//property for German market
//we display tax/shipping info only with "shipping enabled" for this product
//we also ensure this it's not free shipping
model.ProductPrice.DisplayTaxShippingInfo = _catalogSettings.DisplayTaxShippingInfoProductDetailsPage
&& product.IsShipEnabled &&
!product.IsFreeShipping;
//currency code
model.ProductPrice.CurrencyCode = _workContext.WorkingCurrency.CurrencyCode;
}
}
}
else
{
model.ProductPrice.HidePrices = true;
model.ProductPrice.OldPrice = null;
model.ProductPrice.Price = null;
}
#endregion
#region 'Add to cart' model
model.AddToCart.ProductId = product.Id;
model.AddToCart.UpdatedShoppingCartItemId = updatecartitem != null ? updatecartitem.Id : 0;
//quantity
model.AddToCart.EnteredQuantity = updatecartitem != null ? updatecartitem.Quantity : product.OrderMinimumQuantity;
//'add to cart', 'add to wishlist' buttons
model.AddToCart.DisableBuyButton = product.DisableBuyButton || !_permissionService.Authorize(StandardPermissionProvider.EnableShoppingCart);
model.AddToCart.DisableWishlistButton = product.DisableWishlistButton || !_permissionService.Authorize(StandardPermissionProvider.EnableWishlist);
if (!_permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
{
model.AddToCart.DisableBuyButton = true;
model.AddToCart.DisableWishlistButton = true;
}
//pre-order
if (product.AvailableForPreOrder)
{
model.AddToCart.AvailableForPreOrder = !product.PreOrderAvailabilityStartDateTimeUtc.HasValue ||
product.PreOrderAvailabilityStartDateTimeUtc.Value >= DateTime.UtcNow;
model.AddToCart.PreOrderAvailabilityStartDateTimeUtc = product.PreOrderAvailabilityStartDateTimeUtc;
}
//customer entered price
model.AddToCart.CustomerEntersPrice = product.CustomerEntersPrice;
if (model.AddToCart.CustomerEntersPrice)
{
decimal minimumCustomerEnteredPrice = _currencyService.ConvertFromPrimaryStoreCurrency(product.MinimumCustomerEnteredPrice, _workContext.WorkingCurrency);
decimal maximumCustomerEnteredPrice = _currencyService.ConvertFromPrimaryStoreCurrency(product.MaximumCustomerEnteredPrice, _workContext.WorkingCurrency);
model.AddToCart.CustomerEnteredPrice = updatecartitem != null ? updatecartitem.CustomerEnteredPrice : minimumCustomerEnteredPrice;
model.AddToCart.CustomerEnteredPriceRange = string.Format(_localizationService.GetResource("Products.EnterProductPrice.Range"),
_priceFormatter.FormatPrice(minimumCustomerEnteredPrice, false, false),
_priceFormatter.FormatPrice(maximumCustomerEnteredPrice, false, false));
}
//allowed quantities
var allowedQuantities = product.ParseAllowedQuatities();
foreach (var qty in allowedQuantities)
{
model.AddToCart.AllowedQuantities.Add(new SelectListItem()
{
Text = qty.ToString(),
Value = qty.ToString(),
Selected = updatecartitem != null && updatecartitem.Quantity == qty
});
}
#endregion
#region Gift card
model.GiftCard.IsGiftCard = product.IsGiftCard;
if (model.GiftCard.IsGiftCard)
{
model.GiftCard.GiftCardType = product.GiftCardType;
if (updatecartitem == null)
{
model.GiftCard.SenderName = _workContext.CurrentCustomer.GetFullName();
model.GiftCard.SenderEmail = _workContext.CurrentCustomer.Email;
}
else
{
string giftCardRecipientName, giftCardRecipientEmail, giftCardSenderName, giftCardSenderEmail, giftCardMessage;
_productAttributeParser.GetGiftCardAttribute(updatecartitem.AttributesXml,
out giftCardRecipientName, out giftCardRecipientEmail,
out giftCardSenderName, out giftCardSenderEmail, out giftCardMessage);
model.GiftCard.RecipientName = giftCardRecipientName;
model.GiftCard.RecipientEmail = giftCardRecipientEmail;
model.GiftCard.SenderName = giftCardSenderName;
model.GiftCard.SenderEmail = giftCardSenderEmail;
model.GiftCard.Message = giftCardMessage;
}
}
#endregion
#region Product attributes
//performance optimization
//We cache a value indicating whether a product has attributes
IList<ProductVariantAttribute> productVariantAttributes = null;
string cacheKey = string.Format(ModelCacheEventConsumer.PRODUCT_HAS_PRODUCT_ATTRIBUTES_KEY, product.Id);
var hasProductAttributesCache = _cacheManager.Get<bool?>(cacheKey);
if (!hasProductAttributesCache.HasValue)
{
//no value in the cache yet
//let's load attributes and cache the result (true/false)
productVariantAttributes = _productAttributeService.GetProductVariantAttributesByProductId(product.Id);
hasProductAttributesCache = productVariantAttributes.Count > 0;
_cacheManager.Set(cacheKey, hasProductAttributesCache, 60);
}
if (hasProductAttributesCache.Value && productVariantAttributes == null)
{
//cache indicates that the product has attributes
//let's load them
productVariantAttributes = _productAttributeService.GetProductVariantAttributesByProductId(product.Id);
}
if (productVariantAttributes == null)
{
productVariantAttributes = new List<ProductVariantAttribute>();
}
foreach (var attribute in productVariantAttributes)
{
var pvaModel = new ProductDetailsModel.ProductVariantAttributeModel()
{
Id = attribute.Id,
ProductId = product.Id,
ProductAttributeId = attribute.ProductAttributeId,
Name = attribute.ProductAttribute.GetLocalized(x => x.Name),
Description = attribute.ProductAttribute.GetLocalized(x => x.Description),
TextPrompt = attribute.TextPrompt,
IsRequired = attribute.IsRequired,
AttributeControlType = attribute.AttributeControlType,
DefaultValue = updatecartitem != null ? null : attribute.DefaultValue,
};
if (!String.IsNullOrEmpty(attribute.ValidationFileAllowedExtensions))
{
pvaModel.AllowedFileExtensions = attribute.ValidationFileAllowedExtensions
.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries)
.ToList();
}
if (attribute.ShouldHaveValues())
{
//values
var pvaValues = _productAttributeService.GetProductVariantAttributeValues(attribute.Id);
foreach (var pvaValue in pvaValues)
{
var pvaValueModel = new ProductDetailsModel.ProductVariantAttributeValueModel()
{
Id = pvaValue.Id,
Name = pvaValue.GetLocalized(x => x.Name),
ColorSquaresRgb = pvaValue.ColorSquaresRgb, //used with "Color squares" attribute type
IsPreSelected = pvaValue.IsPreSelected
};
pvaModel.Values.Add(pvaValueModel);
//display price if allowed
if (_permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
{
decimal taxRate = decimal.Zero;
decimal pvaValuePriceAdjustment = _priceCalculationService.GetProductVariantAttributeValuePriceAdjustment(pvaValue);
decimal priceAdjustmentBase = _taxService.GetProductPrice(product, pvaValuePriceAdjustment, out taxRate);
decimal priceAdjustment = _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, _workContext.WorkingCurrency);
if (priceAdjustmentBase > decimal.Zero)
pvaValueModel.PriceAdjustment = "+" + _priceFormatter.FormatPrice(priceAdjustment, false, false);
else if (priceAdjustmentBase < decimal.Zero)
pvaValueModel.PriceAdjustment = "-" + _priceFormatter.FormatPrice(-priceAdjustment, false, false);
pvaValueModel.PriceAdjustmentValue = priceAdjustment;
}
//picture
var pvavPicture = _pictureService.GetPictureById(pvaValue.PictureId);
if (pvavPicture != null)
{
pvaValueModel.PictureUrl = _pictureService.GetPictureUrl(pvavPicture, defaultPictureSize);
pvaValueModel.FullSizePictureUrl = _pictureService.GetPictureUrl(pvavPicture);
pvaValueModel.PictureId = pvavPicture.Id;
}
}
}
//set already selected attributes (if we're going to update the existing shopping cart item)
if (updatecartitem != null)
{
switch (attribute.AttributeControlType)
{
case AttributeControlType.DropdownList:
case AttributeControlType.RadioList:
case AttributeControlType.Checkboxes:
case AttributeControlType.ColorSquares:
{
if (!String.IsNullOrEmpty(updatecartitem.AttributesXml))
{
//clear default selection
foreach (var item in pvaModel.Values)
item.IsPreSelected = false;
//select new values
var selectedPvaValues = _productAttributeParser.ParseProductVariantAttributeValues(updatecartitem.AttributesXml);
foreach (var pvaValue in selectedPvaValues)
foreach (var item in pvaModel.Values)
if (pvaValue.Id == item.Id)
item.IsPreSelected = true;
}
}
break;
case AttributeControlType.ReadonlyCheckboxes:
{
//do nothing
//values are already pre-set
}
break;
case AttributeControlType.TextBox:
case AttributeControlType.MultilineTextbox:
{
if (!String.IsNullOrEmpty(updatecartitem.AttributesXml))
{
var enteredText = _productAttributeParser.ParseValues(updatecartitem.AttributesXml, attribute.Id);
if (enteredText.Count > 0)
pvaModel.DefaultValue = enteredText[0];
}
}
break;
case AttributeControlType.Datepicker:
{
//keep in mind my that the code below works only in the current culture
var selectedDateStr = _productAttributeParser.ParseValues(updatecartitem.AttributesXml, attribute.Id);
if (selectedDateStr.Count > 0)
{
DateTime selectedDate;
if (DateTime.TryParseExact(selectedDateStr[0], "D", CultureInfo.CurrentCulture,
DateTimeStyles.None, out selectedDate))
{
//successfully parsed
pvaModel.SelectedDay = selectedDate.Day;
pvaModel.SelectedMonth = selectedDate.Month;
pvaModel.SelectedYear = selectedDate.Year;
}
}
}
break;
default:
break;
}
}
model.ProductVariantAttributes.Add(pvaModel);
}
#endregion
#region Product specifications
//do not prepare this model for the associated products. any it's not used
if (!isAssociatedProduct)
{
model.ProductSpecifications = this.PrepareProductSpecificationModel(_workContext,
_specificationAttributeService,
_cacheManager,
product);
}
#endregion
#region Product review overview
model.ProductReviewOverview = new ProductReviewOverviewModel()
{
ProductId = product.Id,
RatingSum = product.ApprovedRatingSum,
TotalReviews = product.ApprovedTotalReviews,
AllowCustomerReviews = product.AllowCustomerReviews
};
#endregion
#region Tier prices
if (product.HasTierPrices && _permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
{
model.TierPrices = product.TierPrices
.OrderBy(x => x.Quantity)
.ToList()
.FilterByStore(_storeContext.CurrentStore.Id)
.FilterForCustomer(_workContext.CurrentCustomer)
.RemoveDuplicatedQuantities()
.Select(tierPrice =>
{
var m = new ProductDetailsModel.TierPriceModel()
{
Quantity = tierPrice.Quantity,
};
decimal taxRate = decimal.Zero;
decimal priceBase = _taxService.GetProductPrice(product, _priceCalculationService.GetFinalPrice(product, _workContext.CurrentCustomer, decimal.Zero, _catalogSettings.DisplayTierPricesWithDiscounts, tierPrice.Quantity), out taxRate);
decimal price = _currencyService.ConvertFromPrimaryStoreCurrency(priceBase, _workContext.WorkingCurrency);
m.Price = _priceFormatter.FormatPrice(price, false, false);
return m;
})
.ToList();
}
#endregion
#region Manufacturers
//do not prepare this model for the associated products. any it's not used
if (!isAssociatedProduct)
{
string manufacturersCacheKey = string.Format(ModelCacheEventConsumer.PRODUCT_MANUFACTURERS_MODEL_KEY, product.Id, _workContext.WorkingLanguage.Id, string.Join(",", customerRolesIds), _storeContext.CurrentStore.Id);
model.ProductManufacturers = _cacheManager.Get(manufacturersCacheKey, () =>
{
return _manufacturerService.GetProductManufacturersByProductId(product.Id)
.Select(x => x.Manufacturer.ToModel())
.ToList();
});
}
#endregion
#region Associated products
if (product.ProductType == ProductType.GroupedProduct)
{
//ensure no circular references
if (!isAssociatedProduct)
{
var associatedProducts = _productService.GetAssociatedProducts(product.Id, _storeContext.CurrentStore.Id);
foreach (var associatedProduct in associatedProducts)
model.AssociatedProducts.Add(PrepareProductDetailsPageModel(associatedProduct, null, true));
}
}
#endregion
return model;
}
[NonAction]
protected virtual void PrepareProductReviewsModel(ProductReviewsModel model, Product product)
{
if (product == null)
throw new ArgumentNullException("product");
if (model == null)
throw new ArgumentNullException("model");
model.ProductId = product.Id;
model.ProductName = product.GetLocalized(x => x.Name);
model.ProductSeName = product.GetSeName();
var productReviews = product.ProductReviews.Where(pr => pr.IsApproved).OrderBy(pr => pr.CreatedOnUtc);
foreach (var pr in productReviews)
{
var customer = pr.Customer;
model.Items.Add(new ProductReviewModel()
{
Id = pr.Id,
CustomerId = pr.CustomerId,
CustomerName = customer.FormatUserName(),
AllowViewingProfiles = _customerSettings.AllowViewingProfiles && customer != null && !customer.IsGuest(),
Title = pr.Title,
ReviewText = pr.ReviewText,
Rating = pr.Rating,
Helpfulness = new ProductReviewHelpfulnessModel()
{
ProductReviewId = pr.Id,
HelpfulYesTotal = pr.HelpfulYesTotal,
HelpfulNoTotal = pr.HelpfulNoTotal,
},
WrittenOnStr = _dateTimeHelper.ConvertToUserTime(pr.CreatedOnUtc, DateTimeKind.Utc).ToString("g"),
});
}
model.AddProductReview.CanCurrentCustomerLeaveReview = _catalogSettings.AllowAnonymousUsersToReviewProduct || !_workContext.CurrentCustomer.IsGuest();
model.AddProductReview.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnProductReviewPage;
}
#endregion
#region Product details page
[NopHttpsRequirement(SslRequirement.No)]
public ActionResult ProductDetails(int productId, int updatecartitemid = 0)
{
var product = _productService.GetProductById(productId);
if (product == null || product.Deleted)
return InvokeHttp404();
//Is published?
//Check whether the current user has a "Manage catalog" permission
//It allows him to preview a product before publishing
if (!product.Published && !_permissionService.Authorize(StandardPermissionProvider.ManageProducts))
return InvokeHttp404();
//ACL (access control list)
if (!_aclService.Authorize(product))
return InvokeHttp404();
//Store mapping
if (!_storeMappingService.Authorize(product))
return InvokeHttp404();
//visible individually?
if (!product.VisibleIndividually)
{
//is this one an associated products?
var parentGroupedProduct = _productService.GetProductById(product.ParentGroupedProductId);
if (parentGroupedProduct != null)
{
return RedirectToRoute("Product", new { SeName = parentGroupedProduct.GetSeName() });
}
else
{
return RedirectToRoute("HomePage");
}
}
//update existing shopping cart item?
ShoppingCartItem updatecartitem = null;
if (_shoppingCartSettings.AllowCartItemEditing && updatecartitemid > 0)
{
var cart = _workContext.CurrentCustomer.ShoppingCartItems
.Where(x => x.ShoppingCartType == ShoppingCartType.ShoppingCart)
.LimitPerStore(_storeContext.CurrentStore.Id)
.ToList();
updatecartitem = cart.FirstOrDefault(x => x.Id == updatecartitemid);
//not found?
if (updatecartitem == null)
{
return RedirectToRoute("Product", new { SeName = product.GetSeName() });
}
//is it this product?
if (product.Id != updatecartitem.ProductId)
{
return RedirectToRoute("Product", new { SeName = product.GetSeName() });
}
}
//prepare the model
var model = PrepareProductDetailsPageModel(product, updatecartitem, false);
//save as recently viewed
_recentlyViewedProductsService.AddProductToRecentlyViewedList(product.Id);
//activity log
_customerActivityService.InsertActivity("PublicStore.ViewProduct", _localizationService.GetResource("ActivityLog.PublicStore.ViewProduct"), product.Name);
return View(model.ProductTemplateViewPath, model);
}
[ChildActionOnly]
public ActionResult RelatedProducts(int productId, int? productThumbPictureSize)
{
//load and cache report
var productIds = _cacheManager.Get(string.Format(ModelCacheEventConsumer.PRODUCTS_RELATED_IDS_KEY, productId, _storeContext.CurrentStore.Id),
() =>
_productService.GetRelatedProductsByProductId1(productId).Select(x => x.ProductId2).ToArray()
);
//load products
var products = _productService.GetProductsByIds(productIds);
//ACL and store mapping
products = products.Where(p => _aclService.Authorize(p) && _storeMappingService.Authorize(p)).ToList();
if (products.Count == 0)
return Content("");
var model = PrepareProductOverviewModels(products, true, true, productThumbPictureSize).ToList();
return PartialView(model);
}
[ChildActionOnly]
public ActionResult ProductsAlsoPurchased(int productId, int? productThumbPictureSize)
{
if (!_catalogSettings.ProductsAlsoPurchasedEnabled)
return Content("");
//load and cache report
var productIds = _cacheManager.Get(string.Format(ModelCacheEventConsumer.PRODUCTS_ALSO_PURCHASED_IDS_KEY, productId, _storeContext.CurrentStore.Id),
() =>
_orderReportService
.GetAlsoPurchasedProductsIds(_storeContext.CurrentStore.Id, productId, _catalogSettings.ProductsAlsoPurchasedNumber)
);
//load products
var products = _productService.GetProductsByIds(productIds);
//ACL and store mapping
products = products.Where(p => _aclService.Authorize(p) && _storeMappingService.Authorize(p)).ToList();
if (products.Count == 0)
return Content("");
//prepare model
var model = PrepareProductOverviewModels(products, true, true, productThumbPictureSize).ToList();
return PartialView(model);
}
[ChildActionOnly]
public ActionResult CrossSellProducts(int? productThumbPictureSize)
{
var cart = _workContext.CurrentCustomer.ShoppingCartItems
.Where(sci => sci.ShoppingCartType == ShoppingCartType.ShoppingCart)
.LimitPerStore(_storeContext.CurrentStore.Id)
.ToList();
var products = _productService.GetCrosssellProductsByShoppingCart(cart, _shoppingCartSettings.CrossSellsNumber);
//ACL and store mapping
products = products.Where(p => _aclService.Authorize(p) && _storeMappingService.Authorize(p)).ToList();
if (products.Count == 0)
return Content("");
//Cross-sell products are dispalyed on the shopping cart page.
//We know that the entire shopping cart page is not refresh
//even if "ShoppingCartSettings.DisplayCartAfterAddingProduct" setting is enabled.
//That's why we force page refresh (redirect) in this case
var model = PrepareProductOverviewModels(products,
productThumbPictureSize: productThumbPictureSize, forceRedirectionAfterAddingToCart: true)
.ToList();
return PartialView(model);
}
#endregion
#region Recently viewed products
[NopHttpsRequirement(SslRequirement.No)]
public ActionResult RecentlyViewedProducts()
{
if (!_catalogSettings.RecentlyViewedProductsEnabled)
return Content("");
var products = _recentlyViewedProductsService.GetRecentlyViewedProducts(_catalogSettings.RecentlyViewedProductsNumber);
var model = new List<ProductOverviewModel>();
model.AddRange(PrepareProductOverviewModels(products));
return View(model);
}
[ChildActionOnly]
public ActionResult RecentlyViewedProductsBlock(int? productThumbPictureSize, bool? preparePriceModel)
{
if (!_catalogSettings.RecentlyViewedProductsEnabled)
return Content("");
var preparePictureModel = productThumbPictureSize.HasValue;
var products = _recentlyViewedProductsService.GetRecentlyViewedProducts(_catalogSettings.RecentlyViewedProductsNumber);
//ACL and store mapping
products = products.Where(p => _aclService.Authorize(p) && _storeMappingService.Authorize(p)).ToList();
if (products.Count == 0)
return Content("");
//prepare model
var model = new List<ProductOverviewModel>();
model.AddRange(PrepareProductOverviewModels(products,
preparePriceModel.HasValue ? preparePriceModel.Value : false,
preparePictureModel,
productThumbPictureSize));
return PartialView(model);
}
#endregion
#region Rrecently added products
[NopHttpsRequirement(SslRequirement.No)]
public ActionResult RecentlyAddedProducts()
{
if (!_catalogSettings.RecentlyAddedProductsEnabled)
return Content("");
var products = _productService.SearchProducts(
storeId: _storeContext.CurrentStore.Id,
visibleIndividuallyOnly: true,
orderBy: ProductSortingEnum.CreatedOn,
pageSize: _catalogSettings.RecentlyAddedProductsNumber);
var model = new List<ProductOverviewModel>();
model.AddRange(PrepareProductOverviewModels(products));
return View(model);
}
public ActionResult RecentlyAddedProductsRss()
{
var feed = new SyndicationFeed(
string.Format("{0}: Recently added products", _storeContext.CurrentStore.GetLocalized(x => x.Name)),
"Information about products",
new Uri(_webHelper.GetStoreLocation(false)),
"RecentlyAddedProductsRSS",
DateTime.UtcNow);
if (!_catalogSettings.RecentlyAddedProductsEnabled)
return new RssActionResult() { Feed = feed };
var items = new List<SyndicationItem>();
var products = _productService.SearchProducts(
storeId: _storeContext.CurrentStore.Id,
visibleIndividuallyOnly: true,
orderBy: ProductSortingEnum.CreatedOn,
pageSize: _catalogSettings.RecentlyAddedProductsNumber);
foreach (var product in products)
{
string productUrl = Url.RouteUrl("Product", new { SeName = product.GetSeName() }, "http");
string productName = product.GetLocalized(x => x.Name);
string productDescription = product.GetLocalized(x => x.ShortDescription);
var item = new SyndicationItem(productName, productDescription, new Uri(productUrl), String.Format("RecentlyAddedProduct:{0}", product.Id), product.CreatedOnUtc);
items.Add(item);
//uncomment below if you want to add RSS enclosure for pictures
//var picture = _pictureService.GetPicturesByProductId(product.Id, 1).FirstOrDefault();
//if (picture != null)
//{
// var imageUrl = _pictureService.GetPictureUrl(picture, _mediaSettings.ProductDetailsPictureSize);
// item.ElementExtensions.Add(new XElement("enclosure", new XAttribute("type", "image/jpeg"), new XAttribute("url", imageUrl)).CreateReader());
//}
}
feed.Items = items;
return new RssActionResult() { Feed = feed };
}
#endregion
#region Home page bestsellers and products
[ChildActionOnly]
public ActionResult HomepageBestSellers(int? productThumbPictureSize)
{
if (!_catalogSettings.ShowBestsellersOnHomepage || _catalogSettings.NumberOfBestsellersOnHomepage == 0)
return Content("");
//load and cache report
var report = _cacheManager.Get(string.Format(ModelCacheEventConsumer.HOMEPAGE_BESTSELLERS_IDS_KEY, _storeContext.CurrentStore.Id),
() =>
_orderReportService.BestSellersReport(storeId: _storeContext.CurrentStore.Id,
pageSize: _catalogSettings.NumberOfBestsellersOnHomepage));
//load products
var products = _productService.GetProductsByIds(report.Select(x => x.ProductId).ToArray());
//ACL and store mapping
products = products.Where(p => _aclService.Authorize(p) && _storeMappingService.Authorize(p)).ToList();
if (products.Count == 0)
return Content("");
//prepare model
var model = PrepareProductOverviewModels(products, true, true, productThumbPictureSize).ToList();
return PartialView(model);
}
[ChildActionOnly]
public ActionResult HomepageProducts(int? productThumbPictureSize)
{
var products = _productService.GetAllProductsDisplayedOnHomePage();
//ACL and store mapping
products = products.Where(p => _aclService.Authorize(p) && _storeMappingService.Authorize(p)).ToList();
if (products.Count == 0)
return Content("");
var model = PrepareProductOverviewModels(products, true, true, productThumbPictureSize).ToList();
return PartialView(model);
}
#endregion
#region Back in stock subscriptions
public ActionResult BackInStockSubscribePopup(int productId)
{
var product = _productService.GetProductById(productId);
if (product == null || product.Deleted)
throw new ArgumentException("No product found with the specified id");
var model = new BackInStockSubscribeModel();
model.ProductId = product.Id;
model.ProductName = product.GetLocalized(x => x.Name);
model.ProductSeName = product.GetSeName();
model.IsCurrentCustomerRegistered = _workContext.CurrentCustomer.IsRegistered();
model.MaximumBackInStockSubscriptions = _catalogSettings.MaximumBackInStockSubscriptions;
model.CurrentNumberOfBackInStockSubscriptions = _backInStockSubscriptionService
.GetAllSubscriptionsByCustomerId(_workContext.CurrentCustomer.Id, _storeContext.CurrentStore.Id, 0, 1)
.TotalCount;
if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock &&
product.BackorderMode == BackorderMode.NoBackorders &&
product.AllowBackInStockSubscriptions &&
product.StockQuantity <= 0)
{
//out of stock
model.SubscriptionAllowed = true;
model.AlreadySubscribed = _backInStockSubscriptionService
.FindSubscription(_workContext.CurrentCustomer.Id, product.Id, _storeContext.CurrentStore.Id) != null;
}
return View(model);
}
[HttpPost, ActionName("BackInStockSubscribePopup")]
public ActionResult BackInStockSubscribePopupPOST(int productId)
{
var product = _productService.GetProductById(productId);
if (product == null || product.Deleted)
throw new ArgumentException("No product found with the specified id");
if (!_workContext.CurrentCustomer.IsRegistered())
return Content(_localizationService.GetResource("BackInStockSubscriptions.OnlyRegistered"));
if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock &&
product.BackorderMode == BackorderMode.NoBackorders &&
product.AllowBackInStockSubscriptions &&
product.StockQuantity <= 0)
{
//out of stock
var subscription = _backInStockSubscriptionService
.FindSubscription(_workContext.CurrentCustomer.Id, product.Id, _storeContext.CurrentStore.Id);
if (subscription != null)
{
//unsubscribe
_backInStockSubscriptionService.DeleteSubscription(subscription);
return Content("Unsubscribed");
}
else
{
if (_backInStockSubscriptionService
.GetAllSubscriptionsByCustomerId(_workContext.CurrentCustomer.Id, _storeContext.CurrentStore.Id, 0, 1)
.TotalCount >= _catalogSettings.MaximumBackInStockSubscriptions)
return Content(string.Format(_localizationService.GetResource("BackInStockSubscriptions.MaxSubscriptions"), _catalogSettings.MaximumBackInStockSubscriptions));
//subscribe
subscription = new BackInStockSubscription()
{
Customer = _workContext.CurrentCustomer,
Product = product,
StoreId = _storeContext.CurrentStore.Id,
CreatedOnUtc = DateTime.UtcNow
};
_backInStockSubscriptionService.InsertSubscription(subscription);
return Content("Subscribed");
}
}
else
{
return Content(_localizationService.GetResource("BackInStockSubscriptions.NotAllowed"));
}
}
#endregion
#region Product reviews
[NopHttpsRequirement(SslRequirement.No)]
public ActionResult ProductReviews(int productId)
{
var product = _productService.GetProductById(productId);
if (product == null || product.Deleted || !product.Published || !product.AllowCustomerReviews)
return RedirectToRoute("HomePage");
var model = new ProductReviewsModel();
PrepareProductReviewsModel(model, product);
//only registered users can leave reviews
if (_workContext.CurrentCustomer.IsGuest() && !_catalogSettings.AllowAnonymousUsersToReviewProduct)
ModelState.AddModelError("", _localizationService.GetResource("Reviews.OnlyRegisteredUsersCanWriteReviews"));
//default value
model.AddProductReview.Rating = _catalogSettings.DefaultProductRatingValue;
return View(model);
}
[HttpPost, ActionName("ProductReviews")]
[FormValueRequired("add-review")]
[CaptchaValidator]
public ActionResult ProductReviewsAdd(int productId, ProductReviewsModel model, bool captchaValid)
{
var product = _productService.GetProductById(productId);
if (product == null || product.Deleted || !product.Published || !product.AllowCustomerReviews)
return RedirectToRoute("HomePage");
//validate CAPTCHA
if (_captchaSettings.Enabled && _captchaSettings.ShowOnProductReviewPage && !captchaValid)
{
ModelState.AddModelError("", _localizationService.GetResource("Common.WrongCaptcha"));
}
if (_workContext.CurrentCustomer.IsGuest() && !_catalogSettings.AllowAnonymousUsersToReviewProduct)
{
ModelState.AddModelError("", _localizationService.GetResource("Reviews.OnlyRegisteredUsersCanWriteReviews"));
}
if (ModelState.IsValid)
{
//save review
int rating = model.AddProductReview.Rating;
if (rating < 1 || rating > 5)
rating = _catalogSettings.DefaultProductRatingValue;
bool isApproved = !_catalogSettings.ProductReviewsMustBeApproved;
var productReview = new ProductReview()
{
ProductId = product.Id,
CustomerId = _workContext.CurrentCustomer.Id,
Title = model.AddProductReview.Title,
ReviewText = model.AddProductReview.ReviewText,
Rating = rating,
HelpfulYesTotal = 0,
HelpfulNoTotal = 0,
IsApproved = isApproved,
CreatedOnUtc = DateTime.UtcNow,
};
product.ProductReviews.Add(productReview);
_productService.UpdateProduct(product);
//update product totals
_productService.UpdateProductReviewTotals(product);
//notify store owner
if (_catalogSettings.NotifyStoreOwnerAboutNewProductReviews)
_workflowMessageService.SendProductReviewNotificationMessage(productReview, _localizationSettings.DefaultAdminLanguageId);
//activity log
_customerActivityService.InsertActivity("PublicStore.AddProductReview", _localizationService.GetResource("ActivityLog.PublicStore.AddProductReview"), product.Name);
PrepareProductReviewsModel(model, product);
model.AddProductReview.Title = null;
model.AddProductReview.ReviewText = null;
model.AddProductReview.SuccessfullyAdded = true;
if (!isApproved)
model.AddProductReview.Result = _localizationService.GetResource("Reviews.SeeAfterApproving");
else
model.AddProductReview.Result = _localizationService.GetResource("Reviews.SuccessfullyAdded");
return View(model);
}
//If we got this far, something failed, redisplay form
PrepareProductReviewsModel(model, product);
return View(model);
}
[HttpPost]
public ActionResult SetProductReviewHelpfulness(int productReviewId, bool washelpful)
{
var productReview = _productService.GetProductReviewById(productReviewId);
if (productReview == null)
throw new ArgumentException("No product review found with the specified id");
if (_workContext.CurrentCustomer.IsGuest() && !_catalogSettings.AllowAnonymousUsersToReviewProduct)
{
return Json(new
{
Result = _localizationService.GetResource("Reviews.Helpfulness.OnlyRegistered"),
TotalYes = productReview.HelpfulYesTotal,
TotalNo = productReview.HelpfulNoTotal
});
}
//customers aren't allowed to vote for their own reviews
if (productReview.CustomerId == _workContext.CurrentCustomer.Id)
{
return Json(new
{
Result = _localizationService.GetResource("Reviews.Helpfulness.YourOwnReview"),
TotalYes = productReview.HelpfulYesTotal,
TotalNo = productReview.HelpfulNoTotal
});
}
//delete previous helpfulness
var prh = productReview.ProductReviewHelpfulnessEntries
.FirstOrDefault(x => x.CustomerId == _workContext.CurrentCustomer.Id);
if (prh != null)
{
//existing one
prh.WasHelpful = washelpful;
}
else
{
//insert new helpfulness
prh = new ProductReviewHelpfulness()
{
ProductReviewId = productReview.Id,
CustomerId = _workContext.CurrentCustomer.Id,
WasHelpful = washelpful,
};
productReview.ProductReviewHelpfulnessEntries.Add(prh);
}
_productService.UpdateProduct(productReview.Product);
//new totals
productReview.HelpfulYesTotal = productReview.ProductReviewHelpfulnessEntries.Count(x => x.WasHelpful);
productReview.HelpfulNoTotal = productReview.ProductReviewHelpfulnessEntries.Count(x => !x.WasHelpful);
_productService.UpdateProduct(productReview.Product);
return Json(new
{
Result = _localizationService.GetResource("Reviews.Helpfulness.SuccessfullyVoted"),
TotalYes = productReview.HelpfulYesTotal,
TotalNo = productReview.HelpfulNoTotal
});
}
#endregion
#region Email a friend
[NopHttpsRequirement(SslRequirement.No)]
public ActionResult ProductEmailAFriend(int productId)
{
var product = _productService.GetProductById(productId);
if (product == null || product.Deleted || !product.Published || !_catalogSettings.EmailAFriendEnabled)
return RedirectToRoute("HomePage");
var model = new ProductEmailAFriendModel();
model.ProductId = product.Id;
model.ProductName = product.GetLocalized(x => x.Name);
model.ProductSeName = product.GetSeName();
model.YourEmailAddress = _workContext.CurrentCustomer.Email;
model.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnEmailProductToFriendPage;
return View(model);
}
[HttpPost, ActionName("ProductEmailAFriend")]
[FormValueRequired("send-email")]
[CaptchaValidator]
public ActionResult ProductEmailAFriendSend(ProductEmailAFriendModel model, bool captchaValid)
{
var product = _productService.GetProductById(model.ProductId);
if (product == null || product.Deleted || !product.Published || !_catalogSettings.EmailAFriendEnabled)
return RedirectToRoute("HomePage");
//validate CAPTCHA
if (_captchaSettings.Enabled && _captchaSettings.ShowOnEmailProductToFriendPage && !captchaValid)
{
ModelState.AddModelError("", _localizationService.GetResource("Common.WrongCaptcha"));
}
//check whether the current customer is guest and ia allowed to email a friend
if (_workContext.CurrentCustomer.IsGuest() && !_catalogSettings.AllowAnonymousUsersToEmailAFriend)
{
ModelState.AddModelError("", _localizationService.GetResource("Products.EmailAFriend.OnlyRegisteredUsers"));
}
if (ModelState.IsValid)
{
//email
_workflowMessageService.SendProductEmailAFriendMessage(_workContext.CurrentCustomer,
_workContext.WorkingLanguage.Id, product,
model.YourEmailAddress, model.FriendEmail,
Core.Html.HtmlHelper.FormatText(model.PersonalMessage, false, true, false, false, false, false));
model.ProductId = product.Id;
model.ProductName = product.GetLocalized(x => x.Name);
model.ProductSeName = product.GetSeName();
model.SuccessfullySent = true;
model.Result = _localizationService.GetResource("Products.EmailAFriend.SuccessfullySent");
return View(model);
}
//If we got this far, something failed, redisplay form
model.ProductId = product.Id;
model.ProductName = product.GetLocalized(x => x.Name);
model.ProductSeName = product.GetSeName();
model.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnEmailProductToFriendPage;
return View(model);
}
#endregion
#region Comparing products
public ActionResult AddProductToCompareList(int productId)
{
var product = _productService.GetProductById(productId);
if (product == null || product.Deleted || !product.Published)
return RedirectToRoute("HomePage");
if (!_catalogSettings.CompareProductsEnabled)
return RedirectToRoute("HomePage");
_compareProductsService.AddProductToCompareList(productId);
//activity log
_customerActivityService.InsertActivity("PublicStore.AddToCompareList", _localizationService.GetResource("ActivityLog.PublicStore.AddToCompareList"), product.Name);
return RedirectToRoute("CompareProducts");
}
public ActionResult RemoveProductFromCompareList(int productId)
{
var product = _productService.GetProductById(productId);
if (product == null)
return RedirectToRoute("HomePage");
if (!_catalogSettings.CompareProductsEnabled)
return RedirectToRoute("HomePage");
_compareProductsService.RemoveProductFromCompareList(productId);
return RedirectToRoute("CompareProducts");
}
[NopHttpsRequirement(SslRequirement.No)]
public ActionResult CompareProducts()
{
if (!_catalogSettings.CompareProductsEnabled)
return RedirectToRoute("HomePage");
var model = new CompareProductsModel()
{
IncludeShortDescriptionInCompareProducts = _catalogSettings.IncludeShortDescriptionInCompareProducts,
IncludeFullDescriptionInCompareProducts = _catalogSettings.IncludeFullDescriptionInCompareProducts,
};
var products = _compareProductsService.GetComparedProducts();
//ACL and store mapping
products = products.Where(p => _aclService.Authorize(p) && _storeMappingService.Authorize(p)).ToList();
//prepare model
PrepareProductOverviewModels(products, prepareSpecificationAttributes: true)
.ToList()
.ForEach(model.Products.Add);
return View(model);
}
public ActionResult ClearCompareList()
{
if (!_catalogSettings.CompareProductsEnabled)
return RedirectToRoute("HomePage");
_compareProductsService.ClearCompareProducts();
return RedirectToRoute("CompareProducts");
}
#endregion
}