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) <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&height=300&crop=0&Compression=75&FillCanvas=true&DoNotUpscale=true&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&height=300&crop=0&Compression=75&FillCanvas=true&DoNotUpscale=true&image=";
229 }
230 else
231 {
232 scalePath = "/Admin/Public/GetImage.ashx?width=300&height=300&crop=5&Compression=75&FillCanvas=true&DoNotUpscale=true&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&height=300&crop=0&Compression=75&FillCanvas=true&DoNotUpscale=true&image={randomProduct.Image}";
243 }
244 else
245 {
246 imagePath = $"{scalePath}{productImagePath}";
247 //imagePath = $"/Admin/Public/GetImage.ashx?format=webp&width=300&height=300&crop=0&Compression=75&FillCanvas=true&DoNotUpscale=true&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 }