| 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_23d3bac100334412afe77a4c10ef9dc7.<>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_23d3bac100334412afe77a4c10ef9dc7.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     
 |