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 <body> 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>
This commit is contained in:
Anatolii Grynchuk
2026-05-02 03:29:54 +03:00
parent b5214973ce
commit 215285d3c0
4 changed files with 63 additions and 54 deletions
@@ -16,6 +16,7 @@ internal sealed class EmailChannelRepository : EfRepository<EmailChannelEntity>,
public async Task<IReadOnlyList<EmailChannel>> 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<EmailChannelEntity>,
public async Task<IReadOnlyList<EmailChannel>> 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<EmailChannelEntity>,
public async Task<EmailChannel?> 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);
}
@@ -123,7 +123,7 @@
</button>
@if (!Model.IsNew)
{
<button type="button" class="btn btn-success" data-bs-toggle="modal" data-bs-target="#testModal">
<button type="button" class="btn btn-success" onclick="new bootstrap.Modal(document.getElementById('testModal')).show()">
<i class="bi bi-send me-1"></i> Test
</button>
}
@@ -135,6 +135,7 @@
@if (!Model.IsNew)
{
@section Scripts {
<div class="modal fade" id="testModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
@@ -194,3 +195,4 @@
}
</script>
}
}
@@ -14,3 +14,7 @@
</div>
</div>
</div>
@section Scripts {
@RenderSection("Scripts", required: false)
}
@@ -51,5 +51,6 @@
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-YvpcrYf0tY3lHB60NNkmXc4s9bIOgUxi8T/jzmGBE+rYG8O9HP+CyEb1BQGE8B8Z"
crossorigin="anonymous"></script>
@RenderSection("Scripts", required: false)
</body>
</html>