Error executing template "Designs/Swift/_parsed/Swift_Page.parsed.cshtml"
System.Data.SqlClient.SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server) ---> System.ComponentModel.Win32Exception (0x80004005): Access is denied
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)
at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
at System.Data.SqlClient.SqlConnection.Open()
at Dynamicweb.Data.DatabaseConnectionProvider.CreateConnection(Boolean open)
at Dynamicweb.Data.Database.CreateConnection()
at Dynamicweb.Data.Database.CreateDataReader(CommandBuilder commandBuilder, IDbConnection connection, IDbTransaction transaction, Int32 commandTimeout)
at Dynamicweb.Ecommerce.Products.ProductRepository.GetProductById(String productId, String productVariantId, String productLanguageId)
at Dynamicweb.Ecommerce.Products.ProductService.FetchMissingProductsInternal(IProductRepository repo, IEnumerable`1 keys)
at Dynamicweb.Caching.ServiceCache`2.GetCache(IEnumerable`1 keys)
at Dynamicweb.Caching.ServiceCache`2.GetCache(TKey key)
at Dynamicweb.Ecommerce.Products.ProductService.GetProductById(String productId, String productVariantId, String productLanguageId, User user, Boolean showUntranslated)
at Dynamicweb.Ecommerce.Products.ProductService.GetProductById(String productId, String productVariantId, String productLanguageId, Boolean useAssortments)
at Dynamicweb.Ecommerce.Products.ProductService.GetProductById(String productId, String productVariantId, String productLanguageId)
at CompiledRazorTemplates.Dynamic.RazorEngine_aebde1cf66d540aca0a6b5d7eeb0dbcb.Execute() in D:\dynamicweb.net\Solutions\Dynamicweb\scrouples.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\_parsed\Swift_Page.parsed.cshtml:line 419
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()
ClientConnectionId:00000000-0000-0000-0000-000000000000
Error Number:5,State:0,Class:20
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
2 @using System
3 @using Dynamicweb
4 @using Dynamicweb.Environment
5 @using Dynamicweb.Frontend
6
7 @{
8 string swiftVersion = ReadFile("/Files/Templates/Designs/Swift/swift_version.txt");
9 bool renderAsResponsive = Model.Area.Item.GetString("DeviceRendering", "responsive").Equals("responsive", StringComparison.OrdinalIgnoreCase);
10 bool renderMobile = Pageview.Device == Dynamicweb.Frontend.Devices.DeviceType.Mobile || Pageview.Device == Dynamicweb.Frontend.Devices.DeviceType.Tablet;
11 string responsiveClassDesktop = string.Empty;
12 string responsiveClassMobile = string.Empty;
13 if (renderAsResponsive)
14 {
15 responsiveClassDesktop = " d-none d-xl-block";
16 responsiveClassMobile = " d-block d-xl-none";
17 }
18
19 var disableWideBreakpoints = Model.Area?.Item?.GetRawValueString("DisableWideBreakpoints", "default");
20
21 var brandingPageId = Model.Area.Item.GetLink("BrandingPage") != null ? Model.Area.Item.GetLink("BrandingPage").PageId : 0;
22 var themePageId = Model.Area.Item.GetLink("ThemesPage") != null ? Model.Area.Item.GetLink("ThemesPage").PageId : 0;
23 string customHeaderInclude = Model.Area.Item.GetFile("CustomHeaderInclude") != null ? Model.Area.Item.GetFile("CustomHeaderInclude").Name : string.Empty;
24
25 var brandingPage = Dynamicweb.Content.Services.Pages?.GetPage(brandingPageId) ?? null;
26 var themesParagraphLastChanged = Dynamicweb.Content.Services.Paragraphs.GetParagraphsByPageId(themePageId).OrderByDescending(p => p.Audit.LastModifiedAt).FirstOrDefault();
27
28 var cssLastModified = brandingPage.Audit.LastModifiedAt > themesParagraphLastChanged.Audit.LastModifiedAt ? brandingPage.Audit.LastModifiedAt : themesParagraphLastChanged.Audit.LastModifiedAt;
29 var cssThemeAndBrandingStyleFileInfo = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath($"/Files/Templates/Designs/Swift/_parsed/Swift_css/Swift_styles_{Model.Area.ID}.min.css"));
30
31 // Schema.org details for PDP
32 string productId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("ProductID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("ProductID") : "";
33 bool isProductDetailsPage = !string.IsNullOrEmpty(productId);
34 bool isArticlePage = Model.ItemType == "Swift_Article";
35 string schemaOrgType = string.Empty;
36
37 if (isProductDetailsPage)
38 {
39 schemaOrgType = "itemscope=\"\" itemtype=\"https://schema.org/Product\"";
40 }
41
42 if (isArticlePage)
43 {
44 schemaOrgType = "itemscope=\"\" itemtype=\"https://schema.org/Article\"";
45 }
46
47 if (!cssThemeAndBrandingStyleFileInfo.Exists || cssThemeAndBrandingStyleFileInfo.LastWriteTime < brandingPage.Audit.LastModifiedAt)
48 {
49 //Branding page has been saved or the file is missing. Rewrite the file to disc.
50 if (brandingPageId > 0)
51 {
52 var brandingPageview = Dynamicweb.Frontend.PageView.GetPageviewByPageID(brandingPageId);
53 brandingPageview.Redirect = false;
54 brandingPageview.Output();
55 }
56 }
57
58 if (!cssThemeAndBrandingStyleFileInfo.Exists || cssThemeAndBrandingStyleFileInfo.LastWriteTime < themesParagraphLastChanged.Audit.LastModifiedAt)
59 {
60 //Branding page has been saved or the file is missing. Rewrite the file to disc.
61 if (themePageId > 0)
62 {
63 var themePageview = Dynamicweb.Frontend.PageView.GetPageviewByPageID(themePageId);
64 themePageview.Redirect = false;
65 themePageview.Output();
66 }
67 }
68
69 var cssStyleFileInfo = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath("/Files/Templates/Designs/Swift/Assets/css/styles.css"));
70 var jsFileInfo = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath("/Files/Templates/Designs/Swift/Assets/js/scripts.js"));
71
72 string masterTheme = !string.IsNullOrWhiteSpace(Model.Area.Item.GetRawValueString("Theme")) ? " theme " + Model.Area.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : "";
73
74 string favicon = Model.Area.Item.GetFile("Favicon") != null ? Model.Area.Item.GetFile("Favicon").Path : "/Files/Templates/Designs/Swift/Assets/Images/favicon.png";
75
76 string headerCssClass = "sticky-top";
77 bool movePageBehind = false;
78
79 if (Pageview.Page.PropertyItem != null)
80 {
81 headerCssClass = Pageview.Page.PropertyItem["MoveThisPageBehindTheHeader"] != null ? Pageview.Page.PropertyItem["MoveThisPageBehindTheHeader"].ToString() : "sticky-top";
82 movePageBehind = headerCssClass == "fixed-top" && !Pageview.IsVisualEditorMode ? true : false;
83 }
84
85 headerCssClass = headerCssClass == "" ? "sticky-top" : headerCssClass;
86 headerCssClass = Pageview.IsVisualEditorMode ? "" : headerCssClass;
87
88 string googleTagManagerID = Model.Area.Item.GetString("GoogleTagManagerID");
89 string googleAnalyticsMeasurementID = Model.Area.Item.GetString("GoogleAnalyticsMeasurementID");
90 var cookieOptInLevel = CookieManager.GetCookieOptInLevel();
91 bool allowTracking = cookieOptInLevel == CookieOptInLevel.All || (cookieOptInLevel == CookieOptInLevel.Functional && CookieManager.GetCookieOptInCategories().Contains("Statistical"));
92
93 Dynamicweb.Context.Current.Response.AddHeader("link", $"</Files/Templates/Designs/Swift/Assets/css/styles.css?{cssStyleFileInfo.LastWriteTime.Ticks}>; rel=preload; as=style;");
94 Dynamicweb.Context.Current.Response.AddHeader("link", $"</Files/Templates/Designs/Swift/_parsed/Swift_css/Swift_styles_{Model.Area.ID}.min.css?{cssLastModified.Ticks}; rel=preload; as=style;");
95 Dynamicweb.Context.Current.Response.AddHeader("link", $"</Files/Templates/Designs/Swift/Assets/js/aos.js?{jsFileInfo.LastWriteTime.Ticks}; rel=preload; as=script;");
96 Dynamicweb.Context.Current.Response.AddHeader("link", $"</Files/Templates/Designs/Swift/Assets/js/scripts.js?{jsFileInfo.LastWriteTime.Ticks}; rel=preload; as=script;");
97 //Dynamicweb.Context.Current.Response.Flush(); //This sends the headers where we are now in the rendering making the TTFB faster
98
99 @*SetMetaTags();*@
100
101 List<Dynamicweb.Content.Page> languages = new List<Dynamicweb.Content.Page>();
102
103 if (Pageview.Area.IsMaster)
104 {
105 languages.Add(Pageview.Page);
106 if (Pageview.Page.Languages != null)
107 {
108 foreach (var language in Pageview.Page.Languages)
109 {
110 languages.Add(language);
111 }
112 }
113 }
114 else
115 {
116 languages.Add(Pageview.Page.MasterPage);
117 if (Pageview.Page.MasterPage != null)
118 {
119 if (Pageview.Page.MasterPage.Languages != null)
120 {
121 foreach (var language in Pageview.Page.MasterPage.Languages)
122 {
123 languages.Add(language);
124 }
125 }
126 }
127 }
128
129 string siteLanguage = Pageview.Area.CultureInfo.Name;
130 Uri url = Dynamicweb.Context.Current.Request.Url;
131 string hostName = url.Host; // domain.com/da-dk or domain.com/en-us
132
133 var ecomCountries = Dynamicweb.Ecommerce.Services.Countries.GetCountries();
134 var ecomCurrencies = Dynamicweb.Ecommerce.Services.Currencies.GetAllCurrencies();
135
136
137
138
139 //Generic Site Values
140 string openGraphFacebookAppID = Model.Area.Item.GetString("Fb_app_id") != null ? Model.Area.Item.GetString("Fb_app_id") : "";
141 string openGraphType = Model.Area.Item.GetString("Open_Graph_Type") != null ? Model.Area.Item.GetString("Open_Graph_Type") : "";
142 string openGraphSiteName = Model.Area.Item.GetString("Open_Graph_Site_Name") != null ? Model.Area.Item.GetString("Open_Graph_Site_Name") : "";
143
144
145 //Page specific values
146 string openGraphSiteTitle = Model.Area.Item.GetString("Open_Graph_Title") != null ? Model.Area.Item.GetString("Open_Graph_Title") : "";
147 FileViewModel openGraphImage = Model.Area.Item.GetFile("Open_Graph_Image");
148 string openGraphImageALT = Model.Area.Item.GetString("Open_Graph_Image_ALT") != null ? Model.Area.Item.GetString("Open_Graph_Image_ALT") : "";
149 string openGraphDescription = Model.Area.Item.GetString("Open_Graph_Description") != null ? Model.Area.Item.GetString("Open_Graph_Description") : "";
150
151
152 }
153 <!doctype html>
154 <html lang="@Pageview.Area.CultureInfo.TwoLetterISOLanguageName">
155 <head>
156 <!-- @swiftVersion -->
157 @* Required meta tags *@
158 <meta charset="utf-8">
159 <meta name="viewport" content="height=device-height, width=device-width, initial-scale=1.0">
160 <link rel="shortcut icon" href="@favicon">
161 <link rel="apple-touch-icon" href="/Files/Templates/Designs/Swift/Assets/Images/logo_transparent.png">
162 @RenderSnippet("CustomMetaTags")
163 @if (!string.IsNullOrEmpty(openGraphType))
164 {
165 <meta property="og:type" content="@openGraphType">
166 }
167
168 @if (!string.IsNullOrEmpty(openGraphSiteName))
169 {
170 <meta property="og:site_name" content="@openGraphSiteName">
171 }
172
173 @if (!string.IsNullOrEmpty(Model.Title))
174 {
175 <meta property="og:title" content="@Model.Title">
176 }
177 else
178 {
179 <meta property="og:title" content="@openGraphSiteTitle">
180 }
181 @if (!string.IsNullOrEmpty(Pageview.Page.TopImage) && openGraphImage == null)
182 {
183 <meta property="og:image" content="@Dynamicweb.Context.Current.Request.Url.Scheme://@Dynamicweb.Context.Current.Request.Url.Host@Pageview.Page.TopImage">
184 }
185 @if (string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["ProductID"]))
186 {
187 if (!string.IsNullOrEmpty(Model.Description))
188 {
189 <meta property="og:description" content="@Model.Description">
190
191 }
192 else
193 {
194 <meta property="og:description" content="@openGraphDescription">
195
196 }
197 if (openGraphImage != null)
198 {
199 <meta property="og:image" content="@openGraphImage.Path">
200 }
201
202 if (!string.IsNullOrEmpty(openGraphImageALT))
203 {
204
205 <meta property="og:image:alt" content="@openGraphImageALT">
206
207 }
208 }
209 @Model.MetaTags
210
211 @{
212 var alreadyWrittenTwoletterIsos = new List<string>();
213 @* Languages meta data *@
214 foreach (var language in languages)
215 {
216 hostName = url.Host;
217 if (language?.Area != null)
218 {
219 if (language.Area?.MasterArea != null && !string.IsNullOrEmpty(language.Area.MasterArea.DomainLock))
220 {
221 hostName = language.Area.MasterArea.DomainLock; //dk.domain.com or dk-domain.dk
222 }
223 if (language != null && language.Published && language.Area.Active && language.Area.Published)
224 {
225 if (!string.IsNullOrEmpty(language.Area.DomainLock))
226 {
227 hostName = language.Area.DomainLock; //dk.domain.com or dk-domain.dk
228 }
229 string querystring = $"Default.aspx?ID={language.ID}";
230 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["GroupID"]))
231 {
232 querystring += $"&GroupID={Dynamicweb.Context.Current.Request.QueryString["GroupID"]}";
233 }
234 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["ProductID"]))
235 {
236 querystring += $"&ProductID={Dynamicweb.Context.Current.Request.QueryString["ProductID"]}";
237 }
238 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["VariantID"]))
239 {
240 querystring += $"&VariantID={Dynamicweb.Context.Current.Request.QueryString["VariantID"]}";
241 }
242
243 string friendlyUrl = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(querystring);
244 if (language.Area.RedirectFirstPage && language.ParentPageId == 0 && language.Sort == 1)
245 {
246 friendlyUrl = "/";
247 }
248 string href = $"{url.Scheme}://{hostName}{friendlyUrl}";
249
250
251 <link rel="alternate" hreflang="@language.Area.CultureInfo.Name.ToLower()" href="@href">
252 if (!alreadyWrittenTwoletterIsos.Contains(language.Area.CultureInfo.TwoLetterISOLanguageName))
253 {
254 <link rel="alternate" hreflang="@language.Area.CultureInfo.TwoLetterISOLanguageName.ToLower()" href="@href">
255 }
256 }
257 }
258 }
259 }
260
261 <title>@Model.Title</title>
262 @* Bootstrap + Swift stylesheet *@
263 <link href="/Files/Templates/Designs/Swift/Assets/css/styles.css?@cssStyleFileInfo.LastWriteTime.Ticks" rel="stylesheet" media="all" type="text/css">
264
265 @if (disableWideBreakpoints != "disableBoth")
266 {
267 <style>
268 @@media ( min-width: 1600px ) {
269 .container-xxl,
270 .container-xl,
271 .container-lg,
272 .container-md,
273 .container-sm,
274 .container {
275 max-width: 1520px;
276 }
277 }
278 </style>
279
280
281
282 if (disableWideBreakpoints != "disableUltraWideOnly")
283 {
284 <style>
285 @@media ( min-width: 1920px ) {
286 .container-xxl,
287 .container-xl,
288 .container-lg,
289 .container-md,
290 .container-sm,
291 .container {
292 max-width: 1820px;
293 }
294 }
295 </style>
296 }
297 }
298
299 @* Branding and Themes min stylesheet *@
300 <link href="/Files/Templates/Designs/Swift/_parsed/Swift_css/Swift_styles_@(Model.Area.ID).min.css?@cssLastModified.Ticks" rel="stylesheet" media="all" type="text/css" data-last-modified-content="@cssLastModified">
301 <script src="/Files/Templates/Designs/Swift/Assets/js/aos.js?@jsFileInfo.LastWriteTime.Ticks" defer></script>
302 <script src="/Files/Templates/Designs/Swift/Assets/js/scripts.js?@jsFileInfo.LastWriteTime.Ticks" defer></script>
303
304 <script type="module">
305 AOS.init({ duration: 400, delay: 100, easing: 'ease-in-out', mirror: false, disable: window.matchMedia('(prefers-reduced-motion: reduce)') });
306 swift.Scroll.hideHeadersOnScroll();
307 swift.Scroll.handleAlternativeTheme();
308 </script>
309
310 @* Google tag manager *@
311 @if (!string.IsNullOrWhiteSpace(googleTagManagerID) && allowTracking)
312 {
313 <script>
314 (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
315 new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
316 j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
317 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
318 })(window, document, 'script', 'dataLayer', '@(googleTagManagerID)');
319
320 function gtag() { dataLayer.push(arguments); }
321 </script>
322 }
323
324 @if (!string.IsNullOrWhiteSpace(googleAnalyticsMeasurementID) && allowTracking)
325 {
326 var GoogleAnalyticsDebugMode = "";
327 bool isLoggedInBackendUser = false;
328
329 if (Dynamicweb.Security.UserManagement.User.GetCurrentBackendUser() != null)
330 {
331 isLoggedInBackendUser = true;
332 }
333
334 if (Model.Area.Item.GetBoolean("EnableGoogleAnalyticsDebugMode") && isLoggedInBackendUser)
335 {
336 GoogleAnalyticsDebugMode = ", {'debug_mode': true}";
337 }
338
339 <script async src="https://www.googletagmanager.com/gtag/js?id=@googleAnalyticsMeasurementID"></script>
340 <script>
341 window.dataLayer = window.dataLayer || [];
342 function gtag() { dataLayer.push(arguments); }
343 gtag('js', new Date());
344 gtag('config', '@googleAnalyticsMeasurementID'@GoogleAnalyticsDebugMode);
345 </script>
346 }
347
348 @if (!string.IsNullOrWhiteSpace(customHeaderInclude))
349 {
350 @RenderPartial($"Components/Custom/{customHeaderInclude}")
351 }
352 </head>
353 <body class="brand @(masterTheme)" id="page@(Model.ID)">
354
355 @* Google tag manager *@
356 @if (!string.IsNullOrWhiteSpace(googleTagManagerID) && allowTracking)
357 {
358 <noscript>
359 <iframe src="https://www.googletagmanager.com/ns.html?id=@(googleTagManagerID)"
360 height="0" width="0" style="display:none;visibility:hidden"></iframe>
361 </noscript>
362 }
363
364 @if (renderAsResponsive || !renderMobile)
365 {
366 <header class="page-header @headerCssClass top-0@(responsiveClassDesktop)" id="page-header-desktop">
367 @if (@Model.Area.Item.GetLink("HeaderDesktop") != null)
368 {
369 @RenderGrid(@Model.Area.Item.GetLink("HeaderDesktop").PageId)
370 }
371 </header>
372 }
373
374 @if ((renderAsResponsive || renderMobile))
375 {
376 <header class="page-header @headerCssClass top-0@(responsiveClassMobile)" id="page-header-mobile">
377 @if (@Model.Area.Item.GetLink("HeaderMobile") != null)
378 {
379 @RenderGrid(@Model.Area.Item.GetLink("HeaderMobile").PageId)
380 }
381 </header>
382 }
383
384 <main id="content" @(schemaOrgType)>
385 <div data-intersect></div>
386 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
387 @using System
388 @using Dynamicweb.Ecommerce.ProductCatalog
389
390
391 @{
392 string productIdFromUrl = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("ProductID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("ProductID") : string.Empty;
393 bool isProductDetail = !string.IsNullOrEmpty(productIdFromUrl) && Pageview.Page.NavigationTag.ToLower() == "shop";
394
395 bool isArticlePagePage = Model.ItemType == "Swift_Article";
396 bool isArticleListPage = Model.ItemType == "Swift_ArticleListPage";
397 string schemaOrgProp = string.Empty;
398 if(isArticlePagePage)
399 {
400 schemaOrgProp = "itemprop=\"articleBody\"";
401 }
402
403 string theme = "";
404 string gridContent = "";
405
406 if (Model.PropertyItem != null)
407 {
408 theme = !string.IsNullOrWhiteSpace(Model.PropertyItem.GetRawValueString("Theme")) ? "theme " + Model.PropertyItem.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : "";
409 }
410
411 if (Model.Item != null || Pageview.IsVisualEditorMode)
412 {
413 if (!isProductDetail)
414 {
415 gridContent = Model.Grid("Grid", "Grid", "default:true;sort:1", "Page");
416 }
417 else
418 {
419 var productObject = Dynamicweb.Ecommerce.Services.Products.GetProductById(productIdFromUrl, "", Pageview.Area.EcomLanguageId);
420 var detailPage = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(productObject.PrimaryGroupId)?.Meta.PrimaryPage ?? string.Empty;
421 var detailPageId = detailPage != string.Empty ? Convert.ToInt16(detailPage.Substring(detailPage.LastIndexOf('=') + 1)) : GetPageIdByNavigationTag("ProductDetailPage");
422
423 @RenderGrid(detailPageId)
424 }
425 }
426
427 bool doNotRenderPage = false;
428
429 //Check if we are on the poduct detail page, and if there is data to render
430 ProductViewModel product = new ProductViewModel();
431 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails"))
432 {
433 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"];
434 if (string.IsNullOrEmpty(product.Id)) {
435 doNotRenderPage = true;
436 }
437 }
438
439 //Render the page
440 if (!doNotRenderPage) {
441 string itemIdentifier = Model?.Item?.SystemName != null ? "item_" + Model.Item.SystemName.ToLower() : "item_Swift_Page";
442
443
444 <div class="@theme @itemIdentifier" @schemaOrgProp>
445 @if (isArticleListPage)
446 {
447 var hx = $"hx-get=\"{Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(Model.ID)}\" hx-select=\"#content\" hx-target=\"#content\" hx-swap=\"outerHTML\" hx-trigger=\"change\" hx-headers='{{\"feed\": \"true\"}}' hx-push-url=\"true\" hx-indicator=\"#ArticleFacetForm\"";
448
449 <form @hx id="ArticleFacetForm">
450 @gridContent
451 </form>
452 <script type="module" src="/Files/Templates/Designs/Swift/Assets/js/htmx.js"></script>
453 <script type="module">
454 document.addEventListener('htmx:confirm', (event) => {
455 let filters = event.detail.elt.querySelectorAll('select');
456 for (var i = 0; i < filters.length; i++) {
457 let input = filters[i];
458 if (input.name && !input.value) {
459 input.name = '';
460 }
461 }
462 });
463
464 document.addEventListener('htmx:beforeOnLoad', (event) => {
465 swift.Scroll.stopIntersectionObserver();
466 });
467
468 document.addEventListener('htmx:afterOnLoad', () => {
469 swift.Scroll.hideHeadersOnScroll();
470 swift.Scroll.handleAlternativeTheme();
471 });
472 </script>
473 }
474 else
475 {
476 @gridContent
477 }
478 </div>
479
480 } else {
481 <div class="container">
482 <div class="alert alert-info" role="alert">@Translate("Sorry. There is nothing to view here")</div>
483 </div>
484 }
485
486 if (!Model.IsCurrentUserAllowed)
487 {
488 int signInPage = GetPageIdByNavigationTag("SignInPage");
489 int dashboardPage = GetPageIdByNavigationTag("MyAccountDashboardPage");
490
491 if (!Pageview.IsVisualEditorMode)
492 {
493 if (signInPage != 0)
494 {
495 if (signInPage != Model.ID) {
496 Dynamicweb.Context.Current.Response.Redirect("/Default.aspx?ID=" + signInPage);
497 } else {
498 if (dashboardPage != 0) {
499 Dynamicweb.Context.Current.Response.Redirect("/Default.aspx?ID=" + dashboardPage);
500 } else {
501 Dynamicweb.Context.Current.Response.Redirect("/");
502 }
503 }
504 }
505 else
506 {
507 <div class="alert alert-dark m-0" role="alert">
508 <span>@Translate("You do not have access to this page")</span>
509 </div>
510 }
511 }
512 else
513 {
514 <div class="alert alert-dark m-0" role="alert">
515 <span>@Translate("To work on this page, you must be signed in, in the frontend")</span>
516 </div>
517 }
518 }
519 }
520
521 </main>
522
523 @if (renderAsResponsive || !renderMobile)
524 {
525 <footer class="page-footer@(responsiveClassDesktop)" id="page-footer-desktop">
526 @if (@Model.Area.Item.GetLink("FooterDesktop") != null)
527 {
528 @RenderGrid(@Model.Area.Item.GetLink("FooterDesktop").PageId)
529 }
530 </footer>
531 }
532
533 @if (renderAsResponsive || renderMobile)
534 {
535 <footer class="page-footer@(responsiveClassMobile)" id="page-footer-mobile">
536 @if (@Model.Area.Item.GetLink("FooterMobile") != null)
537 {
538 @RenderGrid(@Model.Area.Item.GetLink("FooterMobile").PageId)
539 }
540 </footer>
541 }
542
543 @* Render any offcanvas menu here *@
544 @RenderSnippet("offcanvas")
545
546 @{
547 bool isErpConnectionDown = !Dynamicweb.Core.Converter.ToBoolean(Context.Current.Items["IsWebServiceConnectionAvailable"]);
548 }
549
550 @* Language selector modal *@
551 @if (languages.Count > 1 || ecomCountries.Count > 1 || ecomCurrencies.Count() > 1)
552 {
553 <div class="modal fade" id="PreferencesModal" tabindex="-1" aria-hidden="true">
554 <div class="modal-dialog modal-dialog-centered modal-sm" id="PreferencesModalContent">
555 @* The content here comes from an external request *@
556 </div>
557 </div>
558 }
559
560 @* Favorite toast *@
561 <div aria-live="polite" aria-atomic="true">
562 <div class="position-fixed bottom-0 end-0 p-3" style="z-index: 11">
563 <div id="favoriteNotificationToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
564 <div class="toast-header">
565 <strong class="me-auto">@Translate("Favorite list updated")</strong>
566 <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
567 </div>
568 <div class="toast-body d-flex gap-3">
569 <div id="favoriteNotificationToast_Image"></div>
570 <div id="favoriteNotificationToast_Text"></div>
571 </div>
572 </div>
573 </div>
574 </div>
575
576 @* Modal for dynamic content *@
577 <div class="modal fade js-product" id="DynamicModal" tabindex="-1" aria-hidden="true">
578 <div class="modal-dialog modal-dialog-centered modal-md">
579 <div class="modal-content theme light" id="DynamicModalContent">
580 @* The content here comes from an external request *@
581 </div>
582 </div>
583 </div>
584
585 @* Offcanvas for dynamic content *@
586 <div class="offcanvas offcanvas-end theme light" tabindex="-1" id="DynamicOffcanvas" style="width: 30rem">
587 @* The content here comes from an external request *@
588 </div>
589
590 @if (isErpConnectionDown && Model.Area.Item.GetBoolean("ShowErpDownMessage"))
591 {
592 string erpDownMessageTheme = !string.IsNullOrWhiteSpace(Model.Area.Item.GetRawValueString("ErpDownMessageTheme")) ? " theme " + Model.Area.Item.GetRawValueString("ErpDownMessageTheme").Replace(" ", "").Trim().ToLower() : "theme light";
593
594 <div class="position-fixed bottom-0 end-0 p-3" style="z-index: 1040">
595 <div class="toast fade show border-0 @erpDownMessageTheme" role="alert" aria-live="assertive" aria-atomic="true">
596 <div class="toast-header">
597 <strong class="me-auto">@Translate("Connection down")</strong>
598 <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
599 </div>
600 <div class="toast-body">
601 @Translate("We are experiencing some connectivity issues. Not all features may be available to you.")
602 </div>
603 </div>
604 </div>
605 }
606 </body>
607 </html>
608
609 @functions {
610 void SetMetaTags()
611 {
612 //Verification Tokens
613 string siteVerificationGoogle = Model.Area.Item.GetString("Google_Site_Verification") != null ? Model.Area.Item.GetString("Google_Site_Verification") : "";
614 //string siteVerificationYandex = Model.Area.Item.GetString("Yandex_Verification") != null ? Model.Area.Item.GetString("Yandex_Verification") : "";
615 //string siteVerificationMS = Model.Area.Item.GetString("Msvalidate_01") != null ? Model.Area.Item.GetString("Msvalidate_01") : "";
616 //string siteVerificationAlexa = Model.Area.Item.GetString("AlexaVerifyID") != null ? Model.Area.Item.GetString("AlexaVerifyID") : "";
617 //string siteVerificationPinterest = Model.Area.Item.GetString("P_domain_verify") != null ? Model.Area.Item.GetString("P_domain_verify") : "";
618 //string siteVerificationNorton = Model.Area.Item.GetString("Norton_safeweb_site_verification") != null ? Model.Area.Item.GetString("Norton_safeweb_site_verification") : "";
619
620 //Generic Site Values
621 string openGraphFacebookAppID = Model.Area.Item.GetString("Fb_app_id") != null ? Model.Area.Item.GetString("Fb_app_id") : "";
622 string openGraphType = Model.Area.Item.GetString("Open_Graph_Type") != null ? Model.Area.Item.GetString("Open_Graph_Type") : "";
623 string openGraphSiteName = Model.Area.Item.GetString("Open_Graph_Site_Name") != null ? Model.Area.Item.GetString("Open_Graph_Site_Name") : "";
624
625 string twitterCardSite = Model.Area.Item.GetString("Twitter_Site") != null ? Model.Area.Item.GetString("Twitter_Site") : "";
626
627 //Page specific values
628 string openGraphSiteTitle = Model.Area.Item.GetString("Open_Graph_Title") != null ? Model.Area.Item.GetString("Open_Graph_Title") : "";
629 FileViewModel openGraphImage = Model.Area.Item.GetFile("Open_Graph_Image");
630 string openGraphImageALT = Model.Area.Item.GetString("Open_Graph_Image_ALT") != null ? Model.Area.Item.GetString("Open_Graph_Image_ALT") : "";
631 string openGraphDescription = Model.Area.Item.GetString("Open_Graph_Description") != null ? Model.Area.Item.GetString("Open_Graph_Description") : "";
632
633 string twitterCardURL = Model.Area.Item.GetString("Twitter_URL") != null ? Model.Area.Item.GetString("Twitter_URL") : "";
634 string twitterCardTitle = Model.Area.Item.GetString("Twitter_Title") != null ? Model.Area.Item.GetString("Twitter_Title") : "";
635 string twitterCardDescription = Model.Area.Item.GetString("Twitter_Description") != null ? Model.Area.Item.GetString("Twitter_Description") : "";
636 FileViewModel twitterCardImage = Model.Area.Item.GetFile("Twitter_Image");
637 string twitterCardImageALT = Model.Area.Item.GetString("Twitter_Image_ALT") != null ? Model.Area.Item.GetString("Twitter_Image_ALT") : "";
638
639 if (!string.IsNullOrEmpty(siteVerificationGoogle))
640 {
641 Pageview.Meta.AddTag("google-site-verification", siteVerificationGoogle);
642 }
643
644 if (!string.IsNullOrEmpty(openGraphFacebookAppID))
645 {
646 Pageview.Meta.AddTag("fb:app_id", openGraphFacebookAppID);
647 }
648
649 if (!string.IsNullOrEmpty(openGraphType))
650 {
651 Pageview.Meta.AddTag("og:type", openGraphType);
652 }
653
654 if (!string.IsNullOrEmpty(openGraphSiteName))
655 {
656 Pageview.Meta.AddTag("og:site_name", openGraphSiteName);
657 }
658
659 if (!string.IsNullOrEmpty(Model.Title))
660 {
661 Pageview.Meta.AddTag("og:title", Model.Title);
662 }
663 else
664 {
665 Pageview.Meta.AddTag("og:title", openGraphSiteTitle);
666 }
667
668 if (!string.IsNullOrEmpty(Pageview.Page.TopImage) && openGraphImage == null)
669 {
670 Pageview.Meta.AddTag("og:image", Dynamicweb.Context.Current.Request.Url.Scheme + "://" + Dynamicweb.Context.Current.Request.Url.Host + Pageview.Page.TopImage);
671 }
672
673 if (string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["ProductID"]))
674 {
675 if (!string.IsNullOrEmpty(Model.Description))
676 {
677 Pageview.Meta.AddTag("og:description", Model.Description);
678 }
679 else
680 {
681 Pageview.Meta.AddTag("og:description", openGraphDescription);
682 }
683 if (openGraphImage != null)
684 {
685 Pageview.Meta.AddTag("og:image", openGraphImage.Path);
686 }
687
688 if (!string.IsNullOrEmpty(openGraphImageALT))
689 {
690 Pageview.Meta.AddTag("og:image:alt", openGraphImageALT);
691 }
692 if (!string.IsNullOrEmpty(twitterCardDescription))
693 {
694 Pageview.Meta.AddTag("twitter:description", twitterCardDescription);
695 }
696
697 if (twitterCardImage != null)
698 {
699 Pageview.Meta.AddTag("twitter:image", twitterCardImage.Path);
700 }
701
702 if (!string.IsNullOrEmpty(twitterCardImageALT))
703 {
704 Pageview.Meta.AddTag("twitter:image:alt", twitterCardImageALT);
705 }
706 }
707
708 if (!string.IsNullOrEmpty(twitterCardSite))
709 {
710 Pageview.Meta.AddTag("twitter:site", twitterCardSite);
711 }
712
713 if (!string.IsNullOrEmpty(twitterCardURL))
714 {
715 Pageview.Meta.AddTag("twitter:url", twitterCardURL);
716 }
717
718 if (!string.IsNullOrEmpty(twitterCardTitle))
719 {
720 Pageview.Meta.AddTag("twitter:title", twitterCardTitle);
721 }
722 }
723 }
724