Error executing template "Designs/Swift-v2/Paragraph/Swift-v2_ProductAddToCart.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at CompiledRazorTemplates.Dynamic.RazorEngine_de82232e8aa5466c8874730f759ae9df.ExecuteAsync() at RazorEngine.Templating.TemplateBase.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineCore.RunTemplate(ICompiledTemplate template, TextWriter writer, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.DynamicWrapperService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass23_0.<Run>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag) 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.ParagraphViewModel> 2 @using Dynamicweb.Ecommerce.ProductCatalog 3 @using Dynamicweb.Rendering 4 @using Dynamicweb.Core.Encoders 5 @using System.Globalization 6 7 @functions { 8 string? DoubleToString(double? value) 9 { 10 if (value.HasValue) 11 { 12 return value.Value.ToString(CultureInfo.InvariantCulture); 13 } 14 return null; 15 } 16 } 17 18 @{ 19 ProductViewModel product = null; 20 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 21 { 22 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 23 } 24 else if (!string.IsNullOrEmpty(Pageview.Page.Item["DummyProduct"]?.ToString()) && Pageview.IsVisualEditorMode) 25 { 26 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 27 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 28 29 if (productList?.Products is object) 30 { 31 product = productList.Products[0]; 32 } 33 } else if (Pageview.IsVisualEditorMode) { 34 product = new ProductViewModel(); 35 product.Id = "1"; 36 product.VariantId = "394041"; 37 product.PurchaseMinimumQuantity = 1; 38 product.PurchaseQuantityStep = 1; 39 product.StockLevel = 10; 40 product.DefaultUnitId = "1"; 41 product.ProductType = Dynamicweb.Ecommerce.Products.ProductType.Stock; 42 product.NeverOutOfstock = false; 43 product.Discontinued = false; 44 product.Price = new PriceViewModel() { 45 Price = 99, 46 PriceFormatted = "99 " + Pageview.Area.EcomCurrencyId, 47 PriceWithoutVat = 99, 48 PriceWithoutVatFormatted = "99 " + Pageview.Area.EcomCurrencyId, 49 PriceWithVat = 99, 50 PriceWithVatFormatted = "99 " + Pageview.Area.EcomCurrencyId 51 }; 52 } 53 54 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 55 bool anonymousUser = Pageview.User == null; 56 57 bool hideAddToCart = anonymousUsersLimitations.Contains("cart") && anonymousUser; 58 hideAddToCart = Pageview.IsVisualEditorMode ? false : hideAddToCart; 59 60 bool isVariant = !string.IsNullOrEmpty(product.VariantId); 61 bool hasVariants = product.VariantInfo?.VariantInfo != null; 62 } 63 64 @if (product is object && !hideAddToCart) 65 { 66 string horizontalAlign = Model.Item.GetRawValueString("HorizontalAlignment", ""); 67 horizontalAlign = horizontalAlign == "center" ? "justify-content-center" : horizontalAlign; 68 horizontalAlign = horizontalAlign == "end" ? "justify-content-end" : horizontalAlign; 69 horizontalAlign = horizontalAlign == "full" ? "" : horizontalAlign; 70 71 bool favoritesSelector = !string.IsNullOrEmpty(Model.Item.GetString("ShowAddToFavorites")) ? Model.Item.GetBoolean("ShowAddToFavorites") : false; 72 bool quantitySelector = !string.IsNullOrEmpty(Model.Item.GetString("ShowQuantitySelector")) ? Model.Item.GetBoolean("ShowQuantitySelector") : false; 73 bool unitsSelector = !string.IsNullOrEmpty(Model.Item.GetString("ShowUnitsSelector")) ? Model.Item.GetBoolean("ShowUnitsSelector") : false; 74 bool hideInventory = !string.IsNullOrEmpty(Model.Item.GetString("HideInventory")) ? Model.Item.GetBoolean("HideInventory") : false; 75 bool hideStockState = !string.IsNullOrEmpty(Model.Item.GetString("HideStockState")) ? Model.Item.GetBoolean("HideStockState") : false; 76 77 string iconPath = "/Files/Images/Icons/"; 78 string url = "/Default.aspx?ID=" + (GetPageIdByNavigationTag("CartService")); 79 if (!url.Contains("LayoutTemplate")) 80 { 81 url += url.Contains("?") ? "&LayoutTemplate=Swift-v2_MiniCart.cshtml" : "?LayoutTemplate=Swift-v2_MiniCart.cshtml"; 82 } 83 84 string whenVariantsExist = Model.Item.GetRawValueString("WhenVariantsExist", "hide"); 85 string flexFill = Model.Item.GetRawValueString("HorizontalAlignment", "") == "full" ? "flex-fill" : ""; 86 string fullWidth = Model.Item.GetRawValueString("HorizontalAlignment", "") == "full" ? "w-100" : ""; 87 string addToCartIcon = Model.Item.GetRawValueString("Icon", iconPath + "cart-shopping.svg"); 88 string addToCartLabel = !addToCartIcon.Contains("_none") ? $"<span class=\"icon-2\">{ReadFile(addToCartIcon)}</span>" : ""; 89 addToCartLabel += !addToCartIcon.Contains("_none") && !Model.Item.GetBoolean("HideButtonText") ? " " : ""; 90 addToCartLabel += !Model.Item.GetBoolean("HideButtonText") ? $"<span class=\"d-none d-md-inline\">{Translate("Add to cart")}</span><span class=\"d-inline d-md-none\">{Translate("Add")}</span>" : ""; 91 bool userHasPendingQuote = Dynamicweb.Ecommerce.Common.Context.Cart != null && Dynamicweb.Ecommerce.Common.Context.Cart.IsQuote; 92 93 94 if (product.VariantInfo?.VariantInfo == null || whenVariantsExist == "disable") 95 { 96 string unitId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.Form.Get("UnitId")) ? Dynamicweb.Context.Current.Request.Form.Get("UnitId") : product.DefaultUnitId; 97 if (string.IsNullOrEmpty(unitId) && product?.UnitOptions != null) 98 { 99 if (product.UnitOptions?.FirstOrDefault<UnitOptionViewModel>() != null) 100 { 101 unitId = product.UnitOptions.FirstOrDefault<UnitOptionViewModel>().Id; 102 } 103 } 104 105 double? stepQty = product.PurchaseQuantityStep > 0 ? product.PurchaseQuantityStep : 1; 106 double? minQty = product.PurchaseMinimumQuantity > 0 ? product.PurchaseMinimumQuantity : 1; 107 double? valueQty = minQty > stepQty ? minQty : stepQty; 108 string? disableAddToCart = null; 109 double? maxQty = null; 110 111 if (Dynamicweb.Context.Current.Items.Contains("ProductQuantity")) 112 { 113 valueQty = Convert.ToDouble(Dynamicweb.Context.Current.Items["ProductQuantity"].ToString()); 114 } 115 116 if (product.ProductType == Dynamicweb.Ecommerce.Products.ProductType.Stock && !product.NeverOutOfstock) 117 { 118 disableAddToCart = product.StockLevel <= 0 ? "disabled" : disableAddToCart; 119 maxQty = product.StockLevel; 120 } 121 122 disableAddToCart = whenVariantsExist == "disable" && product.VariantInfo?.VariantInfo != null && string.IsNullOrEmpty(product.VariantId) ? "disabled" : disableAddToCart; 123 disableAddToCart = product.Discontinued ? "disabled" : disableAddToCart; 124 125 126 127 if (unitsSelector && product.UnitOptions?.Count > 0) 128 { 129 <form method="post" action="/Default.aspx?ID=@(Pageview.Page.ID)&ProductId=@product.Id" id="UnitSelectorForm_@(product.Id)_@(product.VariantId?.Replace(".", "_"))_@Model.ID"> 130 <input type="hidden" name="redirect" value="false"> 131 <input type="hidden" name="VariantID" value="@product.VariantId"> 132 <input type="hidden" name="UnitID" class="js-unit-id" value="@unitId"> 133 </form> 134 } 135 136 @* Price request - custom code *@ 137 string isPriceRequestfieldValue = product != null && product.ProductFields != null 138 && product.ProductFields.ContainsKey("Prisfrfrgan_och_kontakt") 139 && product.ProductFields["Prisfrfrgan_och_kontakt"]?.Value != null 140 ? product.ProductFields["Prisfrfrgan_och_kontakt"].Value.ToString() 141 : ""; 142 bool isPriceRequest = isPriceRequestfieldValue.Equals("True", StringComparison.OrdinalIgnoreCase); 143 if (isPriceRequest) 144 { 145 string priceRequestText = Pageview.AreaSettings.GetRawValueString("PriceRequest", ""); 146 147 <div>@priceRequestText</div> 148 149 <div> 150 <button type="button" class="btn btn-secondary" data-dw-button="secondary" data-bs-toggle="modal" data-bs-target="#quoteRequest">@Translate("Show price request form")</button> 151 152 <div class="modal fade" tabindex="-1" role="dialog" id="quoteRequest"> 153 <div class="modal-dialog" role="document"> 154 <div class="modal-content"> 155 <div class="modal-header"> 156 <h5 class="modal-title" id="exampleModalLiveLabel">@Translate("Price request")</h5> 157 <button type="button" class="close" data-bs-dismiss="modal" aria-label="Close" style="background: transparent; border: 0; padding: 0;"> 158 <span class="icon-4">@ReadFile(iconPath + "x.svg")</span> 159 </button> 160 </div> 161 <div class="modal-body"> 162 @{ 163 string moduleOutput = Model.GetModuleOutput(); 164 165 if (!string.IsNullOrWhiteSpace(moduleOutput)) { 166 <div>@moduleOutput</div> 167 } 168 } 169 </div> 170 <div class="modal-footer"> 171 <button type="button" class="btn btn-secondary" data-dw-button="secondary" data-bs-dismiss="modal">@Translate("Close")</button> 172 </div> 173 </div> 174 </div> 175 </div> 176 </div> 177 178 return; 179 } 180 181 @* Show text field - custom code *@ 182 bool hasSkyltTextSkaAnges = false; 183 string skylttext_hjlptext = string.Empty; 184 string skylttext_antal_tecken_begrnsning = string.Empty; 185 186 if (product.ProductCategories != null) 187 { 188 foreach (var category in product.ProductCategories) 189 { 190 if (category.Value?.Fields != null) 191 { 192 foreach (var field in category.Value.Fields) 193 { 194 if (field.Value.SystemName.ToString() == "Skylttext_ska_anges" && field.Value.ToString() == "True") { 195 hasSkyltTextSkaAnges = true; 196 } 197 if (field.Value.SystemName.ToString() == "Skylttext_hjlptext") { 198 skylttext_hjlptext = field.Value.ToString(); 199 } 200 if (field.Value.SystemName.ToString() == "Skylttext_antal_tecken_begrnsning") { 201 skylttext_antal_tecken_begrnsning = field.Value.ToString(); 202 } 203 } 204 } 205 } 206 } 207 <div class="d-flex @fullWidth js-input-group item_@Model.Item.SystemName.ToLower()"> 208 <div class="d-flex @fullWidth @horizontalAlign flex-wrap flex-lg-nowrap gap-2"> 209 <form method="post" action="@url" class="@fullWidth" style="z-index: 1"> 210 <input type="hidden" name="redirect" value="false"> 211 <input type="hidden" name="ProductId" value="@product.Id"> 212 <input type="hidden" name="ProductName" value="@HtmlEncoder.HtmlEncode(product.Name)"> 213 <input type="hidden" name="ProductVariantName" value="@product.VariantName"> 214 <input type="hidden" name="ProductCurrency" value="@Dynamicweb.Ecommerce.Common.Context.Currency.Code"> 215 <input type="hidden" name="ProductPrice" value="@product.Price.ToStringInvariant()"> 216 <input type="hidden" name="ProductDiscount" value="@product.Discount.ToStringInvariant()"> 217 <input type="hidden" name="ProductReferer" value="component_ProductAddToCart"> 218 <input type="hidden" name="cartcmd" value="add"> 219 <input type="submit" class="d-none" onclick="event.preventDefault(); swift.Cart.Update(event)"> @* Fix for enterKey should not redirect to minicart page *@ 220 221 @if (hasSkyltTextSkaAnges) { 222 <div class="mb-4 mt-2"> 223 <h3 class="h5 mb-1">@Translate("Ange skylttext")</h3> 224 <div>@skylttext_hjlptext</div> 225 <div class="mt-2 form-floating"> 226 <input id="EcomOrderLineFieldInput_SignCustomText" class="form-control" name="EcomOrderLineFieldInput_SignCustomText" type="text" size="20" maxlength="@skylttext_antal_tecken_begrnsning"> 227 <label for="EcomOrderLineFieldInput_SignCustomText">@Translate("Skylttext") (@Translate("max") @skylttext_antal_tecken_begrnsning @Translate("tecken"))</label> 228 </div> 229 <div class="alert alert-danger p-1 fs-7 d-none" id="EcomOrderLineFieldInput_SignCustomTextError" role="alert">@Translate("Ange skylttext error")</div> 230 </div> 231 } 232 233 @if (!string.IsNullOrEmpty(product.VariantId)) 234 { 235 <input type="hidden" name="VariantId" value="@product.VariantId"> 236 } 237 238 <template class="js-step-quantity-warning"> 239 <div class="modal-header"> 240 <h1 class="modal-title fs-5">@Translate("The quantity is not valid")</h1> 241 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 242 </div> 243 <div class="modal-body"> 244 @Translate("Please select a quantity that is dividable by") @stepQty 245 </div> 246 </template> 247 248 <template class="js-min-quantity-warning"> 249 <div class="modal-header"> 250 <h1 class="modal-title fs-5">@Translate("The product could not be added to the cart")</h1> 251 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 252 </div> 253 <div class="modal-body"> 254 @Translate("The quantity is not valid. You must buy at least") @product.PurchaseMinimumQuantity 255 </div> 256 </template> 257 258 <template class="js-value-missing-warning"> 259 <div class="modal-header"> 260 <h1 class="modal-title fs-5">@Translate("No amount specified")</h1> 261 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 262 </div> 263 <div class="modal-body"> 264 @Translate("Specify an amount to add to the cart") 265 </div> 266 </template> 267 268 @if (userHasPendingQuote) 269 { 270 <input type="hidden" name="PendingQuote" value="true"> 271 272 <template class="js-pending-quote-notice"> 273 <div class="modal-header"> 274 <h1 class="modal-title fs-5">@Translate("Pending Quote")</h1> 275 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="@Translate("Close")"></button> 276 </div> 277 <div class="modal-body"> 278 @Translate("You need to complete your current quote or empty the cart before adding this product to cart.") 279 </div> 280 </template> 281 } 282 283 @if (quantitySelector || (!anonymousUser && product.VariantInfo?.VariantInfo != null) || (!anonymousUser && favoritesSelector)) 284 { 285 <input type="hidden" id="Unit_@(product.Id)_@product.VariantId?.Replace(".", "_")" name="UnitID" value="@unitId" /> 286 } 287 288 <div class="d-flex flex-wrap gap-2"> 289 @if (!quantitySelector) 290 { 291 <input id="Quantity_@(product.Id)_@product.VariantId?.Replace(".", "_")" class="swift_quantity_field" name="Quantity" value="@valueQty" type="hidden" @disableAddToCart> 292 } 293 294 @if (unitsSelector && product.UnitOptions?.Count > 0) 295 { 296 string selectedUnitName = !string.IsNullOrEmpty(unitId) && product?.UnitOptions != null ? unitId : product.UnitOptions.FirstOrDefault<UnitOptionViewModel>().Name; 297 298 foreach (var unitOption in product.UnitOptions) 299 { 300 if (unitOption.Id == unitId) 301 { 302 selectedUnitName = unitOption.Name; 303 } 304 } 305 306 <button class="btn btn-secondary @flexFill dropdown-toggle" data-dw-button="secondary" type="button" data-bs-toggle="dropdown" aria-expanded="false"> 307 @selectedUnitName 308 </button> 309 310 <ul class="dropdown-menu swift_unit-field"> 311 @foreach (var unitOption in product.UnitOptions) 312 { 313 var selectedUnit = unitOption.Id == unitId ? "selected" : ""; 314 315 <li> 316 <button type="button" class="btn dropdown-item" data-value="@unitOption.Id" onclick="document.querySelector('#UnitSelectorForm_@(product.Id)_@(product.VariantId.Replace(".", "_"))_@Model.ID').querySelector('.js-unit-id').value = this.getAttribute('data-value'); 317 document.querySelector('#Unit_@(product.Id)_@product.VariantId?.Replace(".", "_")').value = this.getAttribute('data-value'); 318 swift.PageUpdater.Update(document.querySelector('#UnitSelectorForm_@(product.Id)_@(product.VariantId?.Replace(".", "_"))_@Model.ID'))"> 319 <span>@unitOption.Name</span> 320 <span> 321 @if (unitOption.StockLevel > 0 || unitOption.NeverOutOfStock) 322 { 323 if (!Model.Item.GetBoolean("HideInventory") && !unitOption.NeverOutOfStock) 324 { 325 <span class="small text-success">@unitOption.StockLevel @Translate("In stock")</span> 326 } 327 else 328 { 329 <span class="small text-success">@Translate("In stock")</span> 330 } 331 } 332 else 333 { 334 <span class="small text-danger">@Translate("Out of Stock")</span> 335 } 336 </span> 337 </button> 338 </li> 339 } 340 </ul> 341 } 342 @if (quantitySelector) 343 { 344 @RenderPartial("Components/QuantitySelector.cshtml", product) 345 } 346 347 @{ 348 if (!isVariant && !hasVariants) { 349 disableAddToCart = ""; 350 } 351 if (isVariant) { 352 disableAddToCart = ""; 353 } 354 } 355 356 <button @disableAddToCart type="button" onclick="swift.Cart.Update(event)" class="btn btn-primary @flexFill js-add-to-cart-button" data-dw-button="primary" style="white-space: nowrap" title="@Translate("Add to cart")" id="AddToCartButton@(product.Id)_@Pageview.CurrentParagraph.ID"> 357 @if (!Model.Item.GetBoolean("HideButtonText")) 358 { 359 <span class="text-nowrap d-flex align-items-center justify-content-center gap-2"> 360 @addToCartLabel 361 </span> 362 } 363 else 364 { 365 @addToCartLabel 366 } 367 </button> 368 </div> 369 </form> 370 @if (!anonymousUser && favoritesSelector) 371 { 372 @RenderPartial("Components/ToggleFavorite.cshtml", product) 373 } 374 </div> 375 </div> 376 } 377 else if (whenVariantsExist == "modal") 378 { 379 string ButtonShape = Model.Item.GetRawValueString("VariantButtonShape", "square"); 380 string buttonAspectRatio = Model.Item.GetRawValueString("VariantImageAspectRatio", "56%"); 381 382 string buttonText = Translate("Select"); 383 string variantId = !string.IsNullOrWhiteSpace(product.VariantId) ? product.VariantId : product.DefaultVariantId; 384 385 string variantSelectorServicePageId = !string.IsNullOrEmpty(Model.Item.GetString("VariantSelectorServicePageId")) ? Model.Item.GetLink("VariantSelectorServicePageId").PageId.ToString() : ""; 386 variantSelectorServicePageId = variantSelectorServicePageId != "" ? variantSelectorServicePageId : GetPageIdByNavigationTag("VariantSelectorService").ToString(); 387 388 <div class="d-flex @horizontalAlign w-100 item_@Model.Item.SystemName.ToLower()"> 389 @if (!anonymousUser && favoritesSelector) 390 { 391 @RenderPartial("Components/ToggleFavorite.cshtml", product) 392 } 393 <form action="/Default.aspx?ID=@variantSelectorServicePageId" data-response-target-element="DynamicModalContent" data-preloader="inline" style="z-index: 1" class="@fullWidth"> 394 <input type="hidden" name="ProductID" value="@product.Id"> 395 <input type="hidden" name="VariantID" value="@variantId"> 396 <input type="hidden" name="QuantitySelector" value="@quantitySelector.ToString()"> 397 <input type="hidden" name="HideInventory" value="@hideInventory.ToString()"> 398 <input type="hidden" name="HideStockState" value="@hideStockState.ToString()"> 399 <input type="hidden" name="ButtonLayout" value="@ButtonShape"> 400 <input type="hidden" name="ButtonAspectRatio" value="@buttonAspectRatio"> 401 <input type="hidden" name="VariantSelectorServicePage" value="@variantSelectorServicePageId"> 402 <input type="hidden" name="ViewType" value="ModalContent"> 403 404 <button type="button" onclick="swift.PageUpdater.Update(event)" class="btn btn-primary @fullWidth" data-dw-button="primary" title="@Translate("Select")" data-bs-toggle="modal" data-bs-target="#DynamicModal" id="OpenVariantSelectorModal@(product.Id)_@Pageview.CurrentParagraph.ID">@buttonText</button> 405 </form> 406 </div> 407 } 408 } 409
Field display groups will be shown here if any
Tillbehör
Relaterade produkter
Liknande produkter