Error executing template "Designs/Swift/Paragraph/Swift_ProductSpecification.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
at CompiledRazorTemplates.Dynamic.RazorEngine_cae6462a9ba64c9e9aed38cea404b514.Execute() in H:\Solutions\Hamonoya\Files\Templates\Designs\Swift\Paragraph\Swift_ProductSpecification.cshtml:line 35
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
4 @{
5 bool isVisualEditor = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("VisualEdit")) ? Convert.ToBoolean(Dynamicweb.Context.Current.Request.QueryString.Get("VisualEdit")) : false;
6
7 ProductViewModel product = new ProductViewModel();
8
9 ProductViewModelSettings productSetting = new ProductViewModelSettings
10 {
11 LanguageId = Dynamicweb.Ecommerce.Common.Context.LanguageID,
12 CurrencyCode = Dynamicweb.Ecommerce.Common.Context.Currency.Code,
13 CountryCode = Dynamicweb.Ecommerce.Common.Context.Country.Code2,
14 ShopId = Pageview.Area.EcomShopId
15 };
16
17 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails"))
18 {
19 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"];
20 }
21 else if (Pageview.Item["DummyProduct"] != null)
22 {
23
24 string dummyProductId = "";
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 if (productList.Products != null)
28 {
29 foreach (var p in productList.Products) { dummyProductId = p.Id; }
30 ProductViewModel dummyProduct = dummyProductId != "" ? ViewModelFactory.CreateView(productSetting, dummyProductId) : new ProductViewModel();
31 product = dummyProduct;
32 }
33 else
34 {
35 product = ViewModelFactory.CreateView(productSetting, Dynamicweb.Ecommerce.Services.Products.GetLastActiveProducts(1, Dynamicweb.Ecommerce.Common.Context.LanguageID, false).FirstOrDefault().Id);
36 }
37 }
38 else if (Pageview.Item["DummyProduct"] == null)
39 {
40 product = ViewModelFactory.CreateView(productSetting, Dynamicweb.Ecommerce.Services.Products.GetLastActiveProducts(1, Dynamicweb.Ecommerce.Common.Context.LanguageID, false).FirstOrDefault().Id);
41 }
42 }
43
44 @if (product?.Id != null)
45 {
46 IEnumerable<string> selectedDisplayGroupIds = Model.Item.GetRawValueString("DisplayGroups").Split(',').ToList();
47 List<CategoryFieldViewModel> displayGroups = new List<CategoryFieldViewModel>();
48
49 foreach (var selection in selectedDisplayGroupIds)
50 {
51 foreach (CategoryFieldViewModel group in product.FieldDisplayGroups.Values)
52 {
53 if (selection == group.Id)
54 {
55 int fieldsWithNoValueOrZero = 0;
56
57 foreach (var field in group.Fields)
58 {
59 if (string.IsNullOrEmpty(field.Value.Value.ToString()))
60 {
61 fieldsWithNoValueOrZero++;
62 }
63 }
64
65 if (fieldsWithNoValueOrZero != group.Fields.Count)
66 {
67 displayGroups.Add(group);
68 }
69 }
70 }
71 }
72
73 bool showProductFields = Model.Item.GetBoolean("ProductFields");
74
75 bool hideTitle = Model.Item.GetBoolean("HideTitle");
76
77 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : "";
78
79 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "display-4");
80
81 string contentPadding = Model.Item.GetRawValueString("ContentPadding", "");
82 contentPadding = contentPadding == "none" ? string.Empty : contentPadding;
83 contentPadding = contentPadding == "small" ? " p-2 p-md-3" : contentPadding;
84 contentPadding = contentPadding == "large" ? " p-4 p-md-5" : contentPadding;
85
86 string layout = Model.Item.GetRawValueString("Layout", "list");
87 string size = Model.Item.GetRawValueString("Size", "full");
88 string gaps = size == "full" ? " gap-4" : " gap-2";
89
90
91 if (Pageview.IsVisualEditorMode && displayGroups.Count() == 0)
92 {
93 product.ProductFields.Clear();
94 product.ProductFields.Add(Translate("Width"), new FieldValueViewModel { Name = Translate("Width"), Value = "99cm" });
95 product.ProductFields.Add(Translate("Height"), new FieldValueViewModel { Name = Translate("Height"), Value = "195cm" });
96 showProductFields = true;
97 }
98
99 if (layout == "commas")
100 {
101 gaps = size == "full" ? " gap-4" : " gap-2";
102
103 }
104
105 <div class="h-100@(gaps)@(theme)@(contentPadding) item_@Model.Item.SystemName.ToLower()">
106 <div class="grid">
107 @if ((product.ProductFields != null && Model.Item.GetBoolean("ProductFields")) || (product.ProductCategories != null && Model.Item.GetBoolean("CategoryFields")) || (displayGroups.Count != 0)) {
108 if (!hideTitle)
109 {
110 <h2 class="g-col-12 @titleFontSize">@Model.Item.GetString("Title")</h2>
111 }
112 }
113
114 @if (displayGroups.Count != 0)
115 {
116 if (layout != "accordion")
117 {
118 foreach (var group in displayGroups)
119 {
120 bool hideHeader = Model.Item.GetBoolean("HideGroupHeaders");
121
122 if (!hideHeader) {
123 <h4 class="g-col-12 h4 mb-0">@group.Name</h4>
124 }
125
126 { @RenderFieldsFromList(group.Fields, layout) }
127
128 }
129 }
130 else
131 {
132 <div class="g-col-12">
133 <div class="accordion accordion-flush w-100" id="Specifications_@Model.ID">
134 @foreach (var group in displayGroups)
135 {
136 <div class="accordion-item">
137 <h2 class="accordion-header" id="SpecificationHeading_@group.Id">
138 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@group.Id" aria-expanded="false" aria-controls="SpecificationItem_@group.Id">
139 @group.Name
140 </button>
141 </h2>
142 <div id="SpecificationItem_@group.Id" class="accordion-collapse collapse" aria-labelledby="SpecificationHeading_@group.Id" data-bs-parent="#Specifications_@Model.ID">
143 <div class="accordion-body">
144 @{ @RenderFieldsFromList(group.Fields, "list") }
145 </div>
146 </div>
147 </div>
148 }
149 </div>
150 </div>
151 }
152 }
153
154 @if (product.ProductFields != null && showProductFields)
155 {
156 if (product.ProductFields.Count > 0)
157 {
158 if (layout != "accordion")
159 {
160 {@RenderFieldsFromList(product.ProductFields, layout) }
161 }
162 else
163 {
164 <div class="g-col-12">
165 <div class="accordion accordion-flush w-100" id="Specifications_@Model.ID">
166 <div class="accordion-item">
167 <h2 class="accordion-header" id="SpecificationHeading_@Model.ID">
168 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@Model.ID" aria-expanded="false" aria-controls="SpecificationItem_@Model.ID">
169 @Translate("Specifications")
170 </button>
171 </h2>
172 <div id="SpecificationItem_@Model.ID" class="accordion-collapse" aria-labelledby="SpecificationHeading_@Model.ID" data-bs-parent="#Specifications_@Model.ID">
173 <div class="accordion-body">
174 @{ @RenderFieldsFromList(product.ProductFields, "List") }
175 </div>
176 </div>
177 </div>
178 </div>
179 </div>
180 }
181 }
182 }
183
184 @if (product.ProductCategories != null && Model.Item.GetBoolean("CategoryFields"))
185 {
186 if (product.ProductCategories.Count > 0)
187 {
188 if (layout != "accordion")
189 {
190 foreach (var group in product.ProductCategories)
191 {
192 CategoryFieldViewModel category = group.Value;
193 bool hideHeader = Model.Item.GetBoolean("HideGroupHeaders");
194
195 if (!hideHeader) {
196 <h4 class="g-col-12 h4 mb-0">@group.Value.Name</h4>
197 }
198
199 { @RenderFieldsFromList(category.Fields, layout) }
200 }
201 }
202 else
203 {
204 <div class="g-col-12">
205 <div class="accordion accordion-flush w-100" id="Specifications_@Model.ID">
206 @foreach (var group in product.ProductCategories)
207 {
208 CategoryFieldViewModel category = group.Value;
209
210 <div class="accordion-item">
211 <h2 class="accordion-header" id="SpecificationHeading_@group.Value.Id">
212 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@group.Value.Id" aria-expanded="false" aria-controls="SpecificationItem_@group.Value.Id">
213 @group.Value.Name
214 </button>
215 </h2>
216 <div id="SpecificationItem_@group.Value.Id" class="accordion-collapse" aria-labelledby="SpecificationHeading_@group.Value.Id" data-bs-parent="#Specifications_@Model.ID">
217 <div class="accordion-body">
218 @{ @RenderFieldsFromList(category.Fields, "list") }
219 </div>
220 </div>
221 </div>
222 }
223 </div>
224 </div>
225 }
226 }
227 }
228 </div>
229 </div>
230 }
231 else if (Pageview.IsVisualEditorMode)
232 {
233 <div class="alert alert-warning m-0">@Translate("No products available")</div>
234 }
235
236 @helper RenderFieldsFromList(Dictionary<string, FieldValueViewModel> fields, string layout)
237 {
238 string size = Model.Item.GetRawValueString("Size", "full");
239 string gaps = size != "full" ? " gap-1" : string.Empty;
240 bool hideFieldLabels = Model.Item.GetBoolean("HideFieldLabels");
241 bool hideFieldsWithZeroValue = Model.Item.GetBoolean("HideFieldsWithZeroValue");
242
243 if (layout == "columns") {
244 <div class="g-col-12">
245 <div class="grid@(gaps)">
246 @foreach (var field in fields)
247 {
248 {@RenderField(field.Value, layout)}
249 }
250 </div>
251 </div>
252 }
253 if (layout == "list") {
254 <div class="g-col-12">
255 <dl class="grid@(gaps)">
256 @foreach (var field in fields)
257 {
258 {@RenderField(field.Value, layout)}
259 }
260 </dl>
261 </div>
262 }
263 if (layout == "table")
264 {
265 string tableSize = size == "full" ? "" : " table-sm";
266 <div class="g-col-12">
267 <table class="table table-striped@(tableSize)">
268 @foreach (var field in fields)
269 {
270 {@RenderField(field.Value, layout)}
271 }
272 </table>
273 </div>
274 }
275 if (layout == "bullets")
276 {
277 string listSize = size == "full" ? "" : "m-0 p-0 lh-1 fs-7 opacity-75";
278 string listStyle = size == "full" ? "" : "style=\"list-style-position: inside\"";
279 <div class="g-col-12">
280 <ul class="@listSize" @listStyle>
281 @foreach (var field in fields)
282 {
283 {@RenderField(field.Value, layout)}
284 }
285 </ul>
286 </div>
287 }
288 if (layout == "commas")
289 {
290 List<string> featuresList = new List<string>();
291
292 foreach (var field in fields)
293 {
294 string firstListItemValue = string.Empty; //Hack to support field type providers with a single value
295
296 if (field.Value?.Value != null)
297 {
298 if (field.Value.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>))
299 {
300 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value.Value as System.Collections.Generic.List<FieldOptionValueViewModel>;
301
302 //Hack to support field type providers with a single value
303 if (values.FirstOrDefault() != null)
304 {
305 firstListItemValue = values.FirstOrDefault().Value;
306 }
307 }
308 }
309
310 if (!hideFieldsWithZeroValue || (firstListItemValue != "0" && firstListItemValue != "0.0" && field.Value.Value.ToString() != "0" && field.Value.Value.ToString() != "0.0"))
311 {
312 if (field.Value.Value is object && !string.IsNullOrEmpty(field.Value.Value.ToString()))
313 {
314 if (field.Value.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>))
315 {
316 List<string> options = new List<string>();
317 foreach (FieldOptionValueViewModel option in field.Value.Value as System.Collections.Generic.List<FieldOptionValueViewModel>)
318 {
319 if (!string.IsNullOrWhiteSpace(option.Value))
320 {
321 if (option.Value.ToString().Contains("#") && (Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour")))
322 {
323 string colorSpan = "<span class=\"colorbox-sm\" style=\"background-color: " + option.Value + "\"></span>";
324 options.Add(colorSpan);
325 }
326 else if (!string.IsNullOrEmpty(option.Value))
327 {
328 options.Add(option.Name);
329 }
330 }
331 }
332 string optionsString = (string.Join(", ", options.Select(x => x.ToString()).ToArray()));
333 if ((Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour")))
334 {
335 optionsString = (string.Join(" ", options.Select(x => x.ToString()).ToArray()));
336 }
337
338 if (!string.IsNullOrEmpty(optionsString))
339 {
340 if (!hideFieldLabels)
341 {
342 featuresList.Add(field.Value.Name + ": " + optionsString);
343 }
344 else
345 {
346 featuresList.Add(optionsString);
347 }
348 }
349 }
350 else
351 {
352 if (!string.IsNullOrWhiteSpace(field.Value.Value.ToString()))
353 {
354 if (field.Value.Value.ToString().Contains("#") && (Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour")))
355 {
356 string colorSpan = "<span class=\"colorbox-sm\" style=\"background-color: " + field.Value.Value + "\"></span>";
357
358 if (!hideFieldLabels)
359 {
360 featuresList.Add(field.Value.Name + ": " + colorSpan);
361 }
362 else
363 {
364 featuresList.Add(colorSpan);
365 }
366 }
367 else
368 {
369 if (!hideFieldLabels)
370 {
371 featuresList.Add(field.Value.Name + ": " + field.Value.Value.ToString());
372 }
373 else
374 {
375 featuresList.Add(field.Value.Value.ToString());
376 }
377 }
378 }
379 }
380 }
381 }
382 }
383
384 string featuresString = (string.Join(", ", featuresList.Select(x => x.ToString()).ToArray()));
385
386 <div class="g-col-12 opacity-75 fs-7">@featuresString</div>
387 }
388 }
389
390 @helper RenderField(FieldValueViewModel field, string layout)
391 {
392 string size = Model.Item.GetRawValueString("Size", "full");
393 string fieldValue = field?.Value != null ? field.Value.ToString() : "";
394 bool hideFieldLabels = Model.Item.GetBoolean("HideFieldLabels");
395 bool noValues = false;
396 string firstListItemValue = string.Empty; //Hack to support field type providers with a single value
397 bool hideFieldsWithZeroValue = Model.Item.GetBoolean("HideFieldsWithZeroValue");
398
399 if (!string.IsNullOrEmpty(fieldValue))
400 {
401 if (field.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>))
402 {
403 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>;
404 noValues = values.Count > 0 ? false : true;
405
406 //Hack to support field type providers with a single value
407 if (values.FirstOrDefault() != null)
408 {
409 firstListItemValue = values.FirstOrDefault().Value;
410 }
411 }
412 }
413
414 if (!string.IsNullOrEmpty(fieldValue) && noValues == false)
415 {
416 if (!hideFieldsWithZeroValue || (firstListItemValue != "0" && firstListItemValue != "0.0" && field.Value.ToString() != "0" && field.Value.ToString() != "0.0"))
417 {
418 if (layout == "columns")
419 {
420
421 <div class="grid g-col-6 g-col-lg-4 gap-1">
422 @if (!hideFieldLabels)
423 {
424 <dt class="g-col-12 g-col-lg-4">@field.Name</dt>
425 }
426 <dd class="g-col-12 g-col-lg-8 mb-0 text-break">
427 @{ @RenderFieldValue(field) }
428 </dd>
429 </div>
430 }
431 if (layout == "list")
432 {
433 if (!hideFieldLabels)
434 {
435 <dt class="g-col-4">@field.Name</dt>
436 }
437 <dd class="g-col-8 mb-0 text-break">
438 @{ @RenderFieldValue(field) }
439 </dd>
440 }
441 if (layout == "table")
442 {
443 <tr>
444 @if (!hideFieldLabels)
445 {
446 <th class="w-25 w-lg-50" scope="row">@field.Name</th>
447 }
448 <td class="text-break">
449 @{ @RenderFieldValue(field) }
450 </td>
451 </tr>
452 }
453 if (layout == "bullets")
454 {
455 <li>
456 @if (!hideFieldLabels)
457 {
458 <strong>@field.Name</strong>
459 }
460 <span>
461 @{ @RenderFieldValue(field) }
462 </span>
463 </li>
464 }
465 }
466 }
467 }
468
469 @helper RenderFieldValue(FieldValueViewModel field)
470 {
471 string fieldValue = field?.Value != null ? field.Value.ToString() : "";
472
473 bool isLink = field?.Type == "Link";
474 bool isColor = false;
475 bool isBrandName = field?.SystemName == "Brand_name";
476
477 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue;
478 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue;
479
480
481 if (field.Value.GetType() == typeof(System.Collections.Generic.List<Dynamicweb.Ecommerce.ProductCatalog.FieldOptionValueViewModel>))
482 {
483 int valueCount = 0;
484 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>;
485 int totalValues = values.Count;
486
487 foreach (FieldOptionValueViewModel option in values)
488 {
489 if (!string.IsNullOrEmpty(option.Value))
490 {
491 if (option.Value.Substring(0, 1) == "#")
492 {
493 isColor = true;
494 }
495 }
496
497 if (!isColor)
498 {
499 @option.Name
500 }
501 else
502 {
503 <span class="colorbox-sm" style="background-color: @option.Value" title="@option.Name"></span>
504 }
505
506 if (valueCount != totalValues && valueCount < (totalValues - 1))
507 {
508 if (isColor)
509 {
510 <text> </text>
511 }
512 else
513 {
514 <text>, </text>
515 }
516 }
517 valueCount++;
518 }
519 }
520 else
521 {
522 if (fieldValue.Substring(0, 1) == "#")
523 {
524 isColor = true;
525 }
526
527 if (!isColor)
528 {
529 if (isLink)
530 {
531 string linktTitle = !fieldValue.Contains("aspx") ? fieldValue : Translate("Go to link");
532 string target = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && fieldValue.Contains("http") ? "target=\"_blank\"" : string.Empty;
533 string rel = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && fieldValue.Contains("http") ? "rel=\"noopener\"" : string.Empty;
534
535 <a href="@field.Value" title="@field.Name" @target @rel>@linktTitle</a>
536 }
537 else if (isBrandName)
538 {
539 <span itemprop="brand" itemtype="https://schema.org/Brand" itemscope>
540 <span itemprop="name">@fieldValue</span>
541 </span>
542 }
543 else
544 {
545 @fieldValue
546 }
547
548 }
549 else
550 {
551 <span class="colorbox-sm" style="background-color: @fieldValue" title="@fieldValue"></span>
552 }
553 }
554 }
555