In the Bleak Midwinter

Exception in template (Designs\Lorenz\eCom/Product/product.cshtml): System.ArgumentOutOfRangeException: Length cannot be less than zero.
Parameter name: length
   at System.String.Substring(Int32 startIndex, Int32 length)
   at CompiledRazorTemplates.Dynamic.bfeefcdcaeeaeeeeba.Execute()
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context)
   at RazorEngine.Templating.TemplateService.Run(ITemplate template, DynamicViewBag viewBag)
   at RazorEngine.Templating.TemplateService.Parse(String razorTemplate, Object model, DynamicViewBag viewBag, String cacheName)
   at RazorEngine.Razor.Parse[T](String razorTemplate, T model, String cacheName)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()
@using System.IO; @using System.Web; @using System.Text; @using System.Text.RegularExpressions; @functions { public static string image(string imgSmall = "", string imgMedium = "", string imgLarge = "") { string str_image; if (imgSmall != "") { str_image = imgSmall; } else if (imgMedium != "") { str_image = imgMedium; } else if (imgLarge != "") { str_image = imgLarge; } else { str_image = ""; } return str_image; } public static string GetImage(string str_source, int num_width, int num_height = 0, string str_alternativeImage = "", int num_crop = 5) { var str_width = ""; var str_height = ""; if (num_width != 0) { str_width = "&amp;Width=" + num_width; } if (num_height != 0) { str_height = "&amp;Height=" + num_height; } string str_output = "/Admin/Public/GetImage.ashx?Image=" + str_source + "&amp;Format=png" + str_width + str_height + "&amp;altFmImage_path=" + str_alternativeImage + "&amp;Crop=" + num_crop; return str_output.ToString(); } public static FileInfo getFileInfo(dynamic obj_options) { string str_domain = "http://mydeltaq.com"; FileInfo info = new FileInfo(obj_options.str_file); FileAttributes attributes = info.Attributes; return info; } public static string getFileSize(dynamic obj_options) { string str_domain = "http://mydeltaq.com"; string str_output = ""; System.Net.WebClient client = new System.Net.WebClient(); client.OpenRead(str_domain + obj_options.str_file); Int64 bytes_total = Convert.ToInt64(client.ResponseHeaders["Content-Length"]); str_output = SizeSuffix(bytes_total).ToString(); return str_output; } static readonly string[] SizeSuffixes = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; static string SizeSuffix(Int64 value) { if (value < 0) { return "-" + SizeSuffix(-value); } int i = 0; decimal dValue = (decimal)value; while (Math.Round(dValue / 1024) >= 1) { dValue /= 1024; i++; } return string.Format("{0:n1} {1}", dValue, SizeSuffixes[i]); } public static string GetFriendlyUrl(int num_pageId) { var output = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(num_pageId); return output; } public static object GetParagraph(int num_paragraphId) { return Dynamicweb.Services.Paragraphs.GetParagraph(num_paragraphId); } public static string StripHtml(string source) { return Regex.Replace(source, "<.*?>", string.Empty); } public static string GetRequest(string str_param = "") { string str_output = System.Web.HttpContext.Current.Request.QueryString[str_param]; return str_output; } public static string GetParam(string str_param = "") { string str_output = System.Web.HttpContext.Current.Request.Params[str_param]; return str_output; } public static void AddCookie(string str_name = "", string str_value = "") { var obj_cookie = new System.Web.HttpCookie(str_name); obj_cookie.Value = str_value; System.Web.HttpContext.Current.Response.Cookies.Add(obj_cookie); } public static void RemoveCookie(string str_name = "") { var obj_cookie = new System.Web.HttpCookie(str_name); obj_cookie.Expires = DateTime.Now.AddDays(-1d); System.Web.HttpContext.Current.Response.Cookies.Add(obj_cookie); } public static string GetCookie(string str_name = "") { string str_output = ""; if (System.Web.HttpContext.Current.Request.Cookies[str_name] != null) { str_output = System.Web.HttpContext.Current.Request.Cookies[str_name].Value; } return str_output; } public static bool ExistCookie(string str_name = "") { bool bol_output = false; if (System.Web.HttpContext.Current.Request.Cookies[str_name] != null) { bol_output = true; } return bol_output; } public static void Redirect(string str_url = "") { System.Web.HttpContext.Current.Response.Redirect(Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(str_url)); } /*example: Redirect("/Default.aspx?ID=12")*/ public static IHtmlString EncodeJS(string input) { StringBuilder builder = new StringBuilder(); // Open the double quotes builder.Append("\""); // Then add each character properly escaping them foreach (char c in input) { switch (c) { //First check whether it's one of the defined escape sequences case '\'': //single quote builder.Append("\\\'"); break; case '\"': //double quote builder.Append("\\\""); break; case '\\': //backslash builder.Append("\\\\"); break; case '\0': //Unicode character 0 builder.Append("\\0"); break; case '\a': //Alert (character 7) builder.Append("\\a"); break; case '\b': //Backspace (character 8) builder.Append("\\b"); break; case '\f': //Form feed (character 12) builder.Append("\\f"); break; case '\n': //New line (character 10) builder.Append("\\n"); break; case '\r': //Carriage return (character 13) builder.Append("\\r"); break; case '\t': //Horizontal tab (character 9) builder.Append("\\t"); break; case '\v': //Vertical quote (character 11) builder.Append("\\v"); break; default: // If it's none of the defined escape sequences, convert the character to an int and check the code int i = (int)c; if (i >= 32 && i <= 127) { // if it's a displayable ASCII character, just write the character builder.Append(c); } else { // otherwise write the Unicode escape sequence for the character with hex value builder.AppendFormat("\\u{0:X04}", i); } break; } } // Close the double quotes builder.Append("\""); // You have to return an IHtmlString otherwise an HTML escape will be performed e.g. < will be replaced by &lt; return new HtmlString(builder.ToString()); } } @using System; @using System.Collections.Generic; @using System.Web.Script.Serialization; @{ List<LoopItem> obj_loopVariantCombinations = GetLoop("VariantCombinations"); Dictionary<string, Dictionary<string, Dictionary<string, string>>> dic_product = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>(); Dictionary<string, Dictionary<string, string>> dic_variants = new Dictionary<string, Dictionary<string, string>>(); string str_productJSON = ""; if(obj_loopVariantCombinations.Count > 0){ foreach (LoopItem variant in obj_loopVariantCombinations){ string str_variantHref = "/"+ variant.GetValue("Ecom:VariantCombination.Link.Clean") + "?PID=" + Dynamicweb.Frontend.PageView.Current().CurrentParagraph.ID.ToString(); string str_articleNumJson = variant.GetString("Ecom:Product.Number"); string str_price = variant.GetString("Ecom:Product.Price"); string str_stock = variant.GetString("Ecom:Product.AvailableAmount"); string str_id = variant.GetString("Ecom:VariantCombination.VariantID"); string str_variantName = variant.GetString("Ecom:VariantCombination.VariantText"); Dictionary<string, string> dic_variant = new Dictionary<string, string>(); dic_variant.Add("name", str_variantName); dic_variant.Add("id", str_id); dic_variant.Add("number", str_articleNumJson); dic_variant.Add("price", str_price); dic_variant.Add("stock", str_stock); dic_variants.Add(str_id, dic_variant); } dic_product.Add("product", dic_variants); } str_productJSON = new JavaScriptSerializer().Serialize(dic_product); } @inherits RazorTemplateBase<RazorTemplateModel<Template>> @using System @using System.Collections.Generic @using System.IO @using System.Linq @using System.Net @using System.Web @using System.Web.Script.Serialization @using Dna.UrlServices @using Dynamicweb.Rendering @functions{ #region Css functions public static string GetPalletColorNumber(int number = 0) { switch (number) { case 1: return "#333333"; case 2: return "#ebebeb"; default: return "#ffffff"; } } public static string GetFontFamilyNumber(int number = 0) { switch (number) { case 1: return "font-family: Arial, sans-serif;"; default: return "font-family: Arial, sans-serif;"; } } public static string GetFontSize(int fontSize = 0) { return fontSize >= 0 ? string.Concat("font-size: ", fontSize, "px;") : "font-size: 14px"; } #endregion Css functions #region User functions public static string OrganizationsGroupId() { var user = Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUser(); var userGroup = user != null ? user.Groups.FirstOrDefault(x => x.Name.ToLower() == "organizations") : null; return userGroup != null ? userGroup.ID.ToString() : string.Empty; } public static string IndividualGroupId() { var user = Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUser(); var userGroup = user != null ? user.Groups.FirstOrDefault(x => x.Name.ToLower() == "individuals") : null; return userGroup != null ? userGroup.ID.ToString() : string.Empty; } public static string ChoralClubGroupId(string name) { var user = Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUser(); var userGroup = user.Groups.FirstOrDefault(x => String.Equals(x.Name, name, StringComparison.CurrentCultureIgnoreCase)); return userGroup != null ? userGroup.ID.ToString() : string.Empty; } #endregion User functions #region Cart Functions public static string SetStockStatus(string stockStatus, string productId, string languageId, out string status, out string statusIscon) { if (string.IsNullOrEmpty(stockStatus)) { var prod = Dynamicweb.Ecommerce.Products.Product.GetProductById(productId); if (prod != null) { stockStatus = prod.get_StockStatus(languageId).Text; } } var icon = ""; if (!string.IsNullOrEmpty(stockStatus)) { switch (stockStatus) { case "Downloadable": icon = "fa-download"; break; case "Out of Print": icon = "fa-times"; break; case "Available for Preorder": icon = "fa-check"; break; case "Available Now": icon = "fa-check"; break; default: icon = "fa-undo"; break; } } statusIscon = icon; status = stockStatus; return string.Empty; } public static string SetStockStatus(string stockStatus, string productId, string languageId, bool hasSubscription, out string status, out string statusIscon, out bool hasDownload, out bool hasProduct) { if (string.IsNullOrEmpty(stockStatus)) { var prod = Dynamicweb.Ecommerce.Products.Product.GetProductById(productId); if (prod != null) { stockStatus = prod.get_StockStatus(languageId).Text; } } var download = false; var product = false; var icon = ""; if (!string.IsNullOrEmpty(stockStatus)) { switch (stockStatus) { case "Downloadable": icon = "fa-download"; download = true; break; case "Out of Print": icon = "fa-times"; product = true; break; case "Available for Preorder": product = true; icon = "fa-check"; break; case "Available Now": product = !hasSubscription; icon = "fa-check"; break; default: product = true; icon = "fa-undo"; break; } } hasDownload = download; hasProduct = product; statusIscon = icon; status = stockStatus; return string.Empty; } #endregion public static string setCookie(dynamic obj_options) { var str_output = ""; if (obj_options.GetType().GetProperty("str_action") != null) { if (obj_options.str_action == "save") { var obj_cookie = new System.Web.HttpCookie(obj_options.str_key); obj_cookie.Value = obj_options.str_value; obj_cookie.Expires = DateTime.Now.AddDays(30d); System.Web.HttpContext.Current.Response.Cookies.Add(obj_cookie); } else if (obj_options.str_action == "get") { if (System.Web.HttpContext.Current.Request.Cookies[obj_options.str_key] != null) { str_output = System.Web.HttpContext.Current.Request.Cookies[obj_options.str_key].Value; } } } return str_output; } public static string toJson(List<Dictionary<string, string>> dictionary) { var json = new JavaScriptSerializer().Serialize(dictionary); return json; } public static string toJson(Dictionary<string, Dictionary<string, string>> dictionary) { var json = new JavaScriptSerializer().Serialize(dictionary); return json; } public static string GetAlternativeImage(string imagePath, string designFolder) { var request = (HttpWebRequest)HttpWebRequest.Create(imagePath); request.Method = "HEAD"; var originalPath = new Uri(HttpContext.Current.Request.Url.AbsoluteUri).OriginalString; var parentDirectory = originalPath.Substring(0, originalPath.LastIndexOf("/", StringComparison.InvariantCulture)); try { request.GetResponse(); return imagePath; } catch { imagePath = parentDirectory + designFolder + "images/alternativeimage.jpg"; return imagePath; } } public static bool FileExists(string filePath) { var request = (HttpWebRequest)HttpWebRequest.Create(filePath); request.Method = "HEAD"; try { request.GetResponse(); return true; } catch { return false; } } } @{ @* Tables and list helpers *@ @helper RenderTableRowSpacer(int height = 30, int colspan = 1, string style = "") { if (height == 0) { height = 30; } <tr> @if (colspan > 1) { @: <td @style colspan="@colspan" height="@height"></td> } else { <td @style height="@height"></td> } </tr> } @helper RenderTableCellSpacer(int width = 10, int height = 10) { if (width == 0) { width = 10; } if (height == 0) { height = 10; } <td style="@GetFontSize(@width);" width="@width" height="@height">&nbsp;</td> } } @inherits RazorTemplateBase<RazorTemplateModel<Template>> @using System @using Dynamicweb.Rendering @using Dynamicweb.Core @{ @helper RenderCopyright() { <div class="col-xs-12 text-left copyright">&copy; @DateTime.Now.Year @GetString("Item.Area.CompanyName") @GetString("Item.Area.Copyright")</div> } @helper RenderSocialMedia(bool hasLink = true, bool hasTitle = true) { <ul id="socialMedia"> <li> @if (hasTitle) { if (hasLink) { var followUs = GetString("Item.Area.FollowUs"); <a href="@followUs">@Translate("Follow Us")</a> } else { <p>@Translate("Follow Us")</p> } } <ul> @SnippetStart("socialMedia") @foreach (var socialItem in GetLoop("Item.Area.Social")) { var cssClass = socialItem.GetString("Item.Area.Social.Class"); var name = socialItem.GetString("Item.Area.Social.Name"); var link = socialItem.GetString("Item.Area.Social.Link"); var shareLink = socialItem.GetString("Item.Area.Social.ShareLink"); var detail = socialItem.GetString("Item.Area.Social.HideOnDetail"); var footer = socialItem.GetString("Item.Area.Social.HideOnFooter"); <li class="detail_@detail footer_@footer"><a title='@name' class="@cssClass fa" target="_blank" data-href="@shareLink" href="@link"><span>@name</span></a></li> } @SnippetEnd("socialMedia") @RenderSnippet("socialMedia") </ul> </li> </ul> } @helper RenderContacts(bool hasLabel = false, bool hasLink = true) { var contactUs = GetString("Item.Area.ContactUs"); if (hasLink) { <a href="@contactUs">@Translate("Contact Us")</a> } else { <p>@Translate("Call Us")</p> } <ul> @foreach (var contactItem in GetLoop("Item.Area.Contacts")) { var cssClass = contactItem.GetString("Item.Area.Contacts.ContactType.Value"); var name = contactItem.GetString("Item.Area.Contacts.Contact"); var href = ""; var cursor = "click"; var label = ""; if (cssClass == "phone") { href = "tel:" + name; cssClass = hasLabel ? "" : "fa fa-phone"; label = ""; @SnippetStart("contactPhone") <p class="col-xs-12 col-md-4 noPadding"><span>@Translate("Call Us"): </span><a href="@href">@name</a></p> @SnippetEnd("contactPhone") } else if (cssClass == "email") { href = "mailto:" + name; cssClass = hasLabel ? "" : "fa fa-envelope"; } else if (cssClass == "fax") { href = "javascript:void(0)"; cssClass = hasLabel ? "" : "fa fa-fax"; cursor = "noClick"; } <li class="@cursor"><a title='@name' href='@href.Replace("/", "-")'><span class="@cssClass">@label</span>@name</a></li> } </ul> } @helper RenderLogo(string companyName, string imageClass = "col-xs-4") { <figure class="@imageClass logo"> <a id="logo" href="/"> <img class="img-responsive" src="images/logo.jpg" alt="@companyName" title="@companyName"/> </a> </figure> } @helper RenderHtmlHeader() { var designFolder = GetString("Template:DesignBaseUrl"); <head> <title>@GetValue("Title")</title> @RenderSnippet("OGMeta") <meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta name="SKYPE_TOOLBAR" content="SKYPE_TOOLBAR_PARSER_COMPATIBLE"/> <meta name="viewport" content="initial-scale=1.0, width=device-width, user-scalable=no"> @GetValue("MetaTags") @GetValue("CopyRightNotice") @GetValue("Stylesheets") <link rel="shortcut icon" href="@(designFolder)images/favicon.ico" type="image/x-icon"/> @{ var minify = GetBoolean("Item.Area.MinifyCSSAndJavaScript"); var styleBundle = Dna.Optimizer.Renderer.RenderStyles(string.Format("{0}css", designFolder), "-wm-main-styles", new[] {"exceptions"}, minify, true); var scriptBundle = Dna.Optimizer.Renderer.RenderScripts(string.Format("{0}js", designFolder), "-wm-main-scripts", new[] {"exceptions"}, minify, true); } <link rel="stylesheet" href="@styleBundle"/> <script src="@scriptBundle"></script> <!--[if lte IE 9]> <script src="https://html5shim.googlecode.com/svn/trunk/html5.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/respond.js/1.1.0/respond.min.js"></script> <![endif]--> <script type="text/javascript"> var obj_settings = { obj_pages: { str_minicart : "@Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(GetPageIdByNavigationTag("MiniCart"))", str_validateUser : "@Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(GetPageIdByNavigationTag("ValidateUser"))", str_login: "@Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(GetPageIdByNavigationTag("MyAccount"))", str_createAccount: "@Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(GetPageIdByNavigationTag("CreateUser"))", str_subscribe: "@Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(GetPageIdByNavigationTag("Subscribe"))", str_gallery: "@Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(GetPageIdByNavigationTag("Gallery"))" } }; obj_formErrorMessages = { str_errorMessagesTitle: @EncodeJS(Translate("errorMessagesTitle", "Error")), str_closeWarning: @EncodeJS(Translate("errorMessagesCloseWarning", "close")), str_emptyField: @EncodeJS(Translate("emptyField", "Empty fields")), str_mustBeEqual: @EncodeJS(Translate("equalFields", "Fields must be equal")), str_cannotBeEqual: @EncodeJS(Translate("diferentFields", "Cannot be equal to")), str_viewFullDetail: @EncodeJS(Translate("viewFullDetail", "View full detail")), str_selectDefault: @EncodeJS(Translate("selectDefault", "Select default")), str_invalidEmail: @EncodeJS(Translate("invalidEmail", "Invalid e-mail")), str_invalidPassword_1: @EncodeJS(Translate("invalidPassword_1", "Password must be at least 8 characters long and both letters and numbers")), str_invalidPassword_2: @EncodeJS(Translate("invalidPassword_2", "Password must be at least 8 characters long.")), str_invalidPhoneNumber: @EncodeJS(Translate("invalidPhoneNumber", "Invalid phone number")), str_invalidDate: @EncodeJS(Translate("invalidDate", "Invalid date")), str_emailExists: @EncodeJS(GetString("Item.Area.EmailExists")), str_accountExists: @EncodeJS(GetString("Item.Area.AccountExists")), str_paymentError: @EncodeJS(Translate("Payment Information")), str_paymentErrorMessage: @EncodeJS(Translate("Please select a payment method")), str_invalidBirthdate: @EncodeJS(Translate("Invalid Birthdate")), str_invalidField: @EncodeJS(Translate("Invalid field")), str_selectCountry: @EncodeJS(Translate("Select country")), str_selectState: @EncodeJS(Translate("Select state")), str_selectProvince: @EncodeJS(Translate("Select province")) } obj_loginMessages = { str_login:@EncodeJS(Translate("login", "Login")), str_emailNotExists: @EncodeJS(Translate("emailNotExists", "Email not exists")), str_password: @EncodeJS(Translate("password", "Password")), str_forgotPassword: @EncodeJS(Translate("forgotPassword", "Forgot password?")), str_email: @EncodeJS(Translate("email", "Email")), str_username: @EncodeJS(Translate("username", "Username")), str_recoverPassword: @EncodeJS(Translate("recoverPassword", "Recover password")), str_errorPassword: @EncodeJS(Translate("emptyPassword", "Empty password")), str_errorEmailEmpty: @EncodeJS(Translate("emptyEmail", "Empty email")), str_errorUserEmpty: @EncodeJS(Translate("userEmpty", "Empty user")), str_errorEmail: @EncodeJS(Translate("invalidEmail", "Invalid email")), str_fillTheFields: @EncodeJS(Translate("fillTheFields", "Fill the fields")), str_wrongData: @EncodeJS(Translate("wrongData", "Wrong data")) }; obj_generalTranslates = { str_noSearchResultsTitle: @EncodeJS(Translate("noSearchResultsTitle", "NoSearchResultsTitle")), str_noSearchResultsText: @EncodeJS(Translate("noSearchResultsText", "NoSearchResultsText")) } obj_globalBootstrapSizes = { num_screenXS: @GetInteger("Item.Area.ScreenXS"), num_screenSM: @GetInteger("Item.Area.ScreenSM"), num_screenMD: @GetInteger("Item.Area.ScreenMD"), num_screenLG: @GetInteger("Item.Area.ScreenLG") } @RenderSnippet("jsVariables") $(function() { @RenderSnippet("jsOnLoadVariables") @RenderSnippet("jsOnLoad") }); $(window).load(function(){ @RenderSnippet("jsOnWindowLoad") }); @if(GetString("Item.Area.Analytics").IsNotNullOrEmpty()) { <text> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', '@GetString("Item.Area.Analytics")', 'auto'); ga('send', 'pageview'); </text> } </script> @RenderSnippet("outScripts") </head> } } @using System.Web.Script.Serialization; @using System.Linq; @using Dna.Validation @using Dynamicweb.Core @{ var item = Pageview.Area.Item; bool bol_userLogged = Dynamicweb.Security.UserManagement.User.IsExtranetUserLoggedIn(); string str_loginPage = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl("/Default.aspx?ID=" + item["MyAccountRedirectPage"].ToString()); string str_filterUrl = System.Web.HttpContext.Current.Request.Path + "?ID=" + System.Web.HttpContext.Current.Request.QueryString["id"]; string str_productID = GetString("Ecom:Product.ID"); string str_productLanguageId = GetString("Ecom:Product.LanguageID"); string str_productType = GetString("Ecom:Product.CategoryField.LorenzAx.ProductType.OptionLabel"); string str_productFavoritesPageId = (Pageview.Area.Item["FavoritesProcess"] != null) ? Pageview.Area.Item["FavoritesProcess"].ToString() : System.Web.HttpContext.Current.Request.QueryString["id"].ToString(); string str_productFavoritesUrl = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(Int32.Parse(str_productFavoritesPageId)); string str_productAddToList = string.Format("{0}?favoriteID={1}&amp;languageID={2}&amp;favoriteAction=add", str_productFavoritesUrl, str_productID, str_productLanguageId); string str_productRemoveFromList = string.Format("{0}?favoriteID={1}&amp;languageID={2}&amp;favoriteAction=remove", str_productFavoritesUrl, str_productID, str_productLanguageId); bool bol_productIsFavorite = GetBoolean("Ecom:Product.IsProductInFavoriteList"); string str_favoriteUrl = bol_productIsFavorite ? str_productRemoveFromList : str_productAddToList; string str_productName = GetString("Ecom:Product.Name"); string str_productNumber = GetString("Ecom:Product.Number"); string str_articleNum = str_productNumber.Replace("/", "_").Replace("-", "_"); string str_articleNumForImg = str_productNumber.Replace("/", "_"); string str_patternImage = "/Files/Files/Lorenz/Products/Product_Images/" + str_articleNumForImg + ".jpg"; string str_image = GetString("Ecom:Product.ImageSmall.Default.Clean").IsNotNullOrEmpty() ? GetString("Ecom:Product.ImageSmall.Default.Clean") : str_patternImage; string str_shortDescription = GetString("Ecom:Product.ShortDescription"); string str_largeDescription = GetString("Ecom:Product.LongDescription"); string str_stockText = GetString("Ecom:Product:Stock.Text"); string str_productIsFavorite = GetBoolean("Ecom:Product.IsProductInFavoriteList") ? "fa-heart" : "fa-heart-o"; string str_mp3 = ""; string str_title = ""; string str_folderPath = Path.GetDirectoryName(HttpContext.Current.Server.MapPath("/Files/Files/Lorenz/Products/Sample_Audio/" + str_articleNum + ".mp3")); string str_titleKey = "title"; string str_mp3Key = "mp3"; string str_samplePagesFolderPath = Path.GetDirectoryName(HttpContext.Current.Server.MapPath("/Files/Files/Lorenz/Products/Sample_Pages/" + str_articleNum + ".pdf")); string str_samplePagesFileLocalPath = str_samplePagesFolderPath + @"\" + str_articleNum + ".pdf"; string str_samplePagesFilePath = "/Files/Files/Lorenz/Products/Sample_Pages/" + str_articleNum + ".pdf"; string str_downloadPagesFolderPath = Path.GetDirectoryName(HttpContext.Current.Server.MapPath("/Files/Files/Lorenz/Products/Sample_FreeDownloads/" + str_articleNum + ".pdf")); string str_downloadPagesFileLocalPath = str_downloadPagesFolderPath + @"\" + str_articleNum + ".pdf"; string str_downloadPagesFilePath = "/Files/Files/Lorenz/Products/Sample_FreeDownloads/" + str_articleNum + ".pdf"; string str_pattern = str_articleNum + "*"; string str_variant = GetLoop("VariantGroups").Any() ? "hasVariant" : ""; string str_composers = GetString("Ecom:Product:Field.ComposerDescription.Value.Clean"); string str_voicing = GetString("Ecom:Product:Field.VoicingDescription.Value.Clean"); string str_voicingDetails = GetString("Ecom:Product:Field.VoicingDescription.Value.Clean"); string str_lazyURL = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(item["LazyLoadProductPage"].ToString() + "&ProductID=" + HttpUtility.UrlEncode(str_productID)); bool bol_loadJson = HttpContext.Current.Request["loadList"] != null && HttpContext.Current.Request["loadList"] == "true"; List<Dictionary<string, string>> lst_sounds = new List<Dictionary<string, string>>(); string str_minQuantity = GetString("Ecom:Product:Field.MinOrderQuantity.Value"); int int_initQuantity = str_minQuantity.IsNotNullOrEmpty() ? int.Parse(str_minQuantity) : 1; int_initQuantity = int_initQuantity <= 1 ? 1 : int_initQuantity; string str_dataError = string.Format(@Translate(" minimumCopiesRequired", "A minimum of {0} copies are required."), str_minQuantity); if (Directory.Exists(str_folderPath)) { string str_temp = @"\"; foreach (string file in Directory.GetFiles(str_folderPath, str_pattern)) { string str_mp3File = file.Substring((file.LastIndexOf(@str_temp) + 1), (file.Length - file.LastIndexOf(@str_temp) - 1)); if (str_mp3File.Substring(0, str_mp3File.LastIndexOf("_")) != str_articleNum) { continue; } Dictionary<string, string> dct_sound = new Dictionary<string, string>(); str_mp3 = "/Files/Files/Lorenz/Products/Sample_Audio/" + file.Substring((file.LastIndexOf(@str_temp) + 1), (file.Length - file.LastIndexOf(@str_temp) - 1)); string str_metafield = "title"; var metadata = Dynamicweb.Content.Files.Metadata.EditorFactory.GetMetadataForFile(str_mp3); str_title = metadata != null ? StripHtml(metadata.GetValue(str_metafield).ToString().Replace(" ", "").Replace("\"", "''")) : str_productName; string sort = file.Substring((file.LastIndexOf("_") + 1), 2).ToString().Replace(".", ""); dct_sound.Add(str_titleKey, str_title); dct_sound.Add(str_mp3Key, str_mp3); dct_sound.Add("Sort", sort); lst_sounds.Add(dct_sound); } } lst_sounds = lst_sounds.OrderBy(d => int.Parse(d["Sort"])).ToList(); } @if (System.Web.HttpContext.Current.Request.Params["LayoutTemplate"] == null) { <div id="detailLargeContainer" data-lazyurl="@str_lazyURL" itemscope itemtype="http://schema.org/Product" class="col-sm-10 noPaddingLeft noPaddingRight detailTopMargin"> <div id="productLeftCol" class="col-sm-4 hidden-xs noPaddingLeft"> <figure data-img='@str_image'> <img itemprop="image" src="@Dna.Frontend.Images.GetImage(str_image, 380, 0)" alt="@str_productName" title="@str_productName" class="img-responsive" /> </figure> @if (File.Exists(str_samplePagesFileLocalPath)) { @* <a class="detailButton" href="/Admin/Public/DWSDownload.aspx?File=@str_samplePagesFilePath"><i class="fa fa-file-text-o"></i>@Translate("viewSamplePages", "View sample pages")</a> *@ @* The href has '' because the client want the pdf open in a new window. The DW not replace da href for download the file *@ <a class="detailButton" target="_blank" href='@str_samplePagesFilePath'><i class="fa fa-file-text-o"></i>@Translate("viewSamplePages", "View sample pages")</a> } @if (Directory.Exists(str_downloadPagesFolderPath)) { string str_temp = @"\"; bool hasDownload = false; <div id="partsDownload" class="hidden" data-title='@Translate("partsDownloads")'> <div class="partsDownloadContainer"> <div id="multipleDownload"> @foreach (string file in Directory.GetFiles(str_downloadPagesFolderPath, str_pattern)) { string str_file = file.Substring((file.LastIndexOf(@str_temp) + 1), (file.Length - file.LastIndexOf(@str_temp) - 1)); if (str_file.Substring(0, str_file.LastIndexOf("_")) != str_articleNum) { continue; } hasDownload = true; var str_filePath = "/Files/Files/Lorenz/Products/Sample_FreeDownloads/" + str_file; var metadata = Dynamicweb.Content.Files.Metadata.EditorFactory.GetMetadataForFile(str_filePath); var str_docTitle = string.Empty; str_docTitle = metadata != null ? metadata.GetValue("title").ToString() : str_file; <fieldset> <label data-href="/Admin/Public/DWSDownload.aspx?File=@str_filePath" data-file="@str_filePath" class="checkBoxContainer"> <input name='downloadFile' checked type="checkbox"/> <span>@str_docTitle</span> </label> </fieldset> } </div> <a class="greenBtn downloadAllFiles" href="javascript:void(0);">@Translate("download", "Download")</a> </div> </div> if (hasDownload) { <a class="detailButton partsDownload" href='javascript:void(0);'><i class="fa fa-download"></i>@Translate("partsDownloads", "Parts Download(s)")</a> } } @if (bol_userLogged) { <a data-addtolist='@Translate("addToWishList", "Add to wish list")' data-removefromlist='@Translate("removeFromWishList", "Remove from wish list")' class="detailButton" data-remove="@str_productRemoveFromList" data-add="@str_productAddToList" href="@str_favoriteUrl"><i class="fa @str_productIsFavorite"></i>@Translate(bol_productIsFavorite ? "Remove from wish list" : "Add to wish list")</a> } else { <a class="detailButton noUser" data-href="@str_loginPage" href="javascript:void(0)"><i class="fa @str_productIsFavorite"></i>@Translate(bol_productIsFavorite ? "Remove from wish list" : "Add to wish list")</a> } <div class="detailSocialMedia"> <span>@Translate("share", "Share")</span> @RenderSocialMedia(false,false) </div> </div> <div class="col-sm-8 col-xs-12" id="productCenterCol"> <header> <div class="controls"> <div><span><i class="fa fa-play"></i></span></div> </div> <div> <h2 itemprop="name">@str_productName</h2> @if (str_shortDescription.IsNotNullOrEmpty()) { <span> @str_shortDescription <br /> </span> } </div> </header> @if (str_composers.IsNotNullOrEmpty() || str_voicing.IsNotNullOrEmpty()) { <div class="productComposerAndVoicing"> @if (str_composers.IsNotNullOrEmpty()) { <span class="boldFont">@str_composers.Replace(";", ",")</span> <br /> } @if (str_voicingDetails.IsNotNullOrEmpty()) { @str_voicingDetails <br /> } </div> } @if (str_largeDescription.IsNotNullOrEmpty()) { <div class="productDescription" itemprop="description"> @str_largeDescription </div> } @* Player *@ <div id="jpContainer" class="jp-video col-xs-12 noPadding" role="application" aria-label="media player"> @if (bol_loadJson) { <div id="jsonMusicList" class="hidden"> @toJson(lst_sounds) </div> } <div class="jp-type-playlist"> <div id="jquery_jplayer_1" class="jp-jplayer"></div> <div class="jp-gui"> <div class="jp-video-play"> <button class="jp-video-play-icon" role="button" tabindex="0">@Translate("play", "play")</button> </div> <div class="jp-interface"> <div class="jp-controls-holder"> <div class="jp-controls"> <button class="jp-previous" role="button" tabindex="0">@Translate("previous", "previous")</button> <button class="jp-play" role="button" tabindex="0">@Translate("play", "play")</button> <button class="jp-next" role="button" tabindex="0">@Translate("next", "next")</button> </div> <div class="jp-progress"> <div class="jp-seek-bar"> <div class="jp-play-bar"></div> </div> </div> <div class="timerContainer"> <div class="jp-current-time" role="timer" aria-label="time">&nbsp;</div> <div class="jp-duration" role="timer" aria-label="duration">&nbsp;</div> </div> <div class="jp-volume-controls"> <button class="jp-mute" role="button" tabindex="0">@Translate("mute", "mute")</button> <button class="jp-volume-max" role="button" tabindex="0">@Translate("maxVolume", "max volume")</button> <div class="jp-volume-bar"> <div class="jp-volume-bar-value"><span></span></div> </div> </div> </div> <div class="jp-details"> <div class="jp-title" aria-label="title">&nbsp;</div> </div> </div> </div> <div class="jp-playlist"> <ul> <!-- The method Playlist.displayPlaylist() uses this unordered list --> <li>&nbsp;</li> </ul> </div> <div class="jp-no-solution"> <span>@Translate("updateRequired", "Update Required")</span> @Translate("updateBrowserToPlayMedia", "To play the media you will need to either update your browser to a recent version or update your") <a href="http://get.adobe.com/flashplayer/" target="_blank">@Translate("flashPlugin", "Flash plugin")</a>. </div> </div> </div> @* Vídeo Embed *@ @{ string video = GetString("Ecom:Product:Field.Video.Value.Clean"), videoId = System.Text.RegularExpressions.Regex.Match(video, @"(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&amp;]v=)|youtu\.be\/)([^""&amp;?\/ ]{11})").Groups[1].Value, videoEmbed = ""; if (video.IsNotNullOrEmpty() && videoId.IsNullOrEmpty()) { videoId = System.Text.RegularExpressions.Regex.Match(video, @"youtu(?:\.be|be\.com)/(?:.*v(?:/|=)|(?:.*/)?)([a-zA-Z0-9-_]+)").Groups[1].Value; videoId = videoId.IsNullOrEmpty() ? video : videoId; } videoEmbed = (videoId.IsNotNullOrEmpty()) ? string.Format("https://www.youtube.com/embed/{0}", videoId) : ""; if (videoEmbed.IsNotNullOrEmpty()) { <div class="video-container col-xs-12 noPadding"> <div class="video-box"> <iframe width="100%" class="video-iframe" data-videoid="@videoId" src="@videoEmbed?showinfo=0&controls=1&autohide=1&rel=0&modestbranding=1&enablejsapi=1" frameborder="0" allowfullscreen="allowfullscreen"></iframe> </div> </div> } } @if (!GetBoolean("Ecom:Product:Field.OutofPrint.Value.Clean") && str_stockText != "Available for Preorder") { <div class="priceContainer col-xs-12"> <form name="addToCart" action="/homepage" method="post"> <input type="hidden" name="cartcmd" value='add' /> <input type="hidden" name="redirect" value='false' /> <input type="hidden" name="productID" value='@GetString("Ecom:Product.ID")' /> <span class="@str_variant" itemprop="offers" itemscope itemtype="http://schema.org/Offer"> <meta itemprop="price" content="@GetString("Ecom:Product.Price.Price")"> <meta itemprop="priceCurrency" content="@GetString("Ecom:Product.CurrencyCode")"> @GetString("Ecom:Product.Price") </span> @foreach (LoopItem c in GetLoop("VariantGroups")) { string str_sizeSelect = "<fieldset class='Select mandatory' id='Subscriptions'><select name='variantID'>"; string str_selected = ""; str_sizeSelect += "<option value=''>" + Translate("subscription", "Subscriptions") + "</option>"; foreach (LoopItem variantCombination in c.GetLoop("VariantAvailableOptions")) { str_selected = variantCombination.GetString("Ecom:VariantOption.Selected") != "False" ? "selected" : ""; str_sizeSelect += "<option data-default='" + str_selected + "' " + str_selected + " id='" + variantCombination.GetString("Ecom:VariantOption.ID") + "' value='" + variantCombination.GetString("Ecom:VariantOption.ID") + "'>" + variantCombination.GetString("Ecom:VariantOption.Name") + "</option>"; } str_sizeSelect += "</select></fieldset>"; @str_sizeSelect } <fieldset> <label for="quantity">@Translate("quantity", "Quantity"):</label> <input type="number" id="quantity" name="Quantity" class="productQuantity" value='@int_initQuantity' step="1" min="@int_initQuantity" data-prev-value="@int_initQuantity" data-error="@str_dataError" data-error-title="@Translate("minimumOrderRequiredTitle","Minimum Order Required")"/> </fieldset> <input class="hide" type="submit" value="@Translate("addToCart", "Add to cart")"> <div class="searchButton"> <span class="fa-shopping-cart"></span> <a class="addToCart" href="@GetString("Ecom:Product:SavedForLater.AddToBasketLink")">@Translate("addToCart", "Add to cart")</a> </div> </form> </div> } @* Companion Products *@ </div> @* Tabs *@ </div> } @SnippetStart("jsOnLoad") onLoadProductDetail('@toJson(lst_sounds)', '@GetString("Ecom:Product.CategoryField.LorenzAx.Contents.Value.Clean").Replace("'", "´")', {obj_product:@str_productJSON}); productMinimumQuantity(); @SnippetEnd("jsOnLoad") <!-- TODO can only be solved after the URL problems Must open in the final page instead of the search page. --> @SnippetStart("OGMeta") <meta property="og:title" content='@str_productName' /> <meta property="og:image" content='@Pageview.GlobalTags.GetTagByName("Global:Request.Scheme").Value.ToString()://@Pageview.GlobalTags.GetTagByName("Global:Request.Host").Value.ToString()@str_image' /> <meta property="og:site_name" content='@GetGlobalValue("Global:Area.Name")' /> <meta property="og:url" content='@Pageview.GlobalTags.GetTagByName("Global:Request.Scheme").Value.ToString()://@Pageview.GlobalTags.GetTagByName("Global:Request.Host").Value.ToString()@Pageview.GlobalTags.GetTagByName("Global:Pageview.Url").Value.ToString()' /> <meta property="og:description" content='@StripHtml(str_largeDescription)' /> <meta property="og:type" content="article" /> <meta property="og:locale" content='@Pageview.GlobalTags.GetTagByName("Global:Area.LongLang").Value.ToString().Replace("-", "_")' /> @SnippetEnd("OGMeta")
Demo