Error executing template "Designs/Swift-v2/Paragraph/Swift-v2_ProductGroupGrid.cshtml" System.MissingMethodException: Method not found: 'System.Collections.Generic.IEnumerable`1<Dynamicweb.Ecommerce.Products.Group> Custom.Relewise.Services.ProductGroupRecommendationService.GetProductCategoryRecommendations(System.String, Int32, System.String, System.String, Int32, Int32, Double, Double, Double)'. at CompiledRazorTemplates.Dynamic.RazorEngine_e921f94e205647e1ac2fa96c03b61df6.GetGroups(String type) at CompiledRazorTemplates.Dynamic.RazorEngine_e921f94e205647e1ac2fa96c03b61df6.GetGroups(String type) at CompiledRazorTemplates.Dynamic.RazorEngine_e921f94e205647e1ac2fa96c03b61df6.ExecuteAsync() at RazorEngine.Templating.TemplateBase.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineCore.RunTemplate(ICompiledTemplate template, TextWriter writer, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.DynamicWrapperService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.RunCompile(IRazorEngineService service, String name, 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 RazorEngine.Templating.RazorEngineServiceExtensions.RunCompile(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.RunCompile(IRazorEngineService service, String templateSource, String name, Type modelType, Object model, DynamicViewBag viewBag) 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 3 @using Dynamicweb.Ecommerce.ProductCatalog 4 @using Dynamicweb.Frontend 5 6 @functions 7 { 8 private IList<ProductGroupViewModel> GetGroups(string type) 9 { 10 IList<ProductGroupViewModel> groupList = new List<ProductGroupViewModel> { }; 11 12 if (type == "subgroups") 13 { 14 IList<ProductGroupViewModel> groups = Model.Item.GetValue<IList<ProductGroupViewModel>>("Subgroups"); 15 if (groups != null) 16 { 17 foreach (var group in groups) 18 { 19 var subGroups = Services.ProductGroups.GetSubgroups(Services.ProductGroups.GetGroup(group.Id)); 20 21 foreach (var subGroup in subGroups) 22 { 23 var subGroupViewModel = ViewModelFactory.CreateView(new ProductGroupViewModelSettings(), subGroup); 24 groupList.Add(subGroupViewModel); 25 } 26 } 27 } 28 } 29 30 if (type == "selected-groups") 31 { 32 IList<ProductGroupViewModel> groups = Model.Item.GetValue<IList<ProductGroupViewModel>>("SelectedGroups"); 33 if (groups != null) 34 { 35 foreach (var group in groups) 36 { 37 groupList.Add(group); 38 } 39 } 40 } 41 42 if (type == "subgroups-current") 43 { 44 var currentGroupId = Dynamicweb.Context.Current.Request.QueryString.Get("GroupID"); 45 46 //Custom: Only render groupgrid if productlist is not rendered as groups 47 @if (!string.IsNullOrEmpty(currentGroupId)) 48 { 49 string? searchQuery = Dynamicweb.Context.Current?.Request["q"]; 50 Custom.AVN.Facets.Helpers.ProductGroupHelper.RenderLayouts pageRenderLayout = Custom.AVN.Facets.Helpers.ProductGroupHelper.PageContainerRenderLayout(currentGroupId, Dynamicweb.Ecommerce.Common.Context.LanguageID, !string.IsNullOrEmpty(searchQuery)); 51 @if (pageRenderLayout != Custom.AVN.Facets.Helpers.ProductGroupHelper.RenderLayouts.GroupList) 52 { 53 var currentGroup = Services.ProductGroups.GetGroup(currentGroupId, Dynamicweb.Ecommerce.Common.Context.LanguageID); 54 var groups = currentGroup != null ? Services.ProductGroups.GetSubgroups(currentGroup) : null; 55 if (groups != null) 56 { 57 foreach (var group in groups) 58 { 59 var groupViewModel = ViewModelFactory.CreateView(new ProductGroupViewModelSettings(), group); 60 groupList.Add(groupViewModel); 61 } 62 } 63 } 64 } 65 66 } 67 68 if (type == "relewise") 69 { 70 string recommendationEndpoint = Model.Item.GetRawValueString("CustomRelewiseRecommendationEndpoint"); 71 Custom.Relewise.Services.ProductGroupRecommendationService productGroupRecommendationService = new(); 72 73 foreach (var group in productGroupRecommendationService.GetProductCategoryRecommendations(recommendationEndpoint, PageView.Current().ID, "", "", 8)) 74 { 75 var groupViewModel = ViewModelFactory.CreateView(new ProductGroupViewModelSettings(), group); 76 groupList.Add(groupViewModel); 77 } 78 } 79 80 return groupList; 81 } 82 83 private LinkViewModel GetLink(ProductGroupViewModel group) 84 { 85 string groupId = Dynamicweb.Context.Current.Server.UrlEncode(group.Id); 86 var url = $"Default.aspx?ID={GetPageIdByNavigationTag("Shop")}&GroupID={groupId.Trim()}"; 87 //Custom keep filtration when selecting new group and filters available 88 var keepFiltration = Model.Item.GetBoolean("CustomKeepFiltration"); 89 90 if (keepFiltration) 91 { 92 var excludedParameters = !string.IsNullOrEmpty(Model.Item.GetList("CustomExcludedParameters")?.ToString()) ? Model.Item.GetList("CustomExcludedParameters")?.ToString() : ""; 93 94 var requestQueryString = Dynamicweb.Context.Current?.Request.QueryString; 95 96 if (requestQueryString != null && requestQueryString.HasKeys()) 97 { 98 foreach (var key in requestQueryString.Keys) 99 { 100 var keyStr = key.ToString(); 101 if (Custom.AVN.Facets.Helpers.QueryStringHelper.AlwaysExcludedParameters.Contains(keyStr) || excludedParameters.Contains(keyStr, StringComparison.InvariantCultureIgnoreCase)) continue; 102 103 url += $"&{keyStr}={requestQueryString.Get(keyStr)}"; 104 } 105 } 106 } 107 108 var link = new LinkViewModel() 109 { 110 Url = url, 111 IsExternal = false 112 }; 113 114 return link; 115 } 116 117 private string GetGroupImageMarkup(ProductGroupViewModel group, string imageShape) 118 { 119 string groupImage = Services.ProductGroups.GetGroup(group.Id)?.LargeImage; 120 if (groupImage.StartsWith("/") && !groupImage.StartsWith("/Files", StringComparison.OrdinalIgnoreCase)) 121 { 122 groupImage = $"/Files{groupImage}"; 123 } 124 125 126 string groupImageEncoded = Dynamicweb.Context.Current.Server.UrlEncode(groupImage); 127 string groupImagePath = $"/Admin/Public/GetImage.ashx?width=640&crop=0&image={groupImageEncoded}&format=webp"; 128 //Custom image fill 129 string imageFill = Model.Item.GetRawValueString("CustomImageFill", "contain"); 130 string groupImageMarkup = $"<img class=\"{imageShape}\" src=\"{groupImagePath}\" alt=\"{group.Name}\" style=\"object-fit:{imageFill}\">"; 131 132 return !string.IsNullOrEmpty(groupImage) ? groupImageMarkup : string.Empty; 133 } 134 135 private string GetImageShape() 136 { 137 string imageShape = Model.Item.GetRawValueString("ImageShape", "boxed"); 138 switch (imageShape) 139 { 140 case "boxed": 141 imageShape = "rounded-0"; 142 break; 143 case "rounded": 144 imageShape = "rounded-3"; 145 break; 146 case "circle": 147 imageShape = "rounded-pill"; 148 break; 149 } 150 return imageShape; 151 } 152 153 private string GetButtonAlignment() 154 { 155 string buttonAlignment = Model.Item.GetRawValueString("ButtonAlignment", "align-center-center"); 156 157 switch (buttonAlignment) 158 { 159 case "align-center-center": 160 return "text-center justify-content-center align-items-center"; 161 case "align-bottom-start": 162 return "text-start justify-content-start align-items-end"; 163 case "align-bottom-center": 164 return "text-center justify-content-center align-items-end"; 165 case "align-bottom-center-text-center": 166 return "text-center justify-content-center align-items-end"; 167 case "align-bottom-end": 168 return "text-end justify-content-end align-items-end"; 169 default: 170 return "align-center-center"; 171 } 172 } 173 174 private bool DisplayGroup(FacetViewModel facet, string groupId) { 175 if (facet == null || facet.OptionActiveCount == 2048) //2048 max facet count 176 return true; 177 178 return facet.Options.Any(o => o.Value == groupId && o.Count > 0); 179 } 180 } 181 182 @{ 183 ProductListViewModel productList = new ProductListViewModel(); 184 if (Dynamicweb.Context.Current.Items.Contains("ProductList")) 185 { 186 productList = (ProductListViewModel)Dynamicweb.Context.Current.Items["ProductList"]; 187 } 188 189 var customLimitGroupListFacet = productList.FacetGroups?.FirstOrDefault(g => g.Facets.Any(f => f.RenderType == "HideGroups"))?.Facets.FirstOrDefault(f => f.RenderType == "HideGroups"); 190 191 192 string groupType = Model.Item.GetRawValueString("GroupType", "subgroups"); 193 194 @* Custom code: Filter on ShowInMenu to hide EcomGroups where this setting is disabled *@ 195 var groups = GetGroups(groupType).Where(g => g.ShowInMenu).ToList(); 196 197 bool hideHeaders = (Model.Item?.GetBoolean("HideHeaders") ?? false); 198 string title = Model.Item?.GetString("Title", string.Empty); 199 string subtitle = Model.Item?.GetString("Subtitle", string.Empty); 200 bool groupsExist = groups is object && groups.Count != 0; 201 202 // Grid layout 203 string gridSize = Model.Item.GetRawValueString("GridSize", "3"); 204 string gridSizeMobile = Model.Item.GetRawValueString("GridSizeMobile", "1"); 205 gridSize = $"grid-{gridSizeMobile} grid-sm-3 grid-lg-{gridSize}"; 206 207 string itemsGap = $"gap-{Model.Item.GetRawValueString("GridItemsGap", "3")}"; 208 string layout = Model.Item.GetRawValueString("Layout", "overlay"); 209 210 // Styling 211 string ratio = Model.Item.GetRawValueString("ImageAspectRatio", string.Empty); 212 ratio = ratio != "0" ? ratio : string.Empty; 213 string ratioCssClass = ratio != string.Empty ? "ratio" : string.Empty; 214 string ratioVariable = ratio != string.Empty ? "--bs-aspect-ratio: " + ratio : string.Empty; 215 216 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "h3"); 217 string subtitleFontSize = Model.Item.GetRawValueString("SubtitleFontSize", "fs-5"); 218 string maxWidth = Model.Item.GetRawValueString("TextReadability", string.Empty); 219 maxWidth = maxWidth == "max-width-on" ? "mw-75ch" : string.Empty; 220 221 string buttonAlignment = GetButtonAlignment(); 222 223 string buttonStyle = Model.Item.GetRawValueString("ButtonStyle", "primary"); 224 225 string buttonSize = Model.Item.GetRawValueString("ButtonSize", "regular"); 226 buttonSize = buttonSize == "small" ? "btn btn-sm" : buttonSize; 227 buttonSize = buttonSize == "regular" ? "btn" : buttonSize; 228 buttonSize = buttonSize == "large" ? "btn btn-lg" : buttonSize; 229 230 string stretchedLink = "stretched-link"; 231 232 string imageShape = GetImageShape(); 233 string missingImageMarkup = $"<div class=\"bg-opacity-10 {imageShape}\" style=\"background-color:rgba(var(--swift-foreground-color-rgb),var(--bs-bg-opacity));\"></div>"; 234 } 235 236 @if (groupsExist) 237 { 238 <div class="grid gap-0 item_@(Model.Item.SystemName.ToLower())"> 239 @if (!hideHeaders) 240 { 241 <div class="g-col-12 pb-2 pb-lg-4"> 242 <div class="mb-0-last-child"> 243 @if (!string.IsNullOrEmpty(title)) 244 { 245 <h2 class="mt-0 @titleFontSize @maxWidth">@title</h2> 246 } 247 248 @if (!string.IsNullOrEmpty(subtitle)) 249 { 250 <p class="@subtitleFontSize @maxWidth">@subtitle</p> 251 } 252 </div> 253 </div> 254 } 255 256 <div class="g-col-12 grid @gridSize @itemsGap"> 257 @foreach (var group in groups.Where(g => DisplayGroup(customLimitGroupListFacet, g.Id))) 258 { 259 string groupImageMarkup = GetGroupImageMarkup(group, imageShape) ?? missingImageMarkup; 260 bool groupImage = !string.IsNullOrEmpty(groupImageMarkup); 261 262 <div class="d-flex flex-column h-100"> 263 @{ 264 switch (layout) 265 { 266 case "overlay": 267 <div class="card rounded-0 border-0 @(ratioCssClass)" style="@ratioVariable"> 268 269 @(groupImage ? groupImageMarkup : missingImageMarkup) 270 271 <div class="d-grid p-3 @buttonAlignment"> 272 @if (GetLink(group) is object) 273 { 274 bool openLinksInNewTab = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && GetLink(group).IsExternal; 275 string target = openLinksInNewTab ? "target=\"_blank\"" : string.Empty; 276 string rel = openLinksInNewTab ? "rel=\"noopener\"" : string.Empty; 277 278 <a href="@GetLink(group)" class="@(buttonSize) btn-@buttonStyle @(stretchedLink)" data-dw-button="@buttonStyle" @target @rel>@group.Name</a> 279 } 280 </div> 281 </div> 282 break; 283 case "below": 284 <div class="card rounded-0 border-0 gap-3"> 285 286 <div class="@(ratioCssClass)" style="@ratioVariable"> 287 288 @(groupImage ? groupImageMarkup : missingImageMarkup) 289 290 </div> 291 292 <div class="@(groupImage ? "h-100" : string.Empty) d-grid @buttonAlignment"> 293 294 @if (GetLink(group) is object) 295 { 296 bool openLinksInNewTab = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && GetLink(group).IsExternal; 297 string target = openLinksInNewTab ? "target=\"_blank\"" : string.Empty; 298 string rel = openLinksInNewTab ? "rel=\"noopener\"" : string.Empty; 299 300 <a href="@GetLink(group)" class="@(buttonSize) btn-@buttonStyle @(stretchedLink)" data-dw-button="@buttonStyle" @target @rel>@group.Name</a> 301 } 302 </div> 303 </div> 304 break; 305 } 306 } 307 </div> 308 } 309 </div> 310 </div> 311 } 312 else if (Pageview.IsVisualEditorMode) 313 { 314 <div class="alert alert-dark" role="alert"> 315 <span>@Translate("Group grid"): @Translate("Edit this column to configure")</span> 316 </div> 317 } 318