Error executing template "Designs/Swift/Navigation/COMM_EventTabs.cshtml" System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary. at System.ThrowHelper.ThrowKeyNotFoundException() at System.Collections.Generic.Dictionary`2.get_Item(TKey key) at CompiledRazorTemplates.Dynamic.RazorEngine_394e850960994fb69b77c3edfa28ca61.Execute() in C:\inetpub\wwwroot\directions2023\Files\Templates\Designs\Swift\Navigation\COMM_EventTabs.cshtml:line 7 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.Navigation.NavigationTreeViewModel> @using Dynamicweb @using System.Text.RegularExpressions @using Dynamicweb.Frontend @{ string theme = !string.IsNullOrEmpty(Model.Parameters["theme"].ToString()) ? Model.Parameters["theme"].ToString() : string.Empty; string navOrientation = !string.IsNullOrEmpty(Model.Parameters["navOrientation"].ToString()) ? Model.Parameters["navOrientation"].ToString() : string.Empty; string navAlignment = !string.IsNullOrEmpty(Model.Parameters["navAlignment"].ToString()) ? Model.Parameters["navAlignment"].ToString() : string.Empty; string linkFontWeight = !string.IsNullOrEmpty(Model.Parameters["LinkFontWeight"].ToString()) ? Model.Parameters["LinkFontWeight"].ToString() : string.Empty; string linkCasing = !string.IsNullOrEmpty(Model.Parameters["LinkCasing"].ToString()) ? Model.Parameters["LinkCasing"].ToString() : string.Empty; string linkFontSize = !string.IsNullOrEmpty(Model.Parameters["LinkFontSize"].ToString()) ? Model.Parameters["LinkFontSize"].ToString() : string.Empty; string layout = !string.IsNullOrEmpty(Model.Parameters["Layout"].ToString()) ? Model.Parameters["Layout"].ToString() : string.Empty; string iconSize = "icon-3"; if (linkFontSize == "fs-7") { iconSize = "icon-2"; } if (linkFontSize == "fs-5") { iconSize = "icon-4"; } } <div class="grid"> <div class="g-col-12"> <nav class="navbar navbar-expand-lg d-flex py-0 overflow-y-auto @navOrientation @navAlignment"> @{@RenderFirstLevelNodes(Model.Nodes, theme, navOrientation, linkFontWeight, linkCasing, linkFontSize, iconSize, layout)} </nav> </div> </div> @helper RenderFirstLevelNodes(IEnumerable<Dynamicweb.Frontend.Navigation.NavigationTreeNodeViewModel> nodes, string theme, string navOrientation, string linkFontWeight, string linkCasing, string linkFontSize, string iconSize, string layout) { int imageHeight = 50; string logo = Model.Parameters.ContainsKey("Logo") ? Model.Parameters["Logo"].ToString() : string.Empty; int logoHeight = Model.Parameters.ContainsKey("LogoHeight") ? Convert.ToInt32(Model.Parameters["LogoHeight"]) : 50; string rootPageId = Model.Parameters.ContainsKey("RootPageId") ? Model.Parameters["RootPageId"].ToString() : string.Empty; var rootPageFriendlyUrl = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl("Default.aspx?ID=" + rootPageId); string theme = Model.Parameters.ContainsKey("theme") ? Model.Parameters["theme"].ToString() : string.Empty; string themeSticky = Model.Parameters.ContainsKey("themeSticky") ? Model.Parameters["themeSticky"].ToString() : string.Empty; bool showOnlyFirstNavLevel = Model.Parameters.ContainsKey("ShowOnlyFirstNavLevel") ? Convert.ToBoolean(Model.Parameters["ShowOnlyFirstNavLevel"].ToString()) : false; int gridRowId = Model.Parameters.ContainsKey("GridRowId") ? Convert.ToInt32(Model.Parameters["GridRowId"].ToString()) : 0; int currentParagraphId = Pageview.CurrentParagraph != null ? Pageview.CurrentParagraph.ID : gridRowId; string menuId = Model.Parameters.ContainsKey("menu-id") ? $"menu_{Model.Parameters["menu-id"].ToString().ToLower()}" : string.Empty; string firstItemActive = !nodes.Any(node => node.InPath || node.IsActive) ? "active" : string.Empty; <ul class="overflow-y-auto align-items-center w-100 gap-lg-3 gap-1 navbar-nav flex-nowrap @(navOrientation == "vertical" ? "flex-column" : navOrientation)"> <li class="nav-item flex-1"> <div class="item-container first @firstItemActive"> <a href="@rootPageFriendlyUrl" class="first-item fw-bold p-2 nav-link text-nowrap text-decoration-underline-hover @linkFontSize @linkFontWeight @linkCasing"> @Translate("Intro") </a> @if (!string.IsNullOrEmpty(logo)) { var parms = new Dictionary<string, object>(); parms.Add("alt", "logo"); parms.Add("height", logoHeight); <a href="@rootPageFriendlyUrl" class="logo d-none"> @RenderPartial("../Components/Image.cshtml", new FileViewModel { Path = logo }, parms) </a> } </div> </li> @foreach (var node in nodes) { var page = Dynamicweb.Content.Services.Pages.GetPage(node.PageId); var pageType = !string.IsNullOrEmpty(page.ItemType) ? page.ItemType : "Swift_Page"; string pageIcon = string.Empty; if (page.PropertyItem is object && page.PropertyItem.TryGetValue("Icon", out object pageIconValue)) { pageIcon = Dynamicweb.Core.Converter.ToString(pageIconValue); } string preferencesLayout = page.Item?["PreferencesLayout"] != null ? page.Item["PreferencesLayout"].ToString() : ""; string preferencesType = "language"; bool countrySelector = page.Item?["CountrySelector"] != null ? Convert.ToBoolean(page.Item["CountrySelector"].ToString()) : false; bool languageSelector = page.Item?["LanguageSelector"] != null ? Convert.ToBoolean(page.Item["LanguageSelector"].ToString()) : false; bool currencySelector = page.Item?["CurrencySelector"] != null ? Convert.ToBoolean(page.Item["CurrencySelector"].ToString()) : false; string dropdownAttributes = string.Empty; string dropdownClasses = string.Empty; var hasChildren = node.Nodes.Count() > 0 || pageType == "Swift_SignIn"; if (hasChildren && !showOnlyFirstNavLevel) { dropdownAttributes = hasChildren ? " role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" data-bs-toggle=\"dropdown\" data-bs-offset=\"0,0\"" : ""; } string isActive = node.InPath || node.IsActive ? " active" : ""; string nodeId = !string.IsNullOrEmpty(node.GroupId) ? "Navigation_" + node.GroupId + "_" + currentParagraphId : "Navigation_Page_Desktop_" + node.PageId.ToString() + "_" + currentParagraphId; if (pageType != "Swift_Preferences") { <li class="nav-item@(hasChildren ? " dropdown" : "") flex-1 @(isActive)"> <div class="item-container @(isActive)"> @if (node.IsClickable) { <a href="@node.Link" class="fw-bold p-2 nav-link text-nowrap text-decoration-underline-hover @linkFontSize @linkFontWeight @linkCasing@(isActive)@(hasChildren ? " dropdown-toggle" : "")" @dropdownAttributes @(node.IsActive ? " aria-current='page'" : "") id="@nodeId"> @{@RenderNavigationItem(node, pageType, pageIcon, iconSize, layout)} </a> } else { <span class="fw-bold p-2 nav-link text-nowrap @linkFontSize @linkFontWeight @linkCasing@(hasChildren ? " dropdown-toggle " : "")" @dropdownAttributes id="@nodeId"> @{@RenderNavigationItem(node, pageType, pageIcon, iconSize, layout)} </span> } </div> @if (hasChildren) { if (!showOnlyFirstNavLevel) { <ul class="dropdown-menu @(theme)" aria-labelledby="@nodeId"> @foreach (var subnode in node.Nodes) //Standard pages { nodeId = !string.IsNullOrEmpty(subnode.GroupId) ? "Navigation_" + subnode.GroupId + "_" + currentParagraphId : "Navigation_Page_" + subnode.PageId.ToString() + "_" + currentParagraphId; int count = 1; @RenderSubNodes(subnode, 2, nodeId, count) } @if (pageType == "Swift_SignIn") //Sign out link { if (Pageview.User != null) { string link = "/Admin/Public/ExtranetLogoff.aspx?redirect=no"; <li><hr class="dropdown-divider"></li> if (Dynamicweb.Security.UserManagement.User.GetCurrentSecondaryUser() != null) { <li> <a href="Default.aspx?ID=@(Pageview.ID)&DwExtranetRemoveSecondaryUser=1" class="dropdown-item py-2 text-decoration-underline-hover swift_sign-out-as-customer-link @linkFontSize @linkFontWeight @linkCasing" id="SignInButton_@currentParagraphId">@Translate("Sign out as a customer")</a> </li> } <li> <a href="@link" class="dropdown-item py-2 text-decoration-underline-hover swift_sign-out-link @linkFontSize @linkFontWeight @linkCasing">@Translate("Sign out")</a> </li> } } </ul> } } </li> } else { if (preferencesLayout == "modal") { string groupId = Dynamicweb.Context.Current.Request["GroupID"] != null ? Dynamicweb.Context.Current.Request["GroupID"].ToString() : ""; string productId = Dynamicweb.Context.Current.Request["ProductID"] != null ? Dynamicweb.Context.Current.Request["ProductID"].ToString() : ""; string variantId = Dynamicweb.Context.Current.Request["VariantID"] != null ? Dynamicweb.Context.Current.Request["VariantID"].ToString() : ""; <li class="nav-item@(hasChildren ? " dropdown" : "")"> <form action="/Default.aspx?ID=@node.PageId" data-response-target-element="PreferencesModalContent" data-layout-template="Swift_Preferences.cshtml" data-preloader="inline"> <input type="hidden" name="CurrentPageID" value="@Pageview.ID"> <input type="hidden" name="GroupID" value="@groupId"> <input type="hidden" name="ProductID" value="@productId"> <input type="hidden" name="VariantID" value="@variantId"> <button type="button" onmouseover="swift.PageUpdater.Update(event)" onclick="swift.PageUpdater.Update(event)" class="btn nav-link p-2 text-nowrap border-0 swift_open-preferences-modal @linkFontSize @linkFontWeight @linkCasing" data-bs-toggle="modal" data-bs-target="#PreferencesModal" id="OpenPreferences_@currentParagraphId"> @if (languageSelector) { {@RenderNavigationItem(node, pageType, pageIcon, iconSize, layout, "language")} } else { {@RenderNavigationItem(node, pageType, pageIcon, iconSize, layout)} } </button> </form> </li> } else { var ecomCountries = Dynamicweb.Ecommerce.Services.Countries.GetCountries(); var currencies = Dynamicweb.Ecommerce.Services.Currencies.GetAllCurrencies(); if (languageSelector) { List<Dynamicweb.Content.Page> languages = new List<Dynamicweb.Content.Page>(); if (Pageview.Page.Area.IsMaster) { languages.Add(Pageview.Page); if (Pageview.Page.Languages != null) { foreach (var language in Pageview.Page.Languages) { if (language.Area.Active == true) { languages.Add(language); } } } } else { languages.Add(Pageview.Page.MasterPage); if (Pageview.Page.MasterPage != null) { if (Pageview.Page.MasterPage.Languages != null) { foreach (var language in Pageview.Page.MasterPage.Languages) { if (language.Area.Active == true) { languages.Add(language); } } } } } if (languages.Count > 1) { preferencesType = "language"; {@RenderPreferencesDropdown(node, preferencesType, linkFontSize, linkFontWeight, linkCasing, theme, pageType, pageIcon, iconSize, layout)} } } if (countrySelector && ecomCountries.Count > 1) { preferencesType = "country"; {@RenderPreferencesDropdown(node, preferencesType, linkFontSize, linkFontWeight, linkCasing, theme, pageType, pageIcon, iconSize, layout)} } if (currencySelector && currencies.Count() > 1) { preferencesType = "currency"; {@RenderPreferencesDropdown(node, preferencesType, linkFontSize, linkFontWeight, linkCasing, theme, pageType, pageIcon, iconSize, layout)} } } } } </ul> } @helper RenderNavigationItem(Dynamicweb.Frontend.Navigation.NavigationTreeNodeViewModel node, string pageType, string pageIcon, string iconSize, string layout, string preferencesType = "") { var page = Dynamicweb.Content.Services.Pages.GetPage(node.PageId); if (pageType == "Swift_Cart") //Mini cart { string cartId = ""; if (page.Item["ContextCart"] != null) { cartId = !string.IsNullOrEmpty(page.Item["ContextCart"].ToString()) ? "ID=\"Cart_" + page.Item["ContextCart"].ToString() + "\"" : ""; } string jsCartClass = string.IsNullOrEmpty(cartId) ? "js-cart-qty" : ""; double totalProducts = 0; Dynamicweb.Ecommerce.Common.Context.CartContext = null; if (page.Item["ContextCart"] != null) { var orderContext = Dynamicweb.Ecommerce.Services.OrderContexts.GetOrderContextById(page.Item["ContextCart"].ToString()); Dynamicweb.Ecommerce.Common.Context.CartContext = orderContext; } if (Dynamicweb.Ecommerce.Common.Context.Cart != null) { bool renderOrderlineCountInsteadOfProductCount = page.Item["RenderOrderlineCountInsteadOfProductCount"] != null ? Convert.ToBoolean(page.Item["RenderOrderlineCountInsteadOfProductCount"]) : false; if (!renderOrderlineCountInsteadOfProductCount) { totalProducts = Dynamicweb.Ecommerce.Common.Context.Cart.GetParentProductLineQuantityCount(Dynamicweb.Ecommerce.Common.Context.Cart.OrderLines); } else { totalProducts = Dynamicweb.Ecommerce.Common.Context.Cart.GetParentOrderLineCount(Dynamicweb.Ecommerce.Common.Context.Cart.OrderLines); } } switch (layout) { case "linksOnly": <span class="align-middle">@node.Name</span> <span class="@jsCartClass mini-cart-quantity align-middle" @cartId>(@totalProducts)</span> break; case "iconsOnly": {@RenderIcon(pageIcon, iconSize)} <span class="@jsCartClass mini-cart-quantity align-middle" @cartId>(@totalProducts)</span> break; case "iconsAndLinks": {@RenderIcon(pageIcon, iconSize)} <span class="@jsCartClass mini-cart-quantity align-middle" @cartId>(@totalProducts)</span> <span class="align-middle">@node.Name</span> break; case "linksAndIcons": <span class="align-middle">@node.Name</span> <span class="@jsCartClass mini-cart-quantity align-middle" @cartId>(@totalProducts)</span> {@RenderIcon(pageIcon, iconSize)} break; } } else { string name = node.Name; if (preferencesType == "country") { //Country name = Translate("Deliver to") + ": " + Dynamicweb.Ecommerce.Common.Context.Country.GetName(Dynamicweb.Ecommerce.Common.Context.LanguageID); } if (preferencesType == "language") { //Languange string iconFolder = "/Files/FlagIcons/"; pageIcon = iconFolder + Pageview.Area.CultureInfo.Name.ToLower() + ".svg"; Regex reg = new Regex(@"\(([^\)]+)\)"); name = reg.Replace(Pageview.Area.CultureInfo.DisplayName, ""); layout = layout == "linksOnly" ? "iconsAndLinks" : layout; bool hideIcon = page.Item?["HideIcon"] != null ? Convert.ToBoolean(page.Item["HideIcon"].ToString()) : false; bool hideName = page.Item?["HideName"] != null ? Convert.ToBoolean(page.Item["HideName"].ToString()) : false; layout = hideIcon ? "linksOnly" : layout; layout = hideName ? "iconsOnly" : layout; } if (preferencesType == "currency") { //Country name = Dynamicweb.Ecommerce.Common.Context.Currency.Code; } switch (layout) { case "linksOnly": <span class="align-middle">@name</span> break; case "iconsOnly": <span class="visually-hidden">@name</span> {@RenderIcon(pageIcon, iconSize)} break; case "iconsAndLinks": {@RenderIcon(pageIcon, iconSize)} <span class="align-middle">@name</span> break; case "linksAndIcons": <span class="align-middle">@name</span> {@RenderIcon(pageIcon, iconSize)} break; } } } @helper RenderPreferencesDropdown(Dynamicweb.Frontend.Navigation.NavigationTreeNodeViewModel node, string preferencesType, string linkFontSize, string linkFontWeight, string linkCasing, string theme, string pageType, string pageIcon, string iconSize, string layout) { string groupId = Dynamicweb.Context.Current.Request["GroupID"] != null ? Dynamicweb.Context.Current.Request["GroupID"].ToString() : ""; string productId = Dynamicweb.Context.Current.Request["ProductID"] != null ? Dynamicweb.Context.Current.Request["ProductID"].ToString() : ""; string variantId = Dynamicweb.Context.Current.Request["VariantID"] != null ? Dynamicweb.Context.Current.Request["VariantID"].ToString() : ""; int currentParagraphId = Pageview.CurrentParagraph.ID; string nodeId = !string.IsNullOrEmpty(node.GroupId) ? "PreferencesLink_" + node.GroupId + "_" + currentParagraphId : "PreferencesLink_" + node.PageId.ToString() + "_" + currentParagraphId; <li class="nav-item dropdown"> <form class="d-none d-lg-block" action="/Default.aspx?ID=@node.PageId" data-response-target-element="@(preferencesType)Dropdown_@currentParagraphId" data-layout-template="Swift_Preferences.cshtml" data-preloader="inline"> <input type="hidden" name="Type" value="@preferencesType"> <input type="hidden" name="CurrentPageID" value="@Pageview.ID"> <input type="hidden" name="GroupID" value="@groupId"> <input type="hidden" name="ProductID" value="@productId"> <input type="hidden" name="VariantID" value="@variantId"> <input type="hidden" name="FontSize" value="@linkFontSize"> <input type="hidden" name="FontWeight" value="@linkFontWeight"> <input type="hidden" name="Casing" value="@linkCasing"> <a id="@nodeId" onmouseover="swift.PageUpdater.Update(event)" onclick="swift.PageUpdater.Update(event)" class="nav-link p-2 text-nowrap text-decoration-underline-hover @linkFontSize @linkFontWeight @linkCasing@(node.IsActive ? " active" : "") dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" @(node.IsActive ? " aria-current='page'" : "")> @{@RenderNavigationItem(node, pageType, pageIcon, iconSize, layout, preferencesType)} </a> <ul class="dropdown-menu @(theme)" id="@(preferencesType)Dropdown_@currentParagraphId"> @* The content here comes from an external request *@ </ul> </form> <form class="d-block d-lg-none" action="/Default.aspx?ID=@node.PageId" data-response-target-element="PreferencesModalContent" data-layout-template="Swift_Preferences.cshtml" data-preloader="inline"> <input type="hidden" name="Layout" value="modal"> <input type="hidden" name="CurrentPageID" value="@Pageview.ID"> <input type="hidden" name="GroupID" value="@groupId"> <input type="hidden" name="ProductID" value="@productId"> <input type="hidden" name="VariantID" value="@variantId"> <button type="button" onmouseover="swift.PageUpdater.Update(event)" onclick="swift.PageUpdater.Update(event)" class="btn nav-link p-2 text-nowrap border-0 swift_open-preferences-modal @linkFontSize @linkFontWeight @linkCasing" data-bs-toggle="modal" data-bs-target="#PreferencesModal"> @{@RenderNavigationItem(node, pageType, pageIcon, iconSize, layout, preferencesType)} </button> </form> </li> } @helper RenderIcon(string pageIcon, string iconSize) { if (pageIcon.EndsWith(".svg", StringComparison.OrdinalIgnoreCase) && !pageIcon.EndsWith("none.svg", StringComparison.OrdinalIgnoreCase)) { string iconPath = Dynamicweb.Context.Current.Server.MapPath(pageIcon); <span class="@iconSize"> @ReadFile(iconPath) </span> } } @helper RenderSubNodes(Dynamicweb.Frontend.Navigation.NavigationTreeNodeViewModel subnode , int maxLevel , string nodeId , int count) { <li class="nav-item@(subnode.Nodes.Any() ? " dropdown" : "") d-flex align-items-center"> @if (subnode.IsClickable) { <a href="@subnode.Link" class="dropdown-item py-2 text-decoration-underline-hover" @(subnode.IsActive ? " aria-current='page'" : "") id="@nodeId">@subnode.Name</a> if (subnode.Nodes.Any() && (count != maxLevel)) { <ul class="dropdown-menu dropdown-submenu" aria-labelledby="@nodeId"> @foreach (var item in subnode.Nodes) { if (item.Nodes.Any()) { count++; @RenderSubNodes(item , 2 , nodeId , count) } else { <li class="d-flex align-items-center"> <a href="@item.Link" class="dropdown-item py-2 text-decoration-underline-hover" title="@item.Name">@item.Name</a> </li> } } </ul> <span class="px-2 lh-1 arrow_wrapper"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-right" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"/> </svg> </span> } } else { <span class="dropdown-item py-2" @(subnode.IsActive ? " aria-current='page'" : "") id="@nodeId">@subnode.Name</span> } </li> }
What can you look forward to?
The speakerwall for Directions EMEA 2023
Top speakers
Second tier speakers
Third tier speakers
Elena Baeva
Fonder and CEO at 365 Talent Portal, IAMCP EMEA President and Global Diversity and Inclusion Chairperson
Steve Brooks
CTO at Bam Boom Cloud - Microsoft D365 Business Central Partner of the Year 2022, 2019, finalist 2020, 2021.
Julien Chambon
Head of D365 Consulting at Bam Boom Cloud - Microsoft D365 Business Central Partner of the Year 2022, 2019, finalist 2020, 2021.
Stefano Demiliani
Microsoft MVP. CTO for NAVLAB. Azure Solution Architect and DevOps Engineer. Microsoft MCSD, MCSA. Trainer and Author.
Tania Konczynski
Global Marketing Director for Bam Boom Cloud | B2B Marketing expert for Microsoft Dynamics 365 | Ultimate frisbee fan | Wannabe foodie | Soccer mom
Lajos Nagy
Enthusiastic Dynamics 365 Business Central Expert, Co-Founder & Product Manager at AppVision
Andrei Panko
Product manager: SCM, Warehouse, Jobs, Manufacturing, and e-Commerce (Shopify Connector)
Kennie Pontoppidan
Principal Program Manager: server, database, reporting and data analysis, telemetry, and performance