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_1a3a58d909b04708929d097fb8045cb7.Execute() in D:\dynamicweb.net\Solutions\Mennt\mennt.cloud.dynamicweb-cms.com\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>
@using Dynamicweb.Ecommerce.ProductCatalog
@{
bool isVisualEditor = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("VisualEdit")) ? Convert.ToBoolean(Dynamicweb.Context.Current.Request.QueryString.Get("VisualEdit")) : false;
ProductViewModel product = new ProductViewModel();
ProductViewModelSettings productSetting = new ProductViewModelSettings
{
LanguageId = Dynamicweb.Ecommerce.Common.Context.LanguageID,
CurrencyCode = Dynamicweb.Ecommerce.Common.Context.Currency.Code,
CountryCode = Dynamicweb.Ecommerce.Common.Context.Country.Code2,
ShopId = Pageview.Area.EcomShopId
};
if (Dynamicweb.Context.Current.Items.Contains("ProductDetails"))
{
product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"];
}
else if (Pageview.Item["DummyProduct"] != null)
{
string dummyProductId = "";
var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page);
ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel();
if (productList.Products != null)
{
foreach (var p in productList.Products) { dummyProductId = p.Id; }
ProductViewModel dummyProduct = dummyProductId != "" ? ViewModelFactory.CreateView(productSetting, dummyProductId) : new ProductViewModel();
product = dummyProduct;
}
else
{
product = ViewModelFactory.CreateView(productSetting, Dynamicweb.Ecommerce.Services.Products.GetLastActiveProducts(1, Dynamicweb.Ecommerce.Common.Context.LanguageID, false).FirstOrDefault().Id);
}
}
else if (Pageview.Item["DummyProduct"] == null)
{
product = ViewModelFactory.CreateView(productSetting, Dynamicweb.Ecommerce.Services.Products.GetLastActiveProducts(1, Dynamicweb.Ecommerce.Common.Context.LanguageID, false).FirstOrDefault().Id);
}
}
@if (product?.Id != null)
{
IEnumerable<string> selectedDisplayGroupIds = Model.Item.GetRawValueString("DisplayGroups").Split(',').ToList();
List<CategoryFieldViewModel> displayGroups = new List<CategoryFieldViewModel>();
foreach (var selection in selectedDisplayGroupIds)
{
foreach (CategoryFieldViewModel group in product.FieldDisplayGroups.Values)
{
if (selection == group.Id)
{
int fieldsWithNoValueOrZero = 0;
foreach (var field in group.Fields)
{
if (string.IsNullOrEmpty(field.Value.Value.ToString()))
{
fieldsWithNoValueOrZero++;
}
}
if (fieldsWithNoValueOrZero != group.Fields.Count)
{
displayGroups.Add(group);
}
}
}
}
bool showProductFields = Model.Item.GetBoolean("ProductFields");
bool hideTitle = Model.Item.GetBoolean("HideTitle");
string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : "";
string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "display-4");
string contentPadding = Model.Item.GetRawValueString("ContentPadding", "");
contentPadding = contentPadding == "none" ? string.Empty : contentPadding;
contentPadding = contentPadding == "small" ? " p-2 p-md-3" : contentPadding;
contentPadding = contentPadding == "large" ? " p-4 p-md-5" : contentPadding;
string layout = Model.Item.GetRawValueString("Layout", "list");
string size = Model.Item.GetRawValueString("Size", "full");
string gaps = size == "full" ? " gap-4" : " gap-2";
if (Pageview.IsVisualEditorMode && displayGroups.Count() == 0)
{
product.ProductFields.Clear();
product.ProductFields.Add(Translate("Width"), new FieldValueViewModel { Name = Translate("Width"), Value = "99cm" });
product.ProductFields.Add(Translate("Height"), new FieldValueViewModel { Name = Translate("Height"), Value = "195cm" });
showProductFields = true;
}
if (layout == "commas")
{
gaps = size == "full" ? " gap-4" : " gap-2";
}
<div class="h-100@(gaps)@(theme)@(contentPadding) item_@Model.Item.SystemName.ToLower()">
<div class="grid">
@if ((product.ProductFields != null && Model.Item.GetBoolean("ProductFields")) || (product.ProductCategories != null && Model.Item.GetBoolean("CategoryFields")) || (displayGroups.Count != 0)) {
if (!hideTitle)
{
<h2 class="g-col-12 @titleFontSize">@Model.Item.GetString("Title")</h2>
}
}
@if (displayGroups.Count != 0)
{
if (layout != "accordion")
{
foreach (var group in displayGroups)
{
bool hideHeader = Model.Item.GetBoolean("HideGroupHeaders");
if (!hideHeader) {
<h4 class="g-col-12 h4 mb-0">@group.Name</h4>
}
{ @RenderFieldsFromList(group.Fields, layout) }
}
}
else
{
<div class="g-col-12">
<div class="accordion accordion-flush w-100" id="Specifications_@Model.ID">
@foreach (var group in displayGroups)
{
<div class="accordion-item">
<h2 class="accordion-header" id="SpecificationHeading_@group.Id">
<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">
@group.Name
</button>
</h2>
<div id="SpecificationItem_@group.Id" class="accordion-collapse collapse" aria-labelledby="SpecificationHeading_@group.Id" data-bs-parent="#Specifications_@Model.ID">
<div class="accordion-body">
@{ @RenderFieldsFromList(group.Fields, "list") }
</div>
</div>
</div>
}
</div>
</div>
}
}
@if (product.ProductFields != null && showProductFields)
{
if (product.ProductFields.Count > 0)
{
if (layout != "accordion")
{
{@RenderFieldsFromList(product.ProductFields, layout) }
}
else
{
<div class="g-col-12">
<div class="accordion accordion-flush w-100" id="Specifications_@Model.ID">
<div class="accordion-item">
<h2 class="accordion-header" id="SpecificationHeading_@Model.ID">
<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">
@Translate("Specifications")
</button>
</h2>
<div id="SpecificationItem_@Model.ID" class="accordion-collapse" aria-labelledby="SpecificationHeading_@Model.ID" data-bs-parent="#Specifications_@Model.ID">
<div class="accordion-body">
@{ @RenderFieldsFromList(product.ProductFields, "List") }
</div>
</div>
</div>
</div>
</div>
}
}
}
@if (product.ProductCategories != null && Model.Item.GetBoolean("CategoryFields"))
{
if (product.ProductCategories.Count > 0)
{
if (layout != "accordion")
{
foreach (var group in product.ProductCategories)
{
CategoryFieldViewModel category = group.Value;
bool hideHeader = Model.Item.GetBoolean("HideGroupHeaders");
if (!hideHeader) {
<h4 class="g-col-12 h4 mb-0">@group.Value.Name</h4>
}
{ @RenderFieldsFromList(category.Fields, layout) }
}
}
else
{
<div class="g-col-12">
<div class="accordion accordion-flush w-100" id="Specifications_@Model.ID">
@foreach (var group in product.ProductCategories)
{
CategoryFieldViewModel category = group.Value;
<div class="accordion-item">
<h2 class="accordion-header" id="SpecificationHeading_@group.Value.Id">
<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">
@group.Value.Name
</button>
</h2>
<div id="SpecificationItem_@group.Value.Id" class="accordion-collapse" aria-labelledby="SpecificationHeading_@group.Value.Id" data-bs-parent="#Specifications_@Model.ID">
<div class="accordion-body">
@{ @RenderFieldsFromList(category.Fields, "list") }
</div>
</div>
</div>
}
</div>
</div>
}
}
}
</div>
</div>
}
else if (Pageview.IsVisualEditorMode)
{
<div class="alert alert-warning m-0">@Translate("No products available")</div>
}
@helper RenderFieldsFromList(Dictionary<string, FieldValueViewModel> fields, string layout)
{
string size = Model.Item.GetRawValueString("Size", "full");
string gaps = size != "full" ? " gap-1" : string.Empty;
bool hideFieldLabels = Model.Item.GetBoolean("HideFieldLabels");
bool hideFieldsWithZeroValue = Model.Item.GetBoolean("HideFieldsWithZeroValue");
if (layout == "columns") {
<div class="g-col-12">
<div class="grid@(gaps)">
@foreach (var field in fields)
{
{@RenderField(field.Value, layout)}
}
</div>
</div>
}
if (layout == "list") {
<div class="g-col-12">
<dl class="grid@(gaps)">
@foreach (var field in fields)
{
{@RenderField(field.Value, layout)}
}
</dl>
</div>
}
if (layout == "table")
{
string tableSize = size == "full" ? "" : " table-sm";
<div class="g-col-12">
<table class="table table-striped@(tableSize)">
@foreach (var field in fields)
{
{@RenderField(field.Value, layout)}
}
</table>
</div>
}
if (layout == "bullets")
{
string listSize = size == "full" ? "" : "m-0 p-0 lh-1 fs-7 opacity-75";
string listStyle = size == "full" ? "" : "style=\"list-style-position: inside\"";
<div class="g-col-12">
<ul class="@listSize" @listStyle>
@foreach (var field in fields)
{
{@RenderField(field.Value, layout)}
}
</ul>
</div>
}
if (layout == "commas")
{
List<string> featuresList = new List<string>();
foreach (var field in fields)
{
string firstListItemValue = string.Empty; //Hack to support field type providers with a single value
if (field.Value?.Value != null)
{
if (field.Value.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>))
{
System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value.Value as System.Collections.Generic.List<FieldOptionValueViewModel>;
//Hack to support field type providers with a single value
if (values.FirstOrDefault() != null)
{
firstListItemValue = values.FirstOrDefault().Value;
}
}
}
if (!hideFieldsWithZeroValue || (firstListItemValue != "0" && firstListItemValue != "0.0" && field.Value.Value.ToString() != "0" && field.Value.Value.ToString() != "0.0"))
{
if (field.Value.Value is object && !string.IsNullOrEmpty(field.Value.Value.ToString()))
{
if (field.Value.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>))
{
List<string> options = new List<string>();
foreach (FieldOptionValueViewModel option in field.Value.Value as System.Collections.Generic.List<FieldOptionValueViewModel>)
{
if (!string.IsNullOrWhiteSpace(option.Value))
{
if (option.Value.ToString().Contains("#") && (Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour")))
{
string colorSpan = "<span class=\"colorbox-sm\" style=\"background-color: " + option.Value + "\"></span>";
options.Add(colorSpan);
}
else if (!string.IsNullOrEmpty(option.Value))
{
options.Add(option.Name);
}
}
}
string optionsString = (string.Join(", ", options.Select(x => x.ToString()).ToArray()));
if ((Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour")))
{
optionsString = (string.Join(" ", options.Select(x => x.ToString()).ToArray()));
}
if (!string.IsNullOrEmpty(optionsString))
{
if (!hideFieldLabels)
{
featuresList.Add(field.Value.Name + ": " + optionsString);
}
else
{
featuresList.Add(optionsString);
}
}
}
else
{
if (!string.IsNullOrWhiteSpace(field.Value.Value.ToString()))
{
if (field.Value.Value.ToString().Contains("#") && (Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour")))
{
string colorSpan = "<span class=\"colorbox-sm\" style=\"background-color: " + field.Value.Value + "\"></span>";
if (!hideFieldLabels)
{
featuresList.Add(field.Value.Name + ": " + colorSpan);
}
else
{
featuresList.Add(colorSpan);
}
}
else
{
if (!hideFieldLabels)
{
featuresList.Add(field.Value.Name + ": " + field.Value.Value.ToString());
}
else
{
featuresList.Add(field.Value.Value.ToString());
}
}
}
}
}
}
}
string featuresString = (string.Join(", ", featuresList.Select(x => x.ToString()).ToArray()));
<div class="g-col-12 opacity-75 fs-7">@featuresString</div>
}
}
@helper RenderField(FieldValueViewModel field, string layout)
{
string size = Model.Item.GetRawValueString("Size", "full");
string fieldValue = field?.Value != null ? field.Value.ToString() : "";
bool hideFieldLabels = Model.Item.GetBoolean("HideFieldLabels");
bool noValues = false;
string firstListItemValue = string.Empty; //Hack to support field type providers with a single value
bool hideFieldsWithZeroValue = Model.Item.GetBoolean("HideFieldsWithZeroValue");
if (!string.IsNullOrEmpty(fieldValue))
{
if (field.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>))
{
System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>;
noValues = values.Count > 0 ? false : true;
//Hack to support field type providers with a single value
if (values.FirstOrDefault() != null)
{
firstListItemValue = values.FirstOrDefault().Value;
}
}
}
if (!string.IsNullOrEmpty(fieldValue) && noValues == false)
{
if (!hideFieldsWithZeroValue || (firstListItemValue != "0" && firstListItemValue != "0.0" && field.Value.ToString() != "0" && field.Value.ToString() != "0.0"))
{
if (layout == "columns")
{
<div class="grid g-col-6 g-col-lg-4 gap-1">
@if (!hideFieldLabels)
{
<dt class="g-col-12 g-col-lg-4">@field.Name</dt>
}
<dd class="g-col-12 g-col-lg-8 mb-0 text-break">
@{ @RenderFieldValue(field) }
</dd>
</div>
}
if (layout == "list")
{
if (!hideFieldLabels)
{
<dt class="g-col-4">@field.Name</dt>
}
<dd class="g-col-8 mb-0 text-break">
@{ @RenderFieldValue(field) }
</dd>
}
if (layout == "table")
{
<tr>
@if (!hideFieldLabels)
{
<th class="w-25 w-lg-50" scope="row">@field.Name</th>
}
<td class="text-break">
@{ @RenderFieldValue(field) }
</td>
</tr>
}
if (layout == "bullets")
{
<li>
@if (!hideFieldLabels)
{
<strong>@field.Name</strong>
}
<span>
@{ @RenderFieldValue(field) }
</span>
</li>
}
}
}
}
@helper RenderFieldValue(FieldValueViewModel field)
{
string fieldValue = field?.Value != null ? field.Value.ToString() : "";
bool isLink = field?.Type == "Link";
bool isColor = false;
bool isBrandName = field?.SystemName == "Brand_name";
fieldValue = fieldValue == "False" ? Translate("No") : fieldValue;
fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue;
if (field.Value.GetType() == typeof(System.Collections.Generic.List<Dynamicweb.Ecommerce.ProductCatalog.FieldOptionValueViewModel>))
{
int valueCount = 0;
System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>;
int totalValues = values.Count;
foreach (FieldOptionValueViewModel option in values)
{
if (!string.IsNullOrEmpty(option.Value))
{
if (option.Value.Substring(0, 1) == "#")
{
isColor = true;
}
}
if (!isColor)
{
@option.Name
}
else
{
<span class="colorbox-sm" style="background-color: @option.Value" title="@option.Name"></span>
}
if (valueCount != totalValues && valueCount < (totalValues - 1))
{
if (isColor)
{
<text> </text>
}
else
{
<text>, </text>
}
}
valueCount++;
}
}
else
{
if (fieldValue.Substring(0, 1) == "#")
{
isColor = true;
}
if (!isColor)
{
if (isLink)
{
string linktTitle = !fieldValue.Contains("aspx") ? fieldValue : Translate("Go to link");
string target = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && fieldValue.Contains("http") ? "target=\"_blank\"" : string.Empty;
string rel = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && fieldValue.Contains("http") ? "rel=\"noopener\"" : string.Empty;
<a href="@field.Value" title="@field.Name" @target @rel>@linktTitle</a>
}
else if (isBrandName)
{
<span itemprop="brand" itemtype="https://schema.org/Brand" itemscope>
<span itemprop="name">@fieldValue</span>
</span>
}
else
{
@fieldValue
}
}
else
{
<span class="colorbox-sm" style="background-color: @fieldValue" title="@fieldValue"></span>
}
}
}