Error executing template "Designs/Swift/Paragraph/Swift_ProductAddToCart.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
   at CompiledRazorTemplates.Dynamic.RazorEngine_1975e9da977a41aa9edea57355515169.Execute() in F:\Domains\Sites\uat-krvc.mydwsitec.com\Files\Templates\Designs\Swift\Paragraph\Swift_ProductAddToCart.cshtml:line 41
   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.ParagraphViewModel>
  2     @using Dynamicweb.Ecommerce.ProductCatalog
  3     @using Dynamicweb.Core.Encoders
  4     @using System.Globalization
  5     
  6     @functions {
  7     	string DoubleToString(double? value)
  8     	{
  9     		if (value.HasValue)
 10     		{
 11     			return value.Value.ToString(CultureInfo.InvariantCulture);
 12     		}
 13     		return null;
 14     	}
 15     }
 16     
 17     @{
 18     	ProductViewModel product = null;
 19     	if (Dynamicweb.Context.Current.Items.Contains("ProductDetails"))
 20     	{
 21     		product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"];
 22     	}
 23     	else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode)
 24     	{
 25     		var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page);
 26     		ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel();
 27     
 28     		if (productList?.Products is object)
 29     		{
 30     			product = productList.Products[0];
 31     		}
 32     	}
 33     
 34     	bool showZeroPrice = Model.Item.GetString("ShowPrice") == "show";
 35     	string zeroPriceMessage = Model.Item.GetString("Message");
 36     
 37     	string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", "");
 38     	bool anonymousUser = Pageview.User == null;
 39     	bool isErpConnectionDown = !Dna.Ecommerce.LiveIntegration.TemplatesHelper.IsWebServiceConnectionAvailable();
 40     	bool isLazyLoadingForProductInfoEnabled = Dna.Ecommerce.LiveIntegration.TemplatesHelper.IsLazyLoadingForProductInfoEnabled;
 41     	bool hideAddToCart = (anonymousUsersLimitations.Contains("cart") && anonymousUser) || (Pageview.AreaSettings.GetBoolean("ErpDownHideAddToCart") && isErpConnectionDown) || (!showZeroPrice && (product.Price.Price <= 0 && !isLazyLoadingForProductInfoEnabled));
 42     	hideAddToCart = Dna.SwiftRizzo.NonOrderable.Helpers.IsProductNonOrderable(product) || hideAddToCart;
 43     	hideAddToCart = Pageview.IsVisualEditorMode ? false : hideAddToCart;
 44     
 45     	string horizontalAlign = Model.Item.GetRawValueString("HorizontalAlignment", "");
 46     	horizontalAlign = horizontalAlign == "center" ? "justify-content-center" : horizontalAlign;
 47     	horizontalAlign = horizontalAlign == "end" ? "justify-content-end" : horizontalAlign;
 48     	horizontalAlign = horizontalAlign == "full" ? "" : horizontalAlign;
 49     	
 50     	string fullWidth = Model.Item.GetRawValueString("HorizontalAlignment", "") == "full" ? "w-100" : "";
 51     }
 52     
 53     @if (product is object && !hideAddToCart)
 54     {
 55     	bool favoritesSelector = !string.IsNullOrEmpty(Model.Item.GetString("ShowAddToFavorites")) ? Model.Item.GetBoolean("ShowAddToFavorites") : false;
 56     	bool quantitySelector = !string.IsNullOrEmpty(Model.Item.GetString("ShowQuantitySelector")) ? Model.Item.GetBoolean("ShowQuantitySelector") : false;
 57     	bool unitsSelector = !string.IsNullOrEmpty(Model.Item.GetString("ShowUnitsSelector")) ? Model.Item.GetBoolean("ShowUnitsSelector") : false;
 58     	bool hideInventory = !string.IsNullOrEmpty(Model.Item.GetString("HideInventory")) ? Model.Item.GetBoolean("HideInventory") : false;
 59     	bool hideStockState = !string.IsNullOrEmpty(Model.Item.GetString("HideStockState")) ? Model.Item.GetBoolean("HideStockState") : false;
 60     
 61     	string buttonSize = Model.Item.GetRawValueString("ButtonSize", "regular");
 62     	string inputSize = string.Empty;
 63     
 64     	switch (buttonSize)
 65     	{
 66     		case "small":
 67     			inputSize = " input-group-sm";
 68     			buttonSize = " btn-sm";
 69     			break;
 70     		case "regular":
 71     			buttonSize = string.Empty;
 72     			break;
 73     		case "large":
 74     			inputSize = " input-group-lg";
 75     			buttonSize = " btn-lg";
 76     			break;
 77     	}
 78     
 79     	string iconPath = "/Files/icons/";
 80     	string url = "/Default.aspx?ID=" + (GetPageIdByNavigationTag("CartService"));
 81     	if (!url.Contains("LayoutTemplate"))
 82     	{
 83     		url += url.Contains("?") ? "&LayoutTemplate=Swift_MiniCart.cshtml" : "?LayoutTemplate=Swift_MiniCart.cshtml";
 84     	}
 85     
 86     	string whenVariantsExist = Model.Item.GetRawValueString("WhenVariantsExist", "hide");
 87     	string flexFill = Model.Item.GetRawValueString("HorizontalAlignment", "") == "full" ? "flex-fill" : "";
 88     	string addToCartIcon = Model.Item.GetRawValueString("Icon", iconPath + "shopping-cart.svg");
 89     	string addToCartLabel = !addToCartIcon.Contains("_none") ? $"<span class=\"icon-2\">{ReadFile(addToCartIcon)}</span>" : "";
 90     	addToCartLabel += !addToCartIcon.Contains("_none") && !Model.Item.GetBoolean("HideButtonText") ? " " : "";
 91     	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>" : "";
 92     
 93     	bool userHasPendingQuote = Dynamicweb.Ecommerce.Common.Context.Cart != null && Dynamicweb.Ecommerce.Common.Context.Cart.IsQuote;
 94     	string cartOnClickText = userHasPendingQuote ? $"alert('{Translate("You need to complete your current quote or empty the cart before adding this product to cart")}')" 
 95     		: "swift.Cart.Update(event)";
 96     
 97     	string liveInfoClass = isLazyLoadingForProductInfoEnabled ? "js-live-info" : "";
 98     	
 99     	if (product.VariantInfo.VariantInfo == null || whenVariantsExist == "disable")
100     	{
101     		string unitId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.Form.Get("UnitId")) ? Dynamicweb.Context.Current.Request.Form.Get("UnitId") : product.DefaultUnitId;
102     		if (string.IsNullOrEmpty(unitId) && product?.UnitOptions != null)
103     		{
104     			if (product.UnitOptions.FirstOrDefault<UnitOptionViewModel>() != null)
105     			{
106     				unitId = product.UnitOptions.FirstOrDefault<UnitOptionViewModel>().Id;
107     			}
108     		}
109     
110     		double? stepQty = product.PurchaseQuantityStep > 0 ? product.PurchaseQuantityStep : 1;
111     		double? minQty = product.PurchaseMinimumQuantity > 0 ? product.PurchaseMinimumQuantity : 1;
112     		double? valueQty = minQty > stepQty ? minQty : stepQty;
113     		string disableAddToCart = null;
114     		double? maxQty = null;
115     		
116     		if (product.ProductType == Dynamicweb.Ecommerce.Products.ProductType.Stock && !product.NeverOutOfstock)
117     		{
118     			disableAddToCart = (product.StockLevel <= 0) || (!product.NeverOutOfstock && isLazyLoadingForProductInfoEnabled) ? "disabled" : disableAddToCart;
119     			maxQty = product.StockLevel;
120     		}
121     
122     		disableAddToCart = whenVariantsExist == "disable" && product.VariantInfo.VariantInfo != null && string.IsNullOrEmpty(product.VariantId) ? "disabled" : disableAddToCart;
123     
124     		if (unitsSelector && product.UnitOptions.Count > 0)
125     		{
126     			<form method="post" action="/Default.aspx?ID=@(Pageview.Page.ID)&ProductId=@product.Id" id="UnitSelectorForm_@(product.Id)_@(product.VariantId.Replace(".", "_"))_@Model.ID">
127     				<input type="hidden" name="redirect" value="false">
128     				<input type="hidden" name="VariantID" value="@product.VariantId">
129     				<input type="hidden" name="UnitID" class="js-unit-id" value="@unitId">
130     			</form>
131     		}
132     
133     		<div class="d-flex @horizontalAlign @fullWidth @liveInfoClass js-input-group item_@Model.Item.SystemName.ToLower()" data-product-id="@product.Id" data-variant-id="@product.VariantId" data-show-zero-price="@showZeroPrice" data-zero-price-message="@zeroPriceMessage">
134     			@if (!anonymousUser && favoritesSelector)
135     			{
136     				@RenderPartial("Components/ToggleFavorite.cshtml", product)
137     			}
138     			
139     			@*START CUSTOM CODE*@
140     			@if (product.ReplacementProduct != null && product.ReplacementProduct.ProductId != "")
141     			{
142     				var replacementProductLink = $"{Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(GetPageIdByNavigationTag("Shop"))}?ProductId={product.ReplacementProduct.ProductId}&VariantId={product.ReplacementProduct.VariantId}";
143     
144     				<div class="@fullWidth ms-4">
145     					<a href="@replacementProductLink" class="btn btn-primary text-nowrap">@Translate("View Replacement")</a>
146     				</div>
147     			}
148     			else
149     			{
150     			@*END CUSTOM CODE*@
151     				<form method="post" action="@url" class="@fullWidth" style="z-index: 1">
152     					<input type="hidden" name="redirect" value="false">
153     					<input type="hidden" name="ProductId" value="@product.Id">
154     					<input type="hidden" name="ProductName" value="@HtmlEncoder.HtmlEncode(product.Name)">
155     					<input type="hidden" name="ProductVariantName" value="@product.VariantName">
156     					<input type="hidden" name="ProductCurrency" value="@Dynamicweb.Ecommerce.Common.Context.Currency.Code">
157     					<input type="hidden" name="ProductPrice" value="@PriceViewModelExtensions.ToStringInvariant(product.Price)">
158     					<input type="hidden" name="ProductReferer" value="component_ProductAddToCart">
159     					<input type="hidden" name="cartcmd" value="add">
160     					<input type="submit" class="d-none" onclick="event.preventDefault(); swift.Cart.Update(event)"> @* Fix for enterKey should not redirect to minicart page *@
161     
162     					@if (!string.IsNullOrEmpty(product.VariantId))
163     					{
164     						<input type="hidden" name="VariantId" value="@product.VariantId">
165     					}
166     
167     					<template class="js-step-quantity-warning">
168     						<div class="modal-header">
169     							<h1 class="modal-title fs-5">@Translate("The quantity is not valid")</h1>
170     							<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
171     						</div>
172     						<div class="modal-body">
173     							@Translate("Please select a quantity that is dividable by") @stepQty
174     						</div>
175     					</template>
176     
177     
178     					<template class="js-min-quantity-warning">
179     						<div class="modal-header">
180     							<h1 class="modal-title fs-5">@Translate("The product could not be added to the cart")</h1>
181     							<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
182     						</div>
183     						<div class="modal-body">
184     							@Translate("The quantity is not valid. You must buy at least") @product.PurchaseMinimumQuantity
185     						</div>
186     					</template>
187     
188     					<template class="js-value-missing-warning">
189     						<div class="modal-header">
190     							<h1 class="modal-title fs-5">@Translate("No amount specified")</h1>
191     							<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
192     						</div>
193     						<div class="modal-body">
194     							@Translate("Specify an amount to add to the cart")
195     						</div>
196     					</template>
197     
198     
199     					@if (userHasPendingQuote)
200     					{
201     						<input type="hidden" name="PendingQuote" value="true">
202     
203     						<template class="js-pending-quote-notice">
204     							<div class="modal-header">
205     								<h1 class="modal-title fs-5">@Translate("Pending Quote")</h1>
206     								<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="@Translate("Close")"></button>
207     							</div>
208     							<div class="modal-body">
209     								@Translate("You need to complete your current quote or empty the cart before adding this product to cart.")
210     							</div>
211     						</template>
212     					}
213     
214     					@if (quantitySelector || (!anonymousUser && product.VariantInfo.VariantInfo != null) || (!anonymousUser && favoritesSelector))
215     					{
216     						<input type="hidden" id="Unit_@(product.Id)_@product.VariantId.Replace(".", "_")" name="UnitID" value="@unitId" />
217     					}
218     
219     					<div class="d-flex flex-row w-100">
220     						@if (!quantitySelector)
221     						{
222     							<input id="Quantity_@(product.Id)_@product.VariantId.Replace(".", "_")" class="swift_quantity_field" name="Quantity" value="@valueQty" type="hidden" @disableAddToCart>
223     						}
224     
225     						@if (unitsSelector && product.UnitOptions.Count > 0)
226     						{
227     							string selectedUnitName = !string.IsNullOrEmpty(unitId) && product?.UnitOptions != null ? unitId : product.UnitOptions.FirstOrDefault<UnitOptionViewModel>().Name;
228     
229     							foreach (var unitOption in product.UnitOptions)
230     							{
231     								if (unitOption.Id == unitId)
232     								{
233     									selectedUnitName = unitOption.Name;
234     								}
235     							}
236     
237     							<div class="d-flex flex-column gap-2 w-100">
238     								<div class="input-group input-primary-button-group flex-nowrap@(inputSize)">
239     
240     									@if (quantitySelector)
241     									{
242     										<input id="Quantity_@(product.Id)_@product.VariantId.Replace(".", "_")" name="Quantity" value="@DoubleToString(valueQty)" step="@DoubleToString(stepQty)" min="@DoubleToString(minQty)" max="@DoubleToString(maxQty)" class="form-control swift_quantity-field" style="min-width: 60px; max-width: 100px; z-index: 1" type="number" @disableAddToCart>
243     									}
244     
245     									<button class="btn btn-secondary @flexFill dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
246     										@selectedUnitName
247     									</button>
248     
249     									<ul class="dropdown-menu swift_unit-field">
250     										@foreach (var unitOption in product.UnitOptions)
251     										{
252     											var selectedUnit = unitOption.Id == unitId ? "selected" : "";
253     
254     											<li>
255     												<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');
256     																											document.querySelector('#Unit_@(product.Id)_@product.VariantId.Replace(".", "_")').value = this.getAttribute('data-value');
257     																											swift.PageUpdater.Update(document.querySelector('#UnitSelectorForm_@(product.Id)_@(product.VariantId.Replace(".", "_"))_@Model.ID'))">
258     													<span>@unitOption.Name</span>
259     													<span>
260     														@if (unitOption.StockLevel > 0 || unitOption.NeverOutOfStock)
261     														{
262     															if (!Model.Item.GetBoolean("HideInventory") && !unitOption.NeverOutOfStock)
263     															{
264     																<span class="small text-success">@unitOption.StockLevel @Translate("In stock")</span>
265     															}
266     															else
267     															{
268     																<span class="small text-success">@Translate("In stock")</span>
269     															}
270     														}
271     														else
272     														{
273     															<span class="small text-danger">@Translate("Out of Stock")</span>
274     														}
275     													</span>
276     												</button>
277     											</li>
278     										}
279     									</ul>
280     								</div>
281     								<button type="button" onclick="@cartOnClickText" class="btn btn-primary @(buttonSize) js-add-to-cart-button" style="white-space: nowrap" @disableAddToCart title="@Translate("Add to cart")" id="AddToCartButton@(product.Id)_@Pageview.CurrentParagraph.ID">
282     									@if (!Model.Item.GetBoolean("HideButtonText"))
283     									{
284     										<span class="text-nowrap d-flex align-items-center justify-content-center gap-2">
285     											@addToCartLabel
286     										</span>
287     									}
288     									else
289     									{
290     										@addToCartLabel
291     									}
292     								</button>
293     							</div>
294     						}
295     						else
296     						{
297     							<div class="input-group input-primary-button-group flex-nowrap@(inputSize)">
298     								@if (quantitySelector)
299     								{
300     									<input id="Quantity_@(product.Id)_@product.VariantId.Replace(".", "_")" name="Quantity" value="@DoubleToString(valueQty)" step="@DoubleToString(stepQty)" min="@DoubleToString(minQty)" max="@DoubleToString(maxQty)" class="form-control swift_quantity-field" style="min-width: 60px; max-width: 100px; z-index: 1" type="number" @disableAddToCart>
301     								}
302     
303     								<button type="button" onclick="@cartOnClickText" class="btn btn-primary @(buttonSize) @flexFill js-add-to-cart-button" style="white-space: nowrap" @disableAddToCart title="@Translate("Add to cart")" id="AddToCartButton@(product.Id)_@Pageview.CurrentParagraph.ID">
304     									@if (!Model.Item.GetBoolean("HideButtonText"))
305     									{
306     										<span class="text-nowrap d-flex align-items-center justify-content-center gap-2">
307     											@addToCartLabel
308     										</span>
309     									}
310     									else
311     									{
312     										@addToCartLabel
313     									}
314     								</button>
315     							</div>
316     						}
317     					</div>
318     				</form>
319     				@*START CUSTOM CODE*@
320     			}
321     			@*END CUSTOM CODE*@
322     
323     			
324     		</div>
325     	}
326     	else if (whenVariantsExist == "modal")
327     	{
328     		string ButtonShape = Model.Item.GetRawValueString("VariantButtonShape", "square");
329     		string buttonAspectRatio = Model.Item.GetRawValueString("VariantImageAspectRatio", "56%");
330     
331     		string buttonText = Translate("Select");
332     		string variantId = !string.IsNullOrWhiteSpace(product.VariantId) ? product.VariantId : product.DefaultVariantId;
333     
334     		string variantSelectorServicePageId = !string.IsNullOrEmpty(Model.Item.GetString("VariantSelectorServicePageId")) ? Model.Item.GetLink("VariantSelectorServicePageId").PageId.ToString() : "";
335     		variantSelectorServicePageId = variantSelectorServicePageId != "" ? variantSelectorServicePageId : GetPageIdByNavigationTag("VariantSelectorService").ToString();
336     
337     		<div class="d-flex @horizontalAlign w-100 item_@Model.Item.SystemName.ToLower()">
338     			@if (!anonymousUser && favoritesSelector)
339     			{
340     				@RenderPartial("Components/ToggleFavorite.cshtml", product)
341     			}
342     			<form action="/Default.aspx?ID=@variantSelectorServicePageId" data-response-target-element="DynamicModalContent" data-preloader="inline" style="z-index: 1" class="@fullWidth">
343     				<input type="hidden" name="ProductID" value="@product.Id">
344     				<input type="hidden" name="VariantID" value="@variantId">
345     				<input type="hidden" name="QuantitySelector" value="@quantitySelector.ToString()">
346     				<input type="hidden" name="HideInventory" value="@hideInventory.ToString()">
347     				<input type="hidden" name="HideStockState" value="@hideStockState.ToString()">
348     				<input type="hidden" name="ButtonLayout" value="@ButtonShape">
349     				<input type="hidden" name="ButtonAspectRatio" value="@buttonAspectRatio">
350     				<input type="hidden" name="VariantSelectorServicePage" value="@variantSelectorServicePageId">
351     				<input type="hidden" name="ViewType" value="ModalContent">
352     				@if (isLazyLoadingForProductInfoEnabled)
353     				{
354     					@* If lazy loading is enabled, bypass it because we're loading a modal window, so render everything as if it was server-side *@
355     					<input type="hidden" name="getproductinfo" value="true">
356     				}
357     				<button type="button" onclick="@cartOnClickText" class="btn btn-primary@(buttonSize) @fullWidth" title="@Translate("Select")" data-bs-toggle="modal" data-bs-target="#DynamicModal" id="OpenVariantSelectorModal@(product.Id)_@Pageview.CurrentParagraph.ID">@buttonText</button>
358     			</form>
359     		</div>
360     	}
361     }
362     else if (!string.IsNullOrEmpty(zeroPriceMessage))
363     {
364     	<div class="d-flex @horizontalAlign @fullWidth item_@Model.Item.SystemName.ToLower()">@zeroPriceMessage</div>
365     }
366     else if (Pageview.IsVisualEditorMode)
367     {
368     	<div class="alert alert-dark m-0">@Translate("No products available")</div>
369     }
370