Error executing template "Designs/Swift/_parsed/GBG_VariantMatrix.parsed.cshtml"
System.ArgumentNullException: Value cannot be null.
Parameter name: input
   at System.Text.RegularExpressions.Regex.Replace(String input, String replacement)
   at System.Text.RegularExpressions.Regex.Replace(String input, String pattern, String replacement)
   at CompiledRazorTemplates.Dynamic.RazorEngine_0a2f975cf37e43a9b0cf193f85de6ec3.Execute() in D:\dynamicweb.net\Solutions\Degree\granberg.cloud.dynamicweb-cms.com\Files\Templates\Designs\Swift\_parsed\GBG_VariantMatrix.parsed.cshtml:line 133
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader)
   at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
   at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()

1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 2 @using System.Text.RegularExpressions 3 @using Dynamicweb.Ecommerce.ProductCatalog 4 @using Dynamicweb.Ecommerce.CustomerExperienceCenter.Favorites 5 @using Dynamicweb.Ecommerce.Products.FieldDisplayGroups 6 @using Dynamicweb.Frontend 7 @using System.Web 8 @using Dynamicweb.Ecommerce.Products 9 @using Dynamicweb.Ecommerce.Stocks 10 11 @functions{ 12 public class MultiplierButton 13 { 14 public int multiplier { get; set; } 15 public string label { get; set; } 16 public int sort { get; set; } 17 } 18 19 public CartOrderlineViewModel GetProductOrderline(string productId, string variantId) 20 { 21 CartOrderlineViewModel response = new CartOrderlineViewModel(); 22 var orderLines = Model.Cart?.CartOrderlines; 23 if(orderLines != null) 24 { 25 CartOrderlineViewModel productOrderLine = orderLines.Where(x => x.ProductID == productId && x.ProductVariantID == variantId).FirstOrDefault(); 26 response = productOrderLine != null ? productOrderLine : response; 27 } 28 return response; 29 } 30 31 } 32 33 @{ 34 ProductViewModel product = new ProductViewModel(); 35 bool hasExpectedDelivery = false; 36 string expectedDeliveryDate = ""; 37 bool IsNeverOutOfStock = false; 38 string[] variantId = new string[] {}; 39 string disableAddToCart = ""; 40 41 42 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 43 { 44 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 45 } 46 47 ProductViewModelSettings productSetting = new ProductViewModelSettings 48 { 49 LanguageId = Dynamicweb.Ecommerce.Common.Context.LanguageID, 50 CurrencyCode = Dynamicweb.Ecommerce.Common.Context.Currency.Code, 51 CountryCode = Dynamicweb.Ecommerce.Common.Context.Country.Code2, 52 ShopId = Pageview.Area.EcomShopId 53 }; 54 55 if (Dynamicweb.Context.Current.Request.QueryString.Get("ProductID") != null) 56 { 57 string productId = Dynamicweb.Context.Current.Request.QueryString.Get("ProductID"); 58 59 product = ViewModelFactory.CreateView(productSetting, productId); 60 } else { 61 product = ViewModelFactory.CreateView(productSetting, "Product122"); 62 } 63 64 int multiplier = 1; 65 if (Dynamicweb.Context.Current.Request.QueryString.Get("multiplier") != null) 66 { 67 multiplier = Dynamicweb.Core.Converter.ToInt32(Dynamicweb.Context.Current.Request.QueryString.Get("multiplier")); 68 } 69 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 70 bool anonymousUser = Pageview.User == null; 71 bool hideAddToCart = anonymousUsersLimitations.Contains("cart") && anonymousUser; 72 //hideAddToCart = product.VariantInfo.VariantInfo != null && Model.Item.GetBoolean("HideVariantSelector") ? true : hideAddToCart; 73 bool hidePrice = anonymousUsersLimitations.Contains("price") && anonymousUser; 74 bool hideFavoritesSelector = false;//!string.IsNullOrEmpty(Model.Item.GetString("HideFavoritesSelector")) ? Model.Item.GetBoolean("HideFavoritesSelector") : false; 75 76 if(product.Id != "") 77 { 78 IsNeverOutOfStock = product.NeverOutOfstock; 79 variantId = product.VariantId?.Split('.'); 80 disableAddToCart = (product.StockLevel <= 0) ? "disabled" : ""; 81 if (IsNeverOutOfStock) 82 { 83 disableAddToCart = ""; 84 } 85 86 // Does product has a expected delivery data 87 hasExpectedDelivery = product.ExpectedDelivery != null && product.ExpectedDelivery > DateTime.Now; 88 expectedDeliveryDate = product.ExpectedDelivery?.ToShortDateString() ?? ""; 89 90 } 91 92 93 string url = "/Default.aspx?ID=" + (GetPageIdByNavigationTag("CartService")); 94 if (!url.Contains("LayoutTemplate")) 95 { 96 url += url.Contains("?") ? "&LayoutTemplate=Swift_MiniCart.cshtml" : "?LayoutTemplate=Swift_MiniCart.cshtml"; 97 } 98 99 100 101 string theme = "";//!string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 102 103 string titleFontSize = "display-6";//Model.Item.GetRawValueString("TitleFontSize", "display-6"); 104 105 string contentPadding = "";//Model.Item.GetRawValueString("ContentPadding", ""); 106 contentPadding = contentPadding == "small" ? "p-2 p-md-3" : contentPadding; 107 contentPadding = contentPadding == "large" ? "p-4 p-md-5" : contentPadding; 108 109 string quantityPricesLayout = "list";//Model.Item.GetRawValueString("QuantityPricesLayout", "list"); 110 string minQty = "min=\"0\""; 111 // string minQty = product.PurchaseMinimumQuantity != 1 ? "min=\"" + product.PurchaseMinimumQuantity.ToString() + "\"" : "min=\"1\""; 112 string stepQty = product.PurchaseQuantityStep > 1 ? product.PurchaseQuantityStep.ToString() : "1"; 113 string valueQty = product.PurchaseMinimumQuantity > product.PurchaseQuantityStep ? product.PurchaseMinimumQuantity.ToString() : stepQty; 114 string qtyValidCheck = stepQty != "1" ? "onkeyup=\"swift.Cart.QuantityValidate(event)\"" : ""; 115 116 string showPricesWithVat = Pageview.Area.EcomPricesWithVat.ToLower(); 117 bool neverShowVat = string.IsNullOrEmpty(showPricesWithVat); 118 119 string priceMin = ""; 120 string priceMax = ""; 121 122 string iconPath = "/Files/icons/"; 123 124 var favoriteParameters = new Dictionary<string, object>(); 125 126 List<UnitOfMeasure> productUnits = new List<UnitOfMeasure>(); 127 128 string tabParameter = Dynamicweb.Context.Current.Request.QueryString.Get("tab"); 129 string outerCaseChecked = tabParameter == "outer-case" || tabParameter == "" ? "checked" : ""; 130 string bundleChecked = tabParameter == "bundle" ? "checked" : ""; 131 string pairsChecked = tabParameter == "pairs" ? "checked" : ""; 132 // string step = tabParameter == "outer-case" || tabParameter == "" ? "72" : tabParameter == "bundle" ? "12" : "1"; 133 string step = Regex.Replace(tabParameter, @"[^\d]", ""); 134 } 135 <div class="h-100 @(contentPadding) @(theme)"> 136 <div class="d-flex flex-column gap-4 js-product"> 137 @if (!anonymousUser) 138 { 139 if(product.Id != "") 140 { 141 142 // Dynamicweb.Ecommerce.Services.UnitOfMeasureService unitService = new Dynamicweb.Ecommerce.Services.UnitOfMeasureService(); 143 Dynamicweb.Ecommerce.Stocks.UnitOfMeasureService unitService = new Dynamicweb.Ecommerce.Stocks.UnitOfMeasureService(); 144 productUnits = unitService.GetUnitOfMeasures(product.Id).ToList(); 145 @* @productUnits.Count *@ 146 <div class="d-flex gap-0" role="group" aria-label="Basic radio toggle button order-units" data-ref="table-header"> 147 @foreach (var unit in productUnits) 148 { 149 150 @* <p>@unit.QuantityPerUnit</p> *@ 151 var quantity = unit.QuantityPerUnit; 152 var id = unit.UnitId; 153 if (quantity == 1) 154 { 155 if (tabParameter=="" || tabParameter == "quantity-input-1") 156 { 157 <input type="radio" class="btn-check quantity-input" name="options" id="quantity-input-@quantity" data-step-input="@quantity" autocomplete="off" checked> 158 <label class="btn btn-primary flex-fill rounded-0 shadow-none multiplier-btn py-3" data-step="@quantity" checked>@quantity @Translate("pair bundle").ToUpper()</label> 159 } 160 else 161 { 162 <input type="radio" class="btn-check quantity-input" name="options" id="quantity-input-@quantity" data-step-input="@quantity" autocomplete="off"> 163 <label class="btn btn-primary flex-fill rounded-0 shadow-none multiplier-btn py-3" data-step="@quantity">@quantity @Translate("pair bundle").ToUpper()</label> 164 } 165 166 } 167 else if(id != "Unit_PALL") 168 { 169 if (tabParameter == "quantity-input-" + quantity) 170 { 171 <input type="radio" class="btn-check quantity-input" name="options" id="quantity-input-@quantity" checked data-step-input="@quantity" autocomplete="off"> 172 <label class="btn btn-primary flex-fill rounded-0 shadow-none multiplier-btn py-3" data-step="@quantity" checked>@quantity @Translate("pairs bundle").ToUpper()</label> 173 } 174 else 175 { 176 <input type="radio" class="btn-check quantity-input" name="options" id="quantity-input-@quantity" data-step-input="@quantity" autocomplete="off"> 177 <label class="btn btn-primary flex-fill rounded-0 shadow-none multiplier-btn py-3" data-step="@quantity">@quantity @Translate("pairs bundle").ToUpper()</label> 178 } 179 } 180 } 181 </div> 182 183 184 // var units = GetUnitOfMeasures(product.Id); 185 186 187 int groupNumber = 1; 188 @* <div class=" grid gap-0" role="group" aria-label="Basic radio toggle button order-units" data-ref="table-header"> *@ 189 190 @* <input type="radio" class="btn-check" name="options" id="outer-case" autocomplete="off" @outerCaseChecked> *@ 191 @* <label class="btn btn-primary rounded-0 shadow-none multiplier-btn py-3 g-col-4" data-step="72" for="outer-case">@Translate("Outer Case").ToUpper()</label> *@ 192 @* *@ 193 @* <input type="radio" class="btn-check" name="options" id="bundle" autocomplete="off" @bundleChecked> *@ 194 @* <label class="btn btn-primary rounded-0 shadow-none multiplier-btn py-3 g-col-4" data-step="12" for="bundle">@Translate("Bundle").ToUpper()</label> *@ 195 @* *@ 196 @* <input type="radio" class="btn-check" name="options" id="pairs" autocomplete="off" @pairsChecked> *@ 197 @* <label class="btn btn-primary rounded-0 shadow-none multiplier-btn py-3 g-col-4" data-step="1" for="pairs">@Translate("Pairs").ToUpper()</label> *@ 198 199 // </div> 200 201 <input type="hidden" name="variantid"/> 202 203 foreach (var variantGroup in product.VariantGroups()) 204 { 205 VariantGroupViewModel group = variantGroup; 206 int i = 0; 207 208 <div class="js-variant-group" data-group-id="@groupNumber"> 209 @if (group.Name == "Size") 210 { 211 212 213 <table class="table text-center"> 214 <thead> 215 <tr> 216 @* <th>@Translate("Stock")</th> *@ 217 <th>@Translate("Sizes")</th> 218 <th>@Translate("Quantity (pairs)")</th> 219 </tr> 220 </thead> 221 <tbody> 222 @foreach (var option in group.Options) 223 { 224 string orderLineID = ""; 225 double orderLineQuantity = 0; 226 int quantityMultiplier = Dynamicweb.Core.Converter.ToInt32(multiplier); 227 228 ProductViewModel variant = ViewModelFactory.CreateView(productSetting, product.Id, option.Id); 229 double? variantStock = variant.StockLevel; 230 string variantMinQty = variant.PurchaseMinimumQuantity != 1 ? "min=\"" + variant.PurchaseMinimumQuantity.ToString() + "\"" : "min=\"1\""; 231 string variantStepQty = variant.PurchaseQuantityStep > 1 ? variant.PurchaseQuantityStep.ToString() : "1"; 232 string variantValueQty = variant.PurchaseMinimumQuantity > variant.PurchaseQuantityStep ? variant.PurchaseMinimumQuantity.ToString() : variantStepQty; 233 string variantQtyValidCheck = stepQty != "1" ? "onkeyup=\"swift.Cart.QuantityValidate(event)\"" : ""; 234 string uniqueID = variant.Id + "_" + variant.VariantId; 235 string quantityInputName = "Quantity"; 236 string inputClass = "d-none"; 237 238 <tr> 239 @* <td> *@ 240 @* @variantStock *@ 241 @* </td> *@ 242 <td> 243 <p class="d-inline-block variant-option js-variant-option mb-0 pt-2" data-variant-id="@option.Id"> 244 @option.Name 245 </p> 246 </td> 247 <td class="w-50"> 248 249 @* @if (variantStock > 0) *@ 250 @* { *@ 251 @{var productOrderLine = GetProductOrderline(variant.Id, variant.VariantId);} 252 <form id="@uniqueID" action="@url"> 253 254 @if (variant.IsProductInCart() && productOrderLine.Quantity > 0) 255 { 256 257 inputClass = "d-flex"; 258 orderLineID = productOrderLine.ID; 259 orderLineQuantity = productOrderLine.Quantity; 260 quantityInputName = "QuantityOrderLine" + orderLineID; 261 <input type="hidden" name="cartcmd" value="UpdateorderLines"> 262 <input type="hidden" name="redirect" value="false"> 263 //do some logic to handle increase orderline 264 } 265 else 266 { 267 // do logic to handle add to cart 268 <input type="hidden" name="redirect" value="false"> 269 <input type="hidden" name="ProductId" value="@variant.Id"> 270 <input type="hidden" name="ProductCurrency" value="@Dynamicweb.Ecommerce.Common.Context.Currency.Code"> 271 <input type="hidden" name="VariantId" value="@variant.VariantId"> 272 <input type="hidden" name="cartcmd" value="add"> 273 274 <button type="button" class="btn btn-primary flex-fill js-add-to-cart-button" title="@Translate("Add to cart")">@Translate("Add to cart") 275 </button> 276 } 277 <div class="js-input-group @inputClass flex-wrap justify-content-center"> 278 <button type="button" class="btn btn-link" data-role="step-down"> 279 <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 280 <rect x="0.5" y="0.5" width="23" height="23" rx="2.5" stroke="black"/> 281 <path d="M17 10V14H7V10H17Z" fill="black"/> 282 </svg> 283 </button> 284 285 <label for="QuantityOrderLine@(option.Id)" class="visually-hidden" >@Translate("Quantity"):</label> 286 <input step="@step" type="number" data-ref="quantity-input" id="QuantityOrderLine@(option.Id)" @minQty class="form-control text-center quantity-input" value="@orderLineQuantity" name="@quantityInputName" @qtyValidCheck style="max-width: 4.5rem;" data-bs-container="body" data-bs-toggle="popover" data-bs-trigger="manual" data-bs-placement="top" data-stock="@variantStock" data-error-invalid-multiplier="The current value is invalid! Step is: " data-error-no-stock="Not enough stock!" data-bs-content="asd" data-bs-custom-class="alert-danger"> 287 288 <button type="button" class="btn btn-link" data-role="step-up" data-bs-container="body" data-bs-toggle="popover" data-bs-trigger="manual" data-bs-placement="top" data-bs-content="Not enough stock!" data-bs-custom-class="alert-danger"> 289 <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 290 <rect x="0.5" y="0.5" width="23" height="23" rx="2.5" stroke="black"/> 291 <path d="M9.9774 20V4H14.0226V20H9.9774ZM4 14.0226V9.9774H20V14.0226H4Z" fill="black"/> 292 </svg> 293 </button> 294 </div> 295 296 @* <div class="px-3 mt-3 w-50 bg-danger m-auto rounded-pill d-none" data-role="alert-stock-exceeded"> *@ 297 @* <p class="align-self-center text-center m-0">@Translate("Stock exceeded!")</p> *@ 298 @* </div> *@ 299 @* <button type="submit" onclick="document.querySelector('#@uniqueID').submit()">submit</button> *@ 300 @* <button type="button" onclick="swift.Cart.UpdateCustom(event)" class="btn btn-primary" style="white-space: nowrap" title="@Translate("Add to cart")" id="AddToCartButton@(uniqueID)"> *@ 301 @* </button> *@ 302 </form> 303 304 @* } *@ 305 @* else *@ 306 @* { *@ 307 @* <button type="button" class="btn btn-primary flex-fill js-add-to-cart-button" disabled title="@Translate("Add to cart")">@Translate("Add to cart") *@ 308 @* </button> *@ 309 @* } *@ 310 </td> 311 </tr> 312 313 i++; 314 315 } 316 </tbody> 317 </table> 318 319 320 } 321 </div> 322 323 groupNumber++; 324 } 325 326 if (!IsNeverOutOfStock) 327 { 328 <div class="mt-3 js-stock-state"> 329 330 @* @if (product.StockLevel > 0) *@ 331 @* { *@ 332 @* if (!Model.Item.GetBoolean("HideInventory")) *@ 333 @* { *@ 334 @* <p class="small text-success m-0">@product.StockLevel @Translate("Products available in stock")</p> *@ 335 @* } *@ 336 @* else *@ 337 @* { *@ 338 @* <p class="small text-success m-0">@Translate("Available in stock")</p> *@ 339 @* } *@ 340 @* } *@ 341 @* *@ 342 @* else *@ 343 @* { *@ 344 @* <p class="small text-danger m-0">@Translate("Out of Stock")</p> *@ 345 @* } *@ 346 347 @if (hasExpectedDelivery) 348 { 349 <p> 350 <span>@Translate("Expected back in stock:")</span> 351 <span>@expectedDeliveryDate</span> 352 </p> 353 } 354 355 </div> 356 } 357 } else { 358 <p>@Translate("Invalid product")</p> 359 } 360 361 } 362 else 363 { 364 <p>test</p> 365 @* <button class="btn btn-primary"> *@ 366 <a href="/sign-in" class="btn btn-secondary col-lg-3 col-6 my-3 ms-lg-4 mx-auto log-in-button-pdp" style="text-transform: none"> 367 @Translate("Webshop Login") 368 </a> 369 @* </button> *@ 370 } 371 </div> 372 </div> 373