Error executing template "Designs/Rapido/eCom/ProductCatalog/Partials/ProductList.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
at Nevotex.PriceProvider.NevotexPriceProvider.PreparePrices(ProductCollection products) in C:\Users\aki.ruuskanen\source\repos\Nevotex\Nevotex.PriceProvider\NevotexPriceProvider.cs:line 157
at Dynamicweb.Ecommerce.Prices.PriceManager.PreparePrices(PriceContext context, IEnumerable`1 selections)
at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.PreparePrices(PriceContext context, Boolean& pricesHasBeenPrepared, Object lock, IList`1 products, Int64 stockLocationId)
at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.CreateView(VariantInfoViewModelSettings settings, Product product, Dictionary`2 variants, Lazy`1 details, IList`1 products, Boolean& pricesHasBeenPrepared, Boolean& variantPricesHasBeenPrepared, Object lock)
at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.<>c__DisplayClass3_1.<BulkCreateView>b__6()
at System.Lazy`1.CreateValue()
at System.Lazy`1.LazyInitValue()
at Dynamicweb.Ecommerce.ProductCatalog.ProductViewModelExtensionMethods.VariantGroups(ProductViewModel productViewModel)
at CompiledRazorTemplates.Dynamic.RazorEngine_a729fbba72e74ff986ab7f564ecbe063.Execute() in F:\sites\NevotexProd\WEB\Application\Files\Templates\Designs\Rapido\eCom\ProductCatalog\Partials\ProductList.cshtml:line 223
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 ViewModelTemplate<ProductListViewModel> 2 @using Dynamicweb.Rendering 3 @using Dynamicweb.Ecommerce.ProductCatalog 4 @using Dynamicweb.Ecommerce; 5 @using System.Collections.Generic; 6 @using System.Web; 7 @using System.Linq; 8 @using Nevotex.Data.Cache 9 @using Nevotex.Data.Entities 10 @using Nevotex.Data.Helpers 11 @using Nevotex.Data.Services 12 13 @{ 14 var productServiceForProductList = new ProductService(); 15 var shopPageId = GetPageIdByNavigationTag("ProductsPage"); 16 var listName = HttpContext.Current?.Request["ListName"]; 17 //var groupId = Model.Group.Id; 18 //var rendera_4 = Convert.ToBoolean(Model.Group.GroupFields.FirstOrDefault(f => f.SystemName == "Rendera_4bilden")?.Value); 19 var gridCSS = "grid__col-lg-3 grid__col-md-3 grid__col-sm-3 grid__col-xs-6 product-list__grid-item image-hover--zoom dw-mod"; 20 21 //var isCollection = productServiceForProductList.IsGroupACollection(Model.Group.Id, Pageview.Area.EcomLanguageId); 22 23 var groupId = Model?.Group?.Id; 24 var languageId = Pageview?.Area?.EcomLanguageId; 25 26 var isCollection = groupId != null && languageId != null 27 ? productServiceForProductList.IsGroupACollection(groupId, languageId) 28 : false; 29 30 var isSearch = !string.IsNullOrWhiteSpace(HttpContext.Current.Request.QueryString.Get("Search")); 31 var onlyShowVariants = HttpContext.Current.Request.QueryString.Get("OnlyShowVariants") == "true"; 32 var kulorFilterPresent = !string.IsNullOrWhiteSpace(Dynamicweb.Context.Current.Request.QueryString["Kulorfilter"]); 33 var columnCss = isCollection ? "2" : "3"; 34 var displayCss = isCollection ? "u-hidden" : ""; 35 var cropMode = isCollection ? "0" : "5"; 36 var paddingFix = isCollection ? "product-list__grid-item__collection-price-info" : string.Empty; 37 var imageBorder = isCollection ? "product-list__grid-item__no_border" : "product-list__grid-item__border"; 38 var hideArticleNumberCss = isCollection ? "u-hidden collection-item" : string.Empty; 39 40 41 var value = Model?.Group?.GroupFields? 42 .FirstOrDefault(f => f.SystemName == "Rendera_4bilden") 43 ?.Value?.ToString(); 44 45 var rendera_4 = bool.TryParse(value, out var result) && result; 46 47 if (isCollection) 48 { 49 gridCSS = "grid__col-lg-2 grid__col-md-2 grid__col-sm-2 grid__col-xs-6 product-list__grid-item image-hover--zoom dw-mod"; 50 } 51 } 52 53 <!--HEADER--> 54 <div class="grid grid--align-content-start grid--justify-start grid--bleed u-margin-bottom--lg u-padding grid--wrap u-flex-grow--0 dw-mod"> 55 <div class="grid "> 56 <div class="u-pull--left"> 57 <h1> 58 <i class=""></i>@(string.IsNullOrWhiteSpace(listName) 59 ? Model?.Group?.Name 60 : listName) 61 </h1> 62 </div> 63 <div class="grid__col-xs-12 grid__col-md-6 dw-mod"> 64 </div> 65 </div> 66 </div> 67 68 <!--FACETS--> 69 <div class="grid__col-lg-3 grid__col-md-3 grid__col-sm-12 grid__col-xs-12 dw-mod" id="Block__Navigation"> 70 <input type="checkbox" id="CheckFacetGroups" class="js-remember-state u-hidden" data-expand="CheckFacetGroups" data-loaded="true"> 71 <div class="facets-container facets-container--left expandable--collapsed dw-mod" data-trigger="CheckFacetGroups"> 72 73 @{ 74 bool facetsFound = false; 75 int selectedFacetsCount = 0; 76 77 78 if (Model.FacetGroups != null) 79 { 80 foreach (FacetGroupViewModel facetGroup in Model.FacetGroups) 81 { 82 83 foreach (FacetViewModel facet in facetGroup.Facets) 84 { 85 86 if (kulorFilterPresent && facet.Name == "Kulör") 87 { 88 continue; 89 } 90 91 if (facet.OptionResultTotalCount > 0) 92 { 93 var optionGroupId = $"OptionsGroup_{facet.Name}"; 94 95 <input type="checkbox" id="@optionGroupId" class="expand-trigger js-remember-state" data-loaded="true" /> 96 97 <div class="expand-container facets-container__box dw-mod js-filter"> 98 <label class="expand-container__btn facets-container__header dw-mod" for="@optionGroupId">@Translate(facet.Name)</label> 99 <div class="expand-container__content js-facet-container dw-mod" data-input="@optionGroupId"> 100101 @if (facet.Options.Count() > 0) 102 { 103 var faceListId = $"facetList{facet.Name}"; 104105 facetsFound = true; 106107 <div id="@faceListId" class="facets-container__list dw-mod"> 108 @foreach (FacetOptionViewModel option in facet.Options) 109 { 110 var facetOptionId = $"{facet.QueryParameter}{option.Name}"; 111 var selected = string.Empty; 112 string facetLabel = Translate(option.Label); 113114 if (facetLabel.ToLower() == "true") 115 { 116 facetLabel = Translate("Yes"); 117 } 118119 if (facetLabel.ToLower() == "false") 120 { 121 facetLabel = Translate("No"); 122 } 123124 if (option.Selected) 125 { 126 selected = "checked"; 127 selectedFacetsCount++; 128 } 129130 if (facet.RenderType != "Range" && facet.Name != "Bredd") 131 { 132 <div class="form__field-group u-no-margin dw-mod"> 133 <input type="checkbox" class=" checkbox-facet__checkbox form__control dw-mod" onclick="Facets.UpdateFacets(this);" id="@facetOptionId" @selected name="@facet.QueryParameter" value="[@option.Name]" /> 134 <label class=" checkbox-facet dw-mod" data-filter-value="@facetLabel" for="@facetOptionId"> 135 <span class="checkbox-facet__label dw-mod">@facetLabel</span> 136 @if (isCollection) 137 { 138 <span class="checkbox-facet__count dw-mod">(@option.Count)</span> 139 } 140141 </label> 142 </div> 143 } 144 else if (facet.Name == "Bredd") 145 { 146147 } 148149150151152 } 153 </div> 154 } 155156 </div> 157 </div> 158 } 159160161 } 162 } 163164 } 165 } 166167 </div> 168 </div> 169170 <label for="CheckFacetGroups" class="btn btn--primary btn--full u-no-margin dw-mod js-expand-hide facets-container-trigger" data-trigger="CheckFacetGroups">Filtrera</label> 171 <label for="CheckFacetGroups" class="btn btn--primary btn--full u-no-margin dw-mod expandable--collapsed facets-container-trigger" data-trigger="CheckFacetGroups">Stäng filter</label> 172173 <!--PRODUCTLIST COLLECTION--> 174175 <div class="grid__col-auto"> 176177 <div class="buttons-collection u-margin-bottom" id="selectedFacets"> 178179 @foreach (FacetGroupViewModel faceGroup in Model.FacetGroups) 180 { 181 foreach (FacetViewModel facet in faceGroup.Facets) 182 { 183 if (facet.OptionResultTotalCount > 0) 184 { 185 foreach (FacetOptionViewModel option in facet.Options) 186 { 187 if (option.Selected) 188 { 189 <button type="button" class="btn btn--tag dw-mod" data-check="checked" onclick="Facets.UpdateFacets(this);" name="@facet.QueryParameter" value="[@option.Value]" title="@Translate("Remove filter")"> 190 @Translate(facet.Name) : @Translate(option.Label) &nbsp;<i class="fal fa-times"></i> 191 </button> 192 } 193 } 194 } 195 } 196 } 197198 </div> 199200 <div id="ProductsContainer" class="grid product-list grid--external-bleed-x dw-mod grid--align-content-start" data-save-cookie="true"> 201202 @foreach (ProductViewModel product in Model.Products) 203 { 204205 var productName = product.Name; 206 var productId = product.Id; 207 var productVariantId = product.VariantId; 208 var productUnit = product.DefaultUnitId; 209 var uniqueId = Guid.NewGuid().ToString("N"); 210 var productLoopCounter = $"ProductLoopCounter{uniqueId}"; 211 var productLoopId = $"ProductID{uniqueId}"; 212 var variantLoopName = $"VariantID{uniqueId}"; 213 var variantLoopId = $"Variant_{uniqueId}"; 214 var unitLoopName = $"UnitID{uniqueId}"; 215 var unitLoopId = $"Unit_{uniqueId}"; 216 var quantityLoopName = $"Quantity{uniqueId}"; 217 var quantityLoopId = $"Quantity_{uniqueId}"; 218 var cartButtonId = $"CartButton_{uniqueId}"; 219 var productImagePath = product.DefaultImage.GetFileViewModel().PathUrlEncoded; 220 var imagePath = $"/Admin/Public/GetImage.ashx?format=webp&width=300&amp;height=300&amp;crop=0&amp;Compression=75&amp;FillCanvas=true&amp;DoNotUpscale=true&amp;image={productImagePath}"; 221 var productLink = product.GetProductLink(shopPageId, false); 222 var collectionData = Convert.ToString(product.ProductFields["ProductNumbersInCollection"].Value); 223 bool hasVariants = product.VariantGroups().Count > 0; 224 var scalePath = string.Empty; 225226 if (isCollection) 227 { 228 scalePath = "/Admin/Public/GetImage.ashx?width=300&amp;height=300&amp;crop=0&amp;Compression=75&amp;FillCanvas=true&amp;DoNotUpscale=true&amp;image="; 229 } 230 else 231 { 232 scalePath = "/Admin/Public/GetImage.ashx?width=300&amp;height=300&amp;crop=5&amp;Compression=75&amp;FillCanvas=true&amp;DoNotUpscale=true&amp;image="; 233 } 234235 if ((isCollection || hasVariants) && !string.IsNullOrWhiteSpace(collectionData) && !onlyShowVariants && !isSearch) 236 { 237 //gridCSS = "grid__col-lg-2 grid__col-md-2 grid__col-sm-2 grid__col-xs-6 product-list__grid-item image-hover--zoom dw-mod"; 238 var randomProduct = GetRandomProduct(collectionData, rendera_4, productName); 239240 productLink = $"/Default.aspx?ID={shopPageId}&GroupId={groupId}&ProductId={productId}&VariantID={randomProduct.VariantId}"; 241 imagePath = $"{scalePath}{randomProduct.Image}"; 242 //imagePath = $"/Admin/Public/GetImage.ashx?format=webp&width=300&amp;height=300&amp;crop=0&amp;Compression=75&amp;FillCanvas=true&amp;DoNotUpscale=true&amp;image={randomProduct.Image}"; 243 } 244 else 245 { 246 imagePath = $"{scalePath}{productImagePath}"; 247 //imagePath = $"/Admin/Public/GetImage.ashx?format=webp&width=300&amp;height=300&amp;crop=0&amp;Compression=75&amp;FillCanvas=true&amp;DoNotUpscale=true&amp;image={productImagePath}"; 248 productLink = $"/Default.aspx?ID={shopPageId}&GroupId={groupId}&ProductId={productId}"; 249250 if (!string.IsNullOrWhiteSpace(productVariantId)) 251 { 252 productLink += $"&VariantID={productVariantId}"; 253 } 254 } 255256 <div id="Product" class="@gridCSS" data-collection-data="@collectionData"> 257258 <div class="grid__col--auto js-product-scroll-trigger u-no-padding u-full-height" data-params=""> 259 <input type="hidden" name="@productLoopCounter" value="@uniqueId"> 260 <input type="hidden" name="@productLoopId" value="@productId"> 261 <input type="hidden" name="@variantLoopId" value="@productVariantId" id="@variantLoopId"> 262 <input type="hidden" name="@unitLoopName" value="@productUnit" id="@unitLoopId"> 263 <input type="hidden" name="@quantityLoopName" value="1" id="@quantityLoopId"> 264 <div class="grid__cell product-list__grid-item__image dw-mod "> 265 <a href="@productLink" onclick="" title="@productName" class="u-block u-position-relative image-hover__wrapper dw-mod"> 266 <img width="168" height="168" class="grid__cell-img grid__cell-img--centered b-lazy b-loaded" src="@imagePath" alt="@productName"> 267 </a> 268 <div class="favorites favorites--for-grid-view u-pull--right dw-mod"> 269 </div> 270271 </div> 272 <div class="grid__cell product-list__grid-item__price-info dw-mod collection-item "> 273 <a href="@productLink" class="u-color-inherit" onclick="" title="@productName"> 274 <h6 class=" u-bold">@productName</h6> 275 </a> 276277 @if (!isCollection) 278 { 279 <p class="u-margin-top"></p> 280 <div class="item-number dw-mod @displayCss @hideArticleNumberCss ">@Translate("ArtNr", "Art. nr"): @product.Number </div> 281282283 if (Dynamicweb.Frontend.PageView.Current().Device != Dynamicweb.Frontend.Devices.DeviceType.Mobile) 284 { 285 // login to see price 286 bool userLoggedIn = Dynamicweb.Security.UserManagement.User.IsExtranetUserLoggedIn(); 287288 if (userLoggedIn) 289 { 290 <div class="price price--product-list dw-mod">@product.Price.PriceFormatted</div> 291292 } 293 else 294 { 295 <div class="u-ta-left dw-mod @displayCss"> 296 <label for="SignInModalTrigger" class="item-number sign-in-modal-trigger-button" onclick="setTimeout(function () { document.getElementById('LoginUsername').focus() }, 10)"> 297 @Translate("Logga_in_for_pris_och_kop") 298 </label> 299 </div> 300 } 301 } 302 } 303304 </div> 305 <div class="product-list__grid-item__footer dw-mod @displayCss"> 306 <div> 307 <a class="u-no-margin btn btn--secondary dw-mod" title="Visa" id="@cartButtonId" onclick="" href="@productLink">@Translate("View")</a> 308 </div> 309 </div> 310 </div> 311 </div> 312313 } 314315 </div> 316 </div> 317318 <div class="grid"> 319 <div class="grid__col-12 u-no-padding"> 320321 @{ 322323 var nextPageCount = 0; 324 if (Model.CurrentPage < Model.PageCount) 325 { 326 nextPageCount = Model.PageSize + 36; 327 } 328329 var baseUrl = $"{Dynamicweb.Context.Current.Request.Path}?ID={Dynamicweb.Frontend.PageView.Current().ID}&GroupId={Model?.Group?.Id}&pagesize={nextPageCount}"; 330 var filters = string.Empty; 331 var loadMoreUrl = baseUrl; 332333 foreach(var qs in System.Web.HttpContext.Current.Request.QueryString.AllKeys) { 334 if(qs != "ID" && qs.ToLower() != "groupid" && qs.ToLower() != "pagesize") 335 { 336 filters += $"&{qs}={Convert.ToString(System.Web.HttpContext.Current.Request.QueryString[qs])}"; 337338 } 339 } 340341 loadMoreUrl += filters; 342343 if (Model.PageCount > Model.CurrentPage) 344 { 345 <a href="@loadMoreUrl" id="LoadMoreButton" data-filters="@filters" class="btn btn--primary btn--full dw-mod" data-current="1" data-page-size="@Model.PageSize;" data-total="4"> 346 @Translate("Load") 36 @Translate("more") 347 </a> 348 } 349 } 350351 <button type="button" class="btn btn--clean" onclick="window.scroll(0, 0)">@Translate("Return to top")</button> 352 </div> 353 </div> 354 @functions { 355356 private static readonly Random _rnd = new Random(); 357358 public RandomVariant GetRandomProduct(string rawData, bool render_4, string defaultName) 359 { 360361 if (string.IsNullOrWhiteSpace(rawData)) 362 return null; 363364 var variants = (rawData ?? string.Empty) 365 .Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries) 366 .Select(item => item.Split(',')) 367 .Where(parts => parts.Length >= 2) // allow 2 or more 368 .Select(parts => 369 { 370 var safeParts = parts.Length >= 3 371 ? parts 372 : new[] { parts[0], parts[1], defaultName }; // 👈 fallback 373374 return new RandomVariant 375 { 376 ProductId = safeParts[0].Trim(), 377 VariantId = safeParts[1].Trim(), 378 Name = safeParts[2].Trim() 379 }; 380 }) 381 .ToList(); 382383 if (!variants.Any()) 384 return null; 385386 var image_4 = string.Empty; 387388389 var randomVariant = variants[_rnd.Next(variants.Count)]; 390391 if (render_4) 392 { 393 image_4 = "_4"; 394 } 395396 randomVariant.Image = $"/files/images/produktbilder/{randomVariant.ProductId}{image_4}.jpg"; 397398 return randomVariant; 399400 } 401402 public class RandomVariant 403 { 404 public string ProductId { get; set; } 405 public string VariantId { get; set; } 406 public string Name { get; set; } 407 public string Image { get; set; } 408 } 409 }