Component builder for: Product list page detail 2 - Ivy

Error executing template "Designs/Swift/Paragraph/SwiftRizzo_StockState.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
   at CompiledRazorTemplates.Dynamic.RazorEngine_33e1b4e016134b149ef8b67a0564d69f.Execute() in F:\Domains\Sites\uat-ic.mydwsite.com\Files\Templates\Designs\Swift\Paragraph\SwiftRizzo_StockState.cshtml:line 88
   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 System 3 @using System.Collections.Generic 4 @using System.Linq 5 @using Dynamicweb.Ecommerce.ProductCatalog 6 7 @functions 8 { 9 static Dynamicweb.Ecommerce.Stocks.StockStatus GetStockDefaultState(string defaultStockGroupId, double stock) 10 { 11 IEnumerable<Dynamicweb.Ecommerce.Stocks.StockStatus> defaultStockStatuses = Dynamicweb.Ecommerce.Services.StockService.GetStockStatuses(defaultStockGroupId, true); 12 foreach (var status in defaultStockStatuses) 13 { 14 switch (status.Definition ?? "") 15 { 16 case "<=": 17 if (stock <= status.Rate) 18 { 19 return status; 20 } 21 22 continue; 23 case ">=": 24 if (stock >= status.Rate) 25 { 26 return status; 27 } 28 29 continue; 30 } 31 } 32 33 return null; 34 } 35 } 36 37 @{ 38 /*START CUSTOM CODE*/ 39 string liveInfoClass = ""; 40 string productInfoFeed = ""; 41 bool isLazyLoadingForProductInfoEnabled = Dna.Ecommerce.LiveIntegration.TemplatesHelper.IsLazyLoadingForProductInfoEnabled; 42 if (isLazyLoadingForProductInfoEnabled) 43 { 44 if (Dynamicweb.Context.Current.Items.Contains("ProductInfoFeed")) 45 { 46 productInfoFeed = Dynamicweb.Context.Current.Items["ProductInfoFeed"]?.ToString(); 47 if (!string.IsNullOrEmpty(productInfoFeed)) 48 { 49 productInfoFeed = $"data-product-info-feed=\"{productInfoFeed}\""; 50 } 51 } 52 53 liveInfoClass = "js-live-info"; 54 } 55 56 //*END CUSTOM CODE*/ 57 ProductViewModel product = new ProductViewModel(); 58 59 ProductViewModelSettings productSetting = new ProductViewModelSettings 60 { 61 LanguageId = Dynamicweb.Ecommerce.Common.Context.LanguageID, 62 CurrencyCode = Dynamicweb.Ecommerce.Common.Context.Currency.Code, 63 CountryCode = Dynamicweb.Ecommerce.Common.Context.Country.Code2, 64 ShopId = Pageview.Area.EcomShopId 65 }; 66 67 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 68 { 69 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 70 } 71 else if (Pageview.Item["DummyProduct"] != null) 72 { 73 string dummyProductId = ""; 74 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 75 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 76 if (productList.Products != null) 77 { 78 foreach (var p in productList.Products) 79 { 80 dummyProductId = p.Id; 81 } 82 83 ProductViewModel dummyProduct = dummyProductId != "" ? ViewModelFactory.CreateView(productSetting, dummyProductId) : new ProductViewModel(); 84 product = dummyProduct; 85 } 86 else 87 { 88 product = ViewModelFactory.CreateView(productSetting, Dynamicweb.Ecommerce.Services.Products.GetLastActiveProducts(1, Dynamicweb.Ecommerce.Common.Context.LanguageID, false).FirstOrDefault().Id); 89 } 90 } 91 else if (Pageview.Item["DummyProduct"] == null) 92 { 93 product = ViewModelFactory.CreateView(productSetting, Dynamicweb.Ecommerce.Services.Products.GetLastActiveProducts(1, Dynamicweb.Ecommerce.Common.Context.LanguageID, false).FirstOrDefault().Id); 94 } 95 96 bool hasDeliveryTime = Model.Item.GetBoolean("IncludeDeliveryTimeInStockMessage"); 97 string defaultStockGroupId = Model.Item.GetRawValueString("DefaultStockState", string.Empty); 98 bool forceStockStateDefault = Model.Item.GetBoolean("ForceStockStateToDefault"); 99 string neverOutOfStockBehavior = Model.Item.GetRawValueString("NeverOutOfStockBehavior"); 100 101 string layout = Model.Item.GetRawValueString("Layout", "icon-top"); 102 string contentPadding = Model.Item.GetRawValueString("SpaceAround", ""); 103 contentPadding = contentPadding == "none" ? " px-0 py-3" : contentPadding; 104 contentPadding = contentPadding == "small" ? " px-3 py-3" : contentPadding; 105 contentPadding = contentPadding == "large" ? " ps-5 pe-3 py-3" : contentPadding; 106 107 string horizontalAlign = Model.Item.GetRawValueString("HorizontalAlignment", ""); 108 horizontalAlign = horizontalAlign == "center" ? "text-center" : horizontalAlign; 109 horizontalAlign = horizontalAlign == "end" ? "text-end" : horizontalAlign; 110 111 var languageId = Dynamicweb.Ecommerce.Common.Context.LanguageID; 112 113 Dynamicweb.Ecommerce.Products.Product prod = Dynamicweb.Ecommerce.Services.Products.GetProductById(product.Id, product.VariantId, true); 114 Dynamicweb.Ecommerce.Stocks.StockStatus productStockStatus = Dynamicweb.Ecommerce.Services.Products.GetStockStatus(prod); 115 string productStockGroupId = forceStockStateDefault ? defaultStockGroupId : prod.StockGroupId; 116 117 if (forceStockStateDefault) 118 { 119 productStockStatus = GetStockDefaultState(productStockGroupId, prod.Stock); 120 } 121 122 if (neverOutOfStockBehavior == "highestAmount" && prod.NeverOutOfStock) 123 { 124 productStockStatus = Dynamicweb.Ecommerce.Services.StockService.GetStockStatuses(productStockGroupId, true).LastOrDefault(); 125 } 126 127 string stockStatus = productStockStatus?.GetText(languageId); 128 string deliveryTimeText = productStockStatus?.GetExpectedDeliveryText(languageId); 129 string deliveryTime = hasDeliveryTime && !string.IsNullOrEmpty(deliveryTimeText) ? " - " + Translate("Delivery in ") + deliveryTimeText + " " + productStockStatus?.GetExpectedDeliveryValue(languageId) : string.Empty; 130 string stockIcon = productStockStatus?.Icon; 131 bool doDoRenderNeverOutOfStockProduct = prod.NeverOutOfStock && neverOutOfStockBehavior == "doNotRenderAnything"; 132 133 @*START CUSTOM CODE*@ 134 135 var stockGroups = Dynamicweb.Ecommerce.Services.StockService.GetStockGroups(); 136 var outOfStockText = ""; 137 var inStockText = ""; 138 var outOfStockIcon = ""; 139 var inStockIcon = ""; 140 } 141 142 @foreach (var stockGroup in stockGroups) 143 { 144 foreach (var stockStatusFromGroups in Dynamicweb.Ecommerce.Services.StockService.GetStockStatuses(stockGroup.Id, true)) 145 { 146 if (stockStatusFromGroups.Definition == "<=" && stockStatusFromGroups.Rate == 0) 147 { 148 outOfStockIcon = stockStatusFromGroups.Icon; 149 foreach (var stockStatusFromGroupsTranslation in stockStatusFromGroups.Translations) 150 { 151 if (languageId == stockStatusFromGroupsTranslation.LanguageId) 152 { 153 outOfStockText = stockStatusFromGroupsTranslation.Text; 154 } 155 } 156 } 157 else if (stockStatusFromGroups.Definition == ">=" && stockStatusFromGroups.Rate == 1) 158 { 159 inStockIcon = stockStatusFromGroups.Icon; 160 foreach (var stockStatusFromGroupsTranslation in stockStatusFromGroups.Translations) 161 { 162 if (languageId == stockStatusFromGroupsTranslation.LanguageId) 163 { 164 inStockText = stockStatusFromGroupsTranslation.Text; 165 } 166 } 167 } 168 } 169 } 170 @if (!doDoRenderNeverOutOfStockProduct && (!string.IsNullOrEmpty(stockStatus) && !layout.Equals("iconOnly", StringComparison.InvariantCultureIgnoreCase)) || (!string.IsNullOrEmpty(stockStatus) && layout.Equals("iconOnly", StringComparison.InvariantCultureIgnoreCase) && !string.IsNullOrEmpty(stockIcon))) 171 { 172 string imageWidth = Model.Item.GetRawValueString("ImageWidth", string.Empty); 173 174 var isPartsList = prod.Type.ToString().Equals("Bom", StringComparison.InvariantCultureIgnoreCase); 175 176 <div class="@(contentPadding) @horizontalAlign item_@Model.Item.SystemName.ToLower()"> 177 @switch (layout) 178 { 179 case "iconOnly": 180 if (!string.IsNullOrEmpty(stockIcon)) 181 { 182 if (isPartsList) 183 { 184 <div class="mt-3 js-stock-state"> 185 <span> 186 <img src="/Admin/Public/GetImage.ashx?image=@inStockIcon&width=@imageWidth&crop=0&format=webp&compression=75" alt="@inStockText"> 187 </span> 188 </div> 189 } 190 else 191 { 192 <div class="js-live-info js-product @liveInfoClass" data-product-id="@product.Id" data-variant-id="@product.VariantId"> 193 <div class="mt-3 js-stock-state spinner-border"> 194 195 <div class="d-none" data-show-if="LiveProductInfo.product.StockLevel => 1"> 196 <span> 197 <img src="/Admin/Public/GetImage.ashx?image=@inStockIcon&width=@imageWidth&crop=0&format=webp&compression=75" alt="@inStockText"> 198 </span> 199 </div> 200 201 <div class="d-none" data-show-if="LiveProductInfo.product.StockLevel <= 0"> 202 <span> 203 <img src="/Admin/Public/GetImage.ashx?image=@outOfStockIcon&width=@imageWidth&crop=0&format=webp&compression=75" alt="@outOfStockText"> 204 </span> 205 </div> 206 207 <div class="d-none" data-show-if="LiveProductInfo.product.ExpectedDelivery != null && new Date(LiveProductInfo.product.ExpectedDelivery) > new Date()"> 208 <span>@Translate("Expected back in stock:")</span> 209 <span class="js-text-expected-delivery"></span> 210 </div> 211 </div> 212 </div> 213 } 214 } 215 break; 216 case "iconAndText": 217 if (isPartsList) 218 { 219 <div class="mt-3 js-stock-state"> 220 <span> 221 <img src="/Admin/Public/GetImage.ashx?image=@inStockIcon&width=@imageWidth&crop=0&format=webp&compression=75" alt="@inStockText"> 222 </span> 223 @inStockText 224 </div> 225 } 226 else 227 { 228 <div class="js-live-info js-product @liveInfoClass" data-product-id="@product.Id" data-variant-id="@product.VariantId"> 229 <div class="mt-3 js-stock-state spinner-border"> 230 231 <div class="d-none" data-show-if="LiveProductInfo.product.StockLevel > 1 || LiveProductInfo.product.StockLevel == 1"> 232 <span> 233 <img src="/Admin/Public/GetImage.ashx?image=@inStockIcon&width=@imageWidth&crop=0&format=webp&compression=75" alt="@inStockText"> 234 </span> 235 @inStockText 236 </div> 237 238 <div class="d-none" data-show-if="LiveProductInfo.product.StockLevel <= 0"> 239 <span> 240 <img src="/Admin/Public/GetImage.ashx?image=@outOfStockIcon&width=@imageWidth&crop=0&format=webp&compression=75" alt="@outOfStockText"> 241 </span> 242 @outOfStockText 243 </div> 244 245 <div class="d-none" data-show-if="LiveProductInfo.product.ExpectedDelivery != null && new Date(LiveProductInfo.product.ExpectedDelivery) > new Date()"> 246 <span>@Translate("Expected back in stock:")</span> 247 <span class="js-text-expected-delivery"></span> 248 </div> 249 </div> 250 </div> 251 } 252 break; 253 case "textAndIcon": 254 if (isPartsList) 255 { 256 <div class="mt-3 js-stock-state"> 257 @inStockText 258 <span> 259 <img src="/Admin/Public/GetImage.ashx?image=@inStockIcon&width=@imageWidth&crop=0&format=webp&compression=75" alt="@inStockText"> 260 </span> 261 </div> 262 } 263 else 264 { 265 <div class="js-live-info js-product @liveInfoClass" data-product-id="@product.Id" data-variant-id="@product.VariantId"> 266 <div class="mt-3 js-stock-state spinner-border"> 267 268 <div class="d-none" data-show-if="LiveProductInfo.product.StockLevel > 1 || LiveProductInfo.product.StockLevel == 1"> 269 @inStockText 270 <span> 271 <img src="/Admin/Public/GetImage.ashx?image=@inStockIcon&width=@imageWidth&crop=0&format=webp&compression=75" alt="@inStockText"> 272 </span> 273 </div> 274 275 <div class="d-none" data-show-if="LiveProductInfo.product.StockLevel <= 0"> 276 @outOfStockText 277 <span> 278 <img src="/Admin/Public/GetImage.ashx?image=@outOfStockIcon&width=@imageWidth&crop=0&format=webp&compression=75" alt="@outOfStockText"> 279 </span> 280 </div> 281 282 <div class="d-none" data-show-if="LiveProductInfo.product.ExpectedDelivery != null && new Date(LiveProductInfo.product.ExpectedDelivery) > new Date()"> 283 <span>@Translate("Expected back in stock:")</span> 284 <span class="js-text-expected-delivery"></span> 285 </div> 286 </div> 287 </div> 288 } 289 break; 290 case "textOnly": 291 if (isPartsList) 292 { 293 <div class="mt-3 js-stock-state"> 294 @inStockText 295 </div> 296 } 297 else 298 { 299 <div class="js-live-info js-product @liveInfoClass" data-product-id="@product.Id" data-variant-id="@product.VariantId"> 300 <div class="mt-3 js-stock-state spinner-border"> 301 302 <div class="d-none" data-show-if="LiveProductInfo.product.StockLevel > 1 || LiveProductInfo.product.StockLevel == 1"> 303 @inStockText 304 </div> 305 306 <div class="d-none" data-show-if="LiveProductInfo.product.StockLevel <= 0"> 307 @outOfStockText 308 </div> 309 310 <div class="d-none" data-show-if="LiveProductInfo.product.ExpectedDelivery != null && new Date(LiveProductInfo.product.ExpectedDelivery) > new Date()"> 311 <span>@Translate("Expected back in stock:")</span> 312 <span class="js-text-expected-delivery"></span> 313 </div> 314 </div> 315 </div> 316 } 317 break; 318 } 319 </div> 320 } 321 @*END CUSTOM CODE*@ 322 else if (Pageview.IsVisualEditorMode) 323 { 324 <div class="alert alert-dark m-0">@Translate("Stock state will be rendered here")</div> 325 }
Error executing template "Designs/Swift/Paragraph/Custom__ShipDate.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
   at CompiledRazorTemplates.Dynamic.RazorEngine_61b778fc51754421ae7a27a53a3efb51.Execute() in F:\Domains\Sites\uat-ic.mydwsite.com\Files\Templates\Designs\Swift\Paragraph\Custom__ShipDate.cshtml:line 32
   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 @* 2 Ian notes 8/12/2025: pulled in the manual expected date using the line "DateTime? ManualDate =...", the added the integration expected date using "DateTime? ExpectedDate =...", 3 then created DisplayDateValue so it would only show 1 of the dates and edited the bool section so it would look at displaydatevalue. 4 5 Also, can use template in the future when trying to pull a custom field into a template, use the manual date as example. 6 *@ 7 8 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 9 @using System 10 @using System.Linq 11 @using Dynamicweb.Ecommerce.ProductCatalog 12 13 @{ 14 ProductViewModel product = null; 15 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 16 { 17 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 18 } 19 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 20 { 21 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 22 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 23 24 if (productList?.Products is object) 25 { 26 product = productList.Products[0]; 27 } 28 } 29 30 bool isErpConnectionDown = !Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsWebServiceConnectionAvailable"]); 31 bool hideStock = Pageview.AreaSettings.GetBoolean("ErpDownHideStock") && isErpConnectionDown; 32 DateTime? ManualDate = product.ProductFields.ContainsKey("ManualProductExpectedDelivery") && DateTime.TryParse(product.ProductFields["ManualProductExpectedDelivery"]?.ToString(), out var dt) ? dt : (DateTime?)null; 33 DateTime? ExpectedDate = product.ExpectedDelivery; 34 DateTime? DisplayDateValue = ExpectedDate ?? ManualDate; 35 bool hasDisplayDate = DisplayDateValue != null && DisplayDateValue > DateTime.Now; 36 } 37 38 39 @if ((product is object && !hideStock) && (hasDisplayDate)) 40 { 41 string horizontalAlign = Model.Item.GetRawValueString("HorizontalAlignment", ""); 42 horizontalAlign = horizontalAlign == "center" ? "text-center" : horizontalAlign; 43 horizontalAlign = horizontalAlign == "end" ? "text-end" : horizontalAlign; 44 string DisplayDate = DisplayDateValue?.ToShortDateString() ?? ""; 45 46 string liveInfoClass = ""; 47 string productInfoFeed = ""; 48 bool isLazyLoadingForProductInfoEnabled = Dna.Ecommerce.LiveIntegration.TemplatesHelper.IsLazyLoadingForProductInfoEnabled; 49 50 if (isLazyLoadingForProductInfoEnabled) 51 { 52 if (Dynamicweb.Context.Current.Items.Contains("ProductInfoFeed")) 53 { 54 productInfoFeed = Dynamicweb.Context.Current.Items["ProductInfoFeed"]?.ToString(); 55 if (!string.IsNullOrEmpty(productInfoFeed)) 56 { 57 productInfoFeed = $"data-product-info-feed=\"{productInfoFeed}\""; 58 } 59 } 60 liveInfoClass = "js-live-info"; 61 62 <div class="js-stock-state @horizontalAlign item_@Model.Item.SystemName.ToLower() @liveInfoClass" data-product-id="@product.Id" data-variant-id="@product.VariantId" @productInfoFeed> 63 <div class="js-stock-state spinner-border"> 64 <p class="d-none" data-show-if="LiveProductInfo.product.StockLevel <= 0"> 65 <span class="js-text-stock d-none"></span> 66 <span>@Translate("Expected Ship Date"): </span> 67 <span>@DisplayDate</span> 68 </p> 69 </div> 70 </div> 71 } 72 else 73 { 74 string firstUnitId = product?.UnitOptions?.FirstOrDefault() != null ? product.UnitOptions.FirstOrDefault().Id : ""; 75 string defaultUnitId = !string.IsNullOrEmpty(product.DefaultUnitId) ? product.DefaultUnitId : firstUnitId; 76 string unitId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.Form.Get("UnitId")) ? Dynamicweb.Context.Current.Request.Form.Get("UnitId") : defaultUnitId; 77 78 var reserveMode = Dynamicweb.Ecommerce.Frontend.Cart.ProductReserve.Mode; 79 double? reservedAmount = 0; 80 if (reserveMode == Dynamicweb.Ecommerce.Frontend.Cart.ProductReserveMode.AddToCart) 81 { 82 reservedAmount = Dynamicweb.Ecommerce.Frontend.Cart.ProductReserve.GetReservedAmount(product.Id, product.VariantId, 0, unitId); 83 } 84 double? currentStockLevel = product.StockLevel - reservedAmount; 85 86 <div class="js-stock-state @horizontalAlign item_@Model.Item.SystemName.ToLower()"> 87 @if (currentStockLevel <= 0) 88 { 89 <p> 90 <span>@Translate("Expected Ship Date"): </span> 91 <span>@DisplayDate</span> 92 </p> 93 } 94 </div> 95 } 96 } else if (Pageview.IsVisualEditorMode) 97 { 98 <div class="alert alert-info">@Translate("Expected Ship Date will be rendered here")</div> 99 }
By clicking 'Accept All' you consent that we may collect information about you for various purposes, including: Functionality, Statistics and Marketing