From 215285d3c0a7cd15926275fee06a2086230cf332 Mon Sep 17 00:00:00 2001 From: Anatolii Grynchuk Date: Sat, 2 May 2026 03:29:54 +0300 Subject: [PATCH] fix: channel save tracking conflict and test modal rendering - Use AsNoTracking() on all EmailChannelRepository read methods to prevent EF identity conflict when Update() attaches a new entity with same key - Move test modal to @section Scripts rendered at end of so bootstrap.Modal is available and modal is not nested inside card DOM - Add @RenderSection('Scripts') forwarding in _EditorLayout to bubble child scripts sections up to _Layout - Switch Test button to programmatic bootstrap.Modal() open instead of data-bs-toggle (more reliable across layout section boundaries) Ref: IT-628 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Repositories/EmailChannelRepository.cs | 4 +- .../Views/AdminChannels/Edit.cshtml | 108 +++++++++--------- .../Views/Shared/_EditorLayout.cshtml | 4 + .../Views/Shared/_Layout.cshtml | 1 + 4 files changed, 63 insertions(+), 54 deletions(-) diff --git a/HrynCo.NotificationService.DAL.EF/Repositories/EmailChannelRepository.cs b/HrynCo.NotificationService.DAL.EF/Repositories/EmailChannelRepository.cs index 840bd74..bba5a2d 100644 --- a/HrynCo.NotificationService.DAL.EF/Repositories/EmailChannelRepository.cs +++ b/HrynCo.NotificationService.DAL.EF/Repositories/EmailChannelRepository.cs @@ -16,6 +16,7 @@ internal sealed class EmailChannelRepository : EfRepository, public async Task> GetAllAsync(CancellationToken ct = default) { var entities = await DbSet + .AsNoTracking() .OrderBy(x => x.ServiceName) .ThenBy(x => x.Priority) .ToListAsync(ct); @@ -26,6 +27,7 @@ internal sealed class EmailChannelRepository : EfRepository, public async Task> GetByServiceAsync(string serviceName, CancellationToken ct = default) { var entities = await DbSet + .AsNoTracking() .Where(x => x.ServiceName == serviceName) .OrderBy(x => x.Priority) .ToListAsync(ct); @@ -35,7 +37,7 @@ internal sealed class EmailChannelRepository : EfRepository, public async Task GetByIdAsync(Guid id, CancellationToken ct = default) { - EmailChannelEntity? entity = await DbSet.FindAsync([id], ct); + EmailChannelEntity? entity = await DbSet.AsNoTracking().FirstOrDefaultAsync(x => x.Id == id, ct); return entity is null ? null : MapToDomain(entity); } diff --git a/HrynCo.NotificationService.Web/Views/AdminChannels/Edit.cshtml b/HrynCo.NotificationService.Web/Views/AdminChannels/Edit.cshtml index 7beb11c..6c76202 100644 --- a/HrynCo.NotificationService.Web/Views/AdminChannels/Edit.cshtml +++ b/HrynCo.NotificationService.Web/Views/AdminChannels/Edit.cshtml @@ -123,7 +123,7 @@ @if (!Model.IsNew) { - } @@ -135,62 +135,64 @@ @if (!Model.IsNew) { - + +@section Scripts { + @RenderSection("Scripts", required: false) +} diff --git a/HrynCo.NotificationService.Web/Views/Shared/_Layout.cshtml b/HrynCo.NotificationService.Web/Views/Shared/_Layout.cshtml index 39b28bd..8a20aec 100644 --- a/HrynCo.NotificationService.Web/Views/Shared/_Layout.cshtml +++ b/HrynCo.NotificationService.Web/Views/Shared/_Layout.cshtml @@ -51,5 +51,6 @@ + @RenderSection("Scripts", required: false)