Error executing template "Designs/Swift/Swift_Email/Paragraph/Swift_EmailProductCatalog.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
at CompiledRazorTemplates.Dynamic.RazorEngine_601f1704b35d41e28c9529c4e34adda0.<>c__DisplayClass4_0.<RenderProduct>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\Zington\ote.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Swift_Email\Paragraph\Swift_EmailProductCatalog.cshtml:line 194
at CompiledRazorTemplates.Dynamic.RazorEngine_601f1704b35d41e28c9529c4e34adda0.Execute() in D:\dynamicweb.net\Solutions\Zington\ote.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Swift_Email\Paragraph\Swift_EmailProductCatalog.cshtml:line 96
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 @functions {
5 private string GetFontStack()
6 {
7 return "font-family:initial,Arial,Helvetica Neue,Helvetica,sans-serif;";
8 }
9
10 private string GetTableReset()
11 {
12 return "border:0;margin:0;outline:0;padding:0;";
13 }
14
15 public Dynamicweb.Frontend.ColorViewModel GetMutedColor(string hex, int percent, double threshold = 0.5)
16 {
17 /// <summary>
18 /// Return a color in either lighter or darker contrast based on the original color luminance.
19 /// </summary>
20 /// <param name="percent">The percent (1-100) to darken or light the color with - higher percentage will give higher contrast</param>
21 /// <param name="threshold">The luminance threshold (0-1). Default is 0.5. 0 is black, 1 is white. Luminance threshold is used to decide wether the returned contrast color should be darker or lighter than the base color</param>
22 /// <returns>A new color viewmodel with the contrasted color in either darker or lighter luminance compared to base color</returns>
23 ///
24 if (threshold > 1)
25 threshold = 1;
26 if (threshold < 0)
27 threshold = 0;
28
29 var color = Dynamicweb.Imaging.Colors.Color.FromHex(hex);
30 var luminance = (0.2126 * color.BaseColor.R) + (0.7152 * color.BaseColor.G) + (0.0722 * color.BaseColor.B);
31 /// == luminance = 0 is black, luminance = 1 is white == //
32 luminance = color.Brightness / 255;
33 if (luminance < threshold)
34 {
35 return new Dynamicweb.Frontend.ColorViewModel() { Hex = color.Lighten(percent).ToHex() };
36 }
37 else
38 {
39 return new Dynamicweb.Frontend.ColorViewModel() { Hex = color.Darken(percent).ToHex() };
40 }
41 }
42 }
43
44 @{
45 string blockType = "productcatalog_block";
46
47 var page = Dynamicweb.Content.Services.Pages.GetPage(Model.PageID);
48 var settings = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(page?.Parent).Item;
49 var blockId = Model.ID;
50 var block = Model.Item;
51
52 var emailContentThemeId = settings.GetRawValueString("EmailContentTheme");
53 var emailContentThemeParagraph = emailContentThemeId != null && emailContentThemeId != string.Empty ? Dynamicweb.Content.Services.Paragraphs.GetParagraph(Dynamicweb.Core.Converter.ToInt32(emailContentThemeId)) : null;
54 var emailContentTheme = emailContentThemeParagraph != null && Dynamicweb.Frontend.ContentViewModelFactory.CreateParagraphInfoViewModel(emailContentThemeParagraph).Item.GetString("CssClassName") != string.Empty ? Dynamicweb.Frontend.ContentViewModelFactory.CreateParagraphInfoViewModel(emailContentThemeParagraph)?.Item : null;
55
56 var rowId = Pageview.CurrentParagraph.GridRowId;
57 var row = Dynamicweb.Content.Services.Grids.GetGridRowById(rowId);
58 var rowItem = Dynamicweb.Content.Services.Items.GetItem(row.ItemType, row.ItemId);
59 var rowThemeId = Dynamicweb.Core.Converter.ToString(rowItem["ColumnBackground"]);
60 var rowThemeParagraph = rowThemeId != null && rowThemeId != string.Empty ? Dynamicweb.Content.Services.Paragraphs.GetParagraph(Dynamicweb.Core.Converter.ToInt32(rowThemeId)) : null;
61 var rowTheme = rowThemeParagraph != null && Dynamicweb.Frontend.ContentViewModelFactory.CreateParagraphInfoViewModel(rowThemeParagraph).Item.GetString("CssClassName") != string.Empty ? Dynamicweb.Frontend.ContentViewModelFactory.CreateParagraphInfoViewModel(rowThemeParagraph)?.Item : null;
62
63 var blockThemeId = block.GetRawValueString("Theme");
64 var blockThemeParagraph = blockThemeId != null && blockThemeId != string.Empty ? Dynamicweb.Content.Services.Paragraphs.GetParagraph(Dynamicweb.Core.Converter.ToInt32(blockThemeId)) : null;
65 var blockTheme = blockThemeParagraph != null && Dynamicweb.Frontend.ContentViewModelFactory.CreateParagraphInfoViewModel(blockThemeParagraph).Item.GetString("CssClassName") != string.Empty ? Dynamicweb.Frontend.ContentViewModelFactory.CreateParagraphInfoViewModel(blockThemeParagraph)?.Item : rowTheme is object ? rowTheme : emailContentTheme;
66
67 string backgroundColor = blockTheme != null ? "background-color: " + blockTheme.GetString("BackgroundColor") + ";" : string.Empty;
68 string foregroundColor = blockTheme != null ? "color:" + blockTheme.GetString("ForegroundColor", "inherit") + ";" : string.Empty;
69
70 string title = block.GetString("Title", string.Empty);
71 int padding = Dynamicweb.Core.Converter.ToInt32(block.GetRawValueString("Padding", "0"));
72 int cellSpacing = 8;
73 string align = block.GetRawValueString("Align", "left");
74 string text = block.GetString("Text", string.Empty);
75 var layoutColumns = Dynamicweb.Core.Converter.ToInt32(block.GetRawValueString("Layout", "2"));
76
77 ProductListViewModel selectedProducts = block?.GetValue("Products") as ProductListViewModel;
78 IList<ProductViewModel> products = selectedProducts?.Products;
79 }
80
81 <table id="@blockId" class="@blockType" align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0pt;mso-table-rspace:0pt;@GetTableReset()color:inherit;width:100%;@(backgroundColor)">
82 <tbody>
83 <tr style="@GetTableReset()">
84 <td style="@GetTableReset()padding:@(padding)px">
85 <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace:0pt;mso-table-rspace:0pt;@GetTableReset()color:inherit;width:100%;">
86 <tbody>
87 @if (products is object && products.Any())
88 {
89 @:<tr style="@GetTableReset()">
90
91 int index = 1;
92 int totalProducts = products.Count();
93 foreach (var product in products)
94 {
95 <td valign="top" style="@GetTableReset()@GetFontStack()">
96 @{ @RenderProduct(product, blockTheme, align) }
97 </td>
98
99 if (index % layoutColumns == 0 && !(index == totalProducts))
100 {
101 @:</tr>
102 @:<tr style="@GetTableReset()">
103 @:<td style="@GetTableReset()" colspan="100%" height="@(cellSpacing * 4)"> </td>
104 @:</tr>
105 @:<tr style="@GetTableReset()">
106 }
107 else
108 {
109 if(!(index == totalProducts))
110 {
111 @:<td width="@(cellSpacing)" style="@GetTableReset()"> </td>
112 }
113 }
114
115 index++;
116 }
117 @:</tr>
118 }
119 else
120 {
121 if (Pageview.IsVisualEditorMode)
122 {
123 <tr style="@GetTableReset()@GetFontStack()">
124 <td style="@(foregroundColor)">@Translate("No products selected")</td>
125 </tr>
126 }
127 }
128 </tbody>
129
130 </table>
131 <!--[if mso]><br/><![endif]-->
132 </td>
133 </tr>
134
135 </tbody>
136 </table>
137
138 @helper RenderImage(ProductViewModel product, Dynamicweb.Frontend.ItemViewModel theme)
139 {
140 int layout = Dynamicweb.Core.Converter.ToInt32(Model.Item.GetRawValueString("Layout", "2"));
141 int padding = Convert.ToInt32(Model.Item.GetRawValueString("Padding", "0"));
142 var imageRatio = Model.Item.GetRawValueString("ImageAspectRatio", "4-3").ToLower();
143
144 var parms = new Dictionary<string, object>();
145 parms.Add("alt", product.Name);
146 parms.Add("columns", layout);
147 parms.Add("gridColumns", Model.GridRowColumnCount);
148 parms.Add("nested", Model.GridRowColumnCount > 1);
149 parms.Add("padding", (padding * 2) + (8 * (layout - 1)));
150 parms.Add("imageRatio", imageRatio);
151
152 if(product.DefaultImage is object)
153 {
154 @RenderPartial("Swift_Email/Components/Image.cshtml", new Dynamicweb.Frontend.FileViewModel() {Name = product.Name, Path = product.DefaultImage.Value }, parms);
155 }
156 }
157
158 @helper RenderProduct(ProductViewModel product, Dynamicweb.Frontend.ItemViewModel theme, string align)
159 {
160 var backgroundColor = theme?.GetColor("BackgroundColor");
161 var foregroundColor = theme?.GetColor("ForegroundColor");
162 var borderColor = theme?.GetColor("BorderColor");
163
164 string link = product.GetProductLink(GetPageIdByNavigationTag("Shop"), false);
165
166 var uri = Dynamicweb.Context.Current.Request.Url;
167 var hostname = uri.Scheme + Uri.SchemeDelimiter + uri.Host;
168
169 bool hideProductPrice = Model.Item?.GetBoolean("HideProductPrice") ?? false;
170 bool hideProductNumber = Model.Item?.GetBoolean("HideProductNumber") ?? false;
171
172 <table style="border-collapse:collapse;table-layout:fixed;@GetTableReset()" cellpadding="0" cellspacing="0" width="100%" role="presentation">
173 <tbody>
174 <tr style="@GetTableReset()">
175 <td style="@GetTableReset()">
176
177 <div align="center" style="font-size:2px;">
178 <a style="text-decoration:none;" href="@link" target="_blank">
179 @{ @RenderImage(product, theme) }
180 </a>
181 </div>
182
183 <table style="border-collapse:collapse;table-layout:fixed;@GetTableReset()" cellpadding="0" cellspacing="0" width="100%" role="presentation">
184 <tbody>
185 <tr style="@GetTableReset()">
186 <td style="@GetTableReset()padding-top:8px;text-align:@align;line-height:18px;font-size:13px;text-decoration:none;color:@foregroundColor;">
187 <a style="text-decoration:none;color:@foregroundColor;@GetTableReset()@GetFontStack()" href="@link" target="_blank">
188 @product.Name
189 </a>
190 </td>
191 </tr>
192
193 @if (!hideProductNumber)
194 {
195 <tr>
196 <td style="@GetTableReset()@GetFontStack()padding-top:8px;line-height:18px;font-size:11px;color:@(GetMutedColor(foregroundColor.Hex, 20));">
197 @product.Number
198 </td>
199 </tr>
200 }
201
202 @if (!hideProductPrice)
203 {
204 <tr>
205 <td style="@GetTableReset()@GetFontStack()padding-top:8px;line-height:13px;font-size:13px;break-inside:avoid;word-break:keep-all;white-space:nowrap;color:@(foregroundColor);">
206 @product.Price.PriceFormatted
207
208 @if (product.Discount.Price > 0)
209 {
210 <span style="line-height:13px;font-size:13px;text-decoration:line-through;break-inside:avoid;word-break:keep-all;white-space:nowrap;color:@(GetMutedColor(foregroundColor.Hex, 20));">@product.PriceBeforeDiscount.PriceFormatted</span>
211 }
212 </td>
213 </tr>
214 }
215 <tr><td height="24" style="padding-top:24px;"></td></tr>
216 </tbody>
217 </table>
218
219 </td>
220 </tr>
221
222 </tbody>
223 </table>
224 }
225
|