Error executing template "Designs/Swift/Swift_Email/Paragraph/Swift_EmailProductCatalog.cshtml"
System.Exception: The Client Secret is expired. Visit the Azure portal to create new keys for your '6945a908-9a4b-44fa-9ced-6fa84bd4a866' app. GetTokenForClientCredentialsFlow failed: A configuration issue is preventing authentication - check the error message from the server for details. You can modify the configuration in the application registration portal. See https://aka.ms/msal-net-invalid-client for details. Original exception: AADSTS7000222: The provided client secret keys for app '6945a908-9a4b-44fa-9ced-6fa84bd4a866' are expired. Visit the Azure portal to create new keys for your app: https://aka.ms/NewClientSecret, or consider using certificate credentials for added security: https://aka.ms/certCreds. Trace ID: 8e8c83fe-d6a6-4fef-bace-118606021b00 Correlation ID: 5cd5d10e-23b7-436d-b371-4ca0fd73c076 Timestamp: 2025-08-19 08:47:07Z. Tenant:7dd45d63-24fc-4edd-8ad8-5fd66b6f9733 Client:6945a908-9a4b-44fa-9ced-6fa84bd4a866.
---> MSAL.NetCore.4.61.3.0.MsalServiceException:
ErrorCode: invalid_client
Microsoft.Identity.Client.MsalServiceException: A configuration issue is preventing authentication - check the error message from the server for details. You can modify the configuration in the application registration portal. See https://aka.ms/msal-net-invalid-client for details. Original exception: AADSTS7000222: The provided client secret keys for app '6945a908-9a4b-44fa-9ced-6fa84bd4a866' are expired. Visit the Azure portal to create new keys for your app: https://aka.ms/NewClientSecret, or consider using certificate credentials for added security: https://aka.ms/certCreds. Trace ID: 8e8c83fe-d6a6-4fef-bace-118606021b00 Correlation ID: 5cd5d10e-23b7-436d-b371-4ca0fd73c076 Timestamp: 2025-08-19 08:47:07Z
at Microsoft.Identity.Client.OAuth2.OAuth2Client.ThrowServerException(HttpResponse response, RequestContext requestContext)
at Microsoft.Identity.Client.OAuth2.OAuth2Client.CreateResponse[T](HttpResponse response, RequestContext requestContext)
at Microsoft.Identity.Client.OAuth2.OAuth2Client.ExecuteRequestAsync[T](Uri endPoint, HttpMethod method, RequestContext requestContext, Boolean expectErrorsOn200OK, Boolean addCommonHeaders, Func`2 onBeforePostRequestData)
at Microsoft.Identity.Client.OAuth2.TokenClient.SendHttpAndClearTelemetryAsync(String tokenEndpoint, ILoggerAdapter logger)
at Microsoft.Identity.Client.OAuth2.TokenClient.SendHttpAndClearTelemetryAsync(String tokenEndpoint, ILoggerAdapter logger)
at Microsoft.Identity.Client.OAuth2.TokenClient.SendTokenRequestAsync(IDictionary`2 additionalBodyParameters, String scopeOverride, String tokenEndpointOverride, CancellationToken cancellationToken)
at Microsoft.Identity.Client.Internal.Requests.RequestBase.SendTokenRequestAsync(IDictionary`2 additionalBodyParameters, CancellationToken cancellationToken)
at Microsoft.Identity.Client.Internal.Requests.ClientCredentialRequest.GetAccessTokenAsync(CancellationToken cancellationToken, ILoggerAdapter logger)
at Microsoft.Identity.Client.Internal.Requests.ClientCredentialRequest.ExecuteAsync(CancellationToken cancellationToken)
at Microsoft.Identity.Client.Internal.Requests.RequestBase.<>c__DisplayClass11_1.<<RunAsync>b__1>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.Identity.Client.Utils.StopwatchService.MeasureCodeBlockAsync(Func`1 codeBlock)
at Microsoft.Identity.Client.Internal.Requests.RequestBase.RunAsync(CancellationToken cancellationToken)
at Microsoft.Identity.Client.ApiConfig.Executors.ConfidentialClientExecutor.ExecuteAsync(AcquireTokenCommonParameters commonParameters, AcquireTokenForClientParameters clientParameters, CancellationToken cancellationToken)
StatusCode: 401
ResponseBody: {"error":"invalid_client","error_description":"AADSTS7000222: The provided client secret keys for app '6945a908-9a4b-44fa-9ced-6fa84bd4a866' are expired. Visit the Azure portal to create new keys for your app: https://aka.ms/NewClientSecret, or consider using certificate credentials for added security: https://aka.ms/certCreds. Trace ID: 8e8c83fe-d6a6-4fef-bace-118606021b00 Correlation ID: 5cd5d10e-23b7-436d-b371-4ca0fd73c076 Timestamp: 2025-08-19 08:47:07Z","error_codes":[7000222],"timestamp":"2025-08-19 08:47:07Z","trace_id":"8e8c83fe-d6a6-4fef-bace-118606021b00","correlation_id":"5cd5d10e-23b7-436d-b371-4ca0fd73c076","error_uri":"https://login.microsoftonline.com/error?code=7000222"}
Headers: Cache-Control: no-store, no-cache
Pragma: no-cache
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
P3P: CP="DSP CUR OTPi IND OTRi ONL FIN"
client-request-id: 5cd5d10e-23b7-436d-b371-4ca0fd73c076
x-ms-request-id: 8e8c83fe-d6a6-4fef-bace-118606021b00
x-ms-ests-server: 2.1.21665.5 - WEULR1 ProdSlices
x-ms-clitelem: 1,7000222,0,,
x-ms-srs: 1.P
Content-Security-Policy-Report-Only: object-src 'none'; base-uri 'self'; script-src 'self' 'nonce-UXLnxAJGJMcmH7pcngLdFg' 'unsafe-inline' 'unsafe-eval' https://*.msauth.net https://*.msftauth.net https://*.msftauthimages.net https://*.msauthimages.net https://*.msidentity.com https://*.microsoftonline-p.com https://*.microsoftazuread-sso.com https://*.azureedge.net https://*.outlook.com https://*.office.com https://*.office365.com https://*.microsoft.com https://*.bing.com 'report-sample'; report-uri https://csp.microsoft.com/report/ESTS-UX-All
X-XSS-Protection: 0
Set-Cookie: fpc=AqU8-QeNwIJMlti2wh4SU5J1fVnmEAAAAKUwNuAOAAAA; expires=Thu, 18-Sep-2025 08:47:07 GMT; path=/; secure; HttpOnly; SameSite=None, x-ms-gateway-slice=estsfd; path=/; secure; httponly
Date: Tue, 19 Aug 2025 08:47:07 GMT
--- End of inner exception stack trace ---
at Dynamicweb.DataIntegration.EndpointManagement.EndpointService.HandleException(Exception ex, Endpoint endpoint) in C:\Work\Repos\Dynamicweb10\src\Features\DataIntegration\Dynamicweb.DataIntegration\EndpointManagement\EndpointService.cs:line 668
at Dynamicweb.DataIntegration.EndpointManagement.EndpointService.GetResponse(Endpoint endpoint, String requestBody, TimeSpan requestTimeout) in C:\Work\Repos\Dynamicweb10\src\Features\DataIntegration\Dynamicweb.DataIntegration\EndpointManagement\EndpointService.cs:line 533
at DynamicwebLiveIntegration3.EndpointManager.ExecuteEndpointRequest(String urlSuffix, Object requestBody)
at DynamicwebLiveIntegration3.Caching.StockCache.FetchMissing(IEnumerable`1 keys)
at Dynamicweb.Caching.ServiceCache`2.GetCache(IEnumerable`1 keys) in C:\Work\Repos\Dynamicweb10\src\Core\Dynamicweb.Core\Caching\ServiceCache.cs:line 267
at Dynamicweb.Caching.ServiceCache`2.GetCache(TKey key) in C:\Work\Repos\Dynamicweb10\src\Core\Dynamicweb.Core\Caching\ServiceCache.cs:line 254
at DynamicwebLiveIntegration3.LiveIntegrationService.GetStock(ProductStockCacheKey productStockCacheKey, Boolean silent)
at DynamicwebLiveIntegration3.Providers.ProductStockProvider.FindStockLevel(Product product, String unitId, StockLocation stockLocation)
at Dynamicweb.Ecommerce.Stocks.StockLevelManager.FindStockLevel(Product product, String unitId, StockLocation stockLocation) in C:\Work\Repos\Dynamicweb10\src\Features\Ecommerce\Dynamicweb.Ecommerce\Stocks\StockLevelManager.cs:line 25
at Dynamicweb.Ecommerce.Products.ProductExtentions.GetUnitStock(Product product, StockLocation stockLocation, String unitId) in C:\Work\Repos\Dynamicweb10\src\Features\Ecommerce\Dynamicweb.Ecommerce\Products\ProductExtentions.cs:line 187
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
at System.Lazy`1.CreateValue()
at Dynamicweb.Ecommerce.ProductCatalog.ViewModelPropertyFiller`1.Fill[S](T model, String propertyName, Func`1 source) in C:\Work\Repos\Dynamicweb10\src\Features\Ecommerce\Dynamicweb.Ecommerce\ProductCatalog\ViewModelPropertyFiller.cs:line 49
at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.BulkCreateView(ProductViewModelSettings settings, Boolean isRecursive, IList`1 products) in C:\Work\Repos\Dynamicweb10\src\Features\Ecommerce\Dynamicweb.Ecommerce\ProductCatalog\ViewEngine.cs:line 128
at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.CreateView(ProductListViewModelSettings settings, Group group, IList`1 products) in C:\Work\Repos\Dynamicweb10\src\Features\Ecommerce\Dynamicweb.Ecommerce\ProductCatalog\ViewEngine.cs:line 586
at Dynamicweb.Ecommerce.ProductCatalog.ViewModelFactory.CreateView(ProductListViewModelSettings settings, IList`1 products, Group group) in C:\Work\Repos\Dynamicweb10\src\Features\Ecommerce\Dynamicweb.Ecommerce\ProductCatalog\ViewModelFactory.cs:line 197
at Dynamicweb.Ecommerce.Content.Items.Editors.ProductCatalogEditor.GetViewModelValue(Object value) in C:\Work\Repos\Dynamicweb10\src\Features\Ecommerce\Dynamicweb.Ecommerce\Content\Items\Editors\ProductCatalogEditor.cs:line 55
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
at System.Lazy`1.CreateValue()
at Dynamicweb.Frontend.ItemViewModel.GetValue(String systemName) in C:\Work\Repos\Dynamicweb10\src\Features\Content\Dynamicweb\Frontend\ItemViewModel.cs:line 738
at CompiledRazorTemplates.Dynamic.RazorEngine_b3228ad74a3f41f1b163d6907095c296.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.DynamicWrapperService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass23_0.<Run>b__0(TextWriter writer)
at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag)
at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template) in /_/src/Application/Providers/Dynamicweb.Rendering.Providers.NetCore/Razor/RazorTemplateRenderingProvider.cs:line 100
at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template) in C:\Work\Repos\Dynamicweb10\src\Core\Dynamicweb.Core\Rendering\TemplateRenderingService.cs:line 22
at Dynamicweb.Rendering.Template.RenderRazorTemplate() in C:\Work\Repos\Dynamicweb10\src\Core\Dynamicweb.Core\Rendering\Template.cs:line 694
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel>
@using Dynamicweb.Ecommerce.ProductCatalog
@functions {
private string GetFontStack()
{
return "font-family:initial,Arial,Helvetica Neue,Helvetica,sans-serif;";
}
private string GetTableReset()
{
return "border:0;margin:0;outline:0;padding:0;";
}
public Dynamicweb.Frontend.ColorViewModel GetMutedColor(string hex, int percent, double threshold = 0.5)
{
/// <summary>
/// Return a color in either lighter or darker contrast based on the original color luminance.
/// </summary>
/// <param name="percent">The percent (1-100) to darken or light the color with - higher percentage will give higher contrast</param>
/// <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>
/// <returns>A new color viewmodel with the contrasted color in either darker or lighter luminance compared to base color</returns>
///
if (threshold > 1)
threshold = 1;
if (threshold < 0)
threshold = 0;
var color = Dynamicweb.Imaging.Colors.Color.FromHex(hex);
var luminance = (0.2126 * color.BaseColor.R) + (0.7152 * color.BaseColor.G) + (0.0722 * color.BaseColor.B);
/// == luminance = 0 is black, luminance = 1 is white == //
luminance = color.Brightness / 255;
if (luminance < threshold)
{
return new Dynamicweb.Frontend.ColorViewModel() { Hex = color.Lighten(percent).ToHex() };
}
else
{
return new Dynamicweb.Frontend.ColorViewModel() { Hex = color.Darken(percent).ToHex() };
}
}
}
@{
string blockType = "productcatalog_block";
var page = Dynamicweb.Content.Services.Pages.GetPage(Model.PageID);
var settings = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(page?.Parent).Item;
var blockId = Model.ID;
var block = Model.Item;
var emailContentThemeId = settings.GetRawValueString("EmailContentTheme");
var emailContentThemeParagraph = emailContentThemeId != null && emailContentThemeId != string.Empty ? Dynamicweb.Content.Services.Paragraphs.GetParagraph(Dynamicweb.Core.Converter.ToInt32(emailContentThemeId)) : null;
var emailContentTheme = emailContentThemeParagraph != null && Dynamicweb.Frontend.ContentViewModelFactory.CreateParagraphInfoViewModel(emailContentThemeParagraph).Item.GetString("CssClassName") != string.Empty ? Dynamicweb.Frontend.ContentViewModelFactory.CreateParagraphInfoViewModel(emailContentThemeParagraph)?.Item : null;
var rowId = Dynamicweb.Content.Services.Paragraphs.GetParagraph(blockId).GridRowId;
var row = Dynamicweb.Content.Services.Grids.GetGridRowById(rowId);
var rowItem = Dynamicweb.Content.Services.Items.GetItem(row.ItemType, row.ItemId);
var rowThemeId = Dynamicweb.Core.Converter.ToString(rowItem["ColumnBackground"]);
var rowThemeParagraph = rowThemeId != null && rowThemeId != string.Empty ? Dynamicweb.Content.Services.Paragraphs.GetParagraph(Dynamicweb.Core.Converter.ToInt32(rowThemeId)) : null;
var rowTheme = rowThemeParagraph != null && Dynamicweb.Frontend.ContentViewModelFactory.CreateParagraphInfoViewModel(rowThemeParagraph).Item.GetString("CssClassName") != string.Empty ? Dynamicweb.Frontend.ContentViewModelFactory.CreateParagraphInfoViewModel(rowThemeParagraph)?.Item : null;
var blockThemeId = block.GetRawValueString("Theme");
var blockThemeParagraph = blockThemeId != null && blockThemeId != string.Empty ? Dynamicweb.Content.Services.Paragraphs.GetParagraph(Dynamicweb.Core.Converter.ToInt32(blockThemeId)) : null;
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;
string backgroundColor = blockTheme != null ? "background-color: " + blockTheme.GetString("BackgroundColor") + ";" : string.Empty;
string foregroundColor = blockTheme != null ? "color:" + blockTheme.GetString("ForegroundColor", "inherit") + ";" : string.Empty;
string title = block.GetString("Title", string.Empty);
int padding = Dynamicweb.Core.Converter.ToInt32(block.GetRawValueString("Padding", "0"));
int cellSpacing = 8;
string align = block.GetRawValueString("Align", "left");
string text = block.GetString("Text", string.Empty);
var layoutColumns = Dynamicweb.Core.Converter.ToInt32(block.GetRawValueString("Layout", "2"));
int layout = Dynamicweb.Core.Converter.ToInt32(Model.Item.GetRawValueString("Layout", "2"));
var imageRatio = Model.Item.GetRawValueString("ImageAspectRatio", "4-3").ToLower();
var imageParms = new Dictionary<string, object>();
imageParms.Add("alt", "");
imageParms.Add("columns", layout);
imageParms.Add("gridColumns", Model.GridRowColumnCount);
imageParms.Add("nested", Model.GridRowColumnCount > 1);
imageParms.Add("padding", (padding * 2) + (8 * (layout - 1)));
imageParms.Add("imageRatio", imageRatio);
ProductListViewModel selectedProducts = block?.GetValue("Products") as ProductListViewModel;
IList<ProductViewModel> products = selectedProducts?.Products;
}
<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)">
<tbody>
<tr style="@GetTableReset()">
<td style="@GetTableReset()padding:@(padding)px">
<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%;">
<tbody>
@if (products is object && products.Any())
{
@:<tr style="@GetTableReset()">
int index = 1;
int totalProducts = products.Count();
foreach (var product in products)
{
var cellForegroundColor = blockTheme?.GetColor("ForegroundColor");
string link = product.GetProductLink(GetPageIdByNavigationTag("Shop"), false);
var uri = Dynamicweb.Context.Current.Request.Url;
var hostname = uri.Scheme + Uri.SchemeDelimiter + uri.Host;
bool hideProductPrice = Model.Item?.GetBoolean("HideProductPrice") ?? false;
bool hideProductNumber = Model.Item?.GetBoolean("HideProductNumber") ?? false;
<td valign="top" style="@GetTableReset()@GetFontStack()">
<table style="border-collapse:collapse;table-layout:fixed;@GetTableReset()" cellpadding="0" cellspacing="0" width="100%" role="presentation">
<tbody>
<tr style="@GetTableReset()">
<td style="@GetTableReset()">
<div align="center" style="font-size:2px;">
<a style="text-decoration:none;" href="@link" target="_blank">
@if (product.DefaultImage is object)
{
imageParms["alt"] = product.Name;
@RenderPartial("Swift_Email/Components/Image.cshtml", new Dynamicweb.Frontend.FileViewModel() { Name = product.Name, Path = product.DefaultImage.Value }, imageParms);
}
</a>
</div>
<table style="border-collapse:collapse;table-layout:fixed;@GetTableReset()" cellpadding="0" cellspacing="0" width="100%" role="presentation">
<tbody>
<tr style="@GetTableReset()">
<td style="@GetTableReset()padding-top:8px;text-align:@align;line-height:18px;font-size:13px;text-decoration:none;color:@cellForegroundColor;">
<a style="text-decoration:none;color:@cellForegroundColor;@GetTableReset()@GetFontStack()" href="@link" target="_blank">
@product.Name
</a>
</td>
</tr>
@if (!hideProductNumber)
{
<tr>
<td style="@GetTableReset()@GetFontStack()padding-top:8px;text-align:@align;line-height:18px;font-size:11px;color:@(GetMutedColor(cellForegroundColor.Hex, 20));">
@product.Number
</td>
</tr>
}
@if (!hideProductPrice)
{
<tr>
<td style="@GetTableReset()@GetFontStack()padding-top:8px;text-align:@align;line-height:13px;font-size:13px;break-inside:avoid;word-break:keep-all;white-space:nowrap;color:@(cellForegroundColor);">
@product.Price.PriceFormatted
@if (product.Discount.Price > 0)
{
<span style="line-height:13px;font-size:13px;text-decoration:line-through;break-inside:avoid;word-break:keep-all;white-space:nowrap;color:@(GetMutedColor(cellForegroundColor.Hex, 20));">@product.PriceBeforeDiscount.PriceFormatted</span>
}
</td>
</tr>
}
<tr><td height="24" style="padding-top:24px;"></td></tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
if (index % layoutColumns == 0 && !(index == totalProducts))
{
@:</tr>
@:<tr style="@GetTableReset()">
@:<td style="@GetTableReset()" colspan="100%" height="@(cellSpacing * 4)"> </td>
@:</tr>
@:<tr style="@GetTableReset()">
}
else
{
if(!(index == totalProducts))
{
@:<td width="@(cellSpacing)" style="@GetTableReset()"> </td>
}
}
index++;
}
@:</tr>
}
else
{
if (Pageview.IsVisualEditorMode)
{
<tr style="@GetTableReset()@GetFontStack()">
<td style="@(foregroundColor)">@Translate("No products selected")</td>
</tr>
}
}
</tbody>
</table>
<!--[if mso]><br/><![endif]-->
</td>
</tr>
</tbody>
</table>
|