fix(web): include PublicationMode/IsMembersOnly in showcase SQL to fix /showcase 500
PR Checks / test-and-build (pull_request) Successful in 8m17s

Dapper.AOT generated a 19-parameter ctor for ShowcaseSessionRow based on the
SELECT list in GetShowcaseSessionsAsync / GetShowcaseSessionAsync. After
adding PublicationMode and IsMembersOnly to ShowcaseSessionDto in v3.7.0 the
record itself was extended, but the SELECT still returned 19 columns, so the
materializer threw "A parameterless default constructor or one matching
signature (...) is required" and every request to /showcase returned 500.

Add s.publication_mode and (s.publication_mode = 'ClubOnly') to both SELECT
lists and propagate them through the ShowcaseSessionDto construction. The
field list now matches the generated constructor exactly.

Version bump 3.7.0 -> 3.7.1 (patch).
This commit is contained in:
2026-06-03 22:21:31 +03:00
parent 6951c72f3c
commit 29f6f6a827
6 changed files with 17 additions and 13 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ on:
- main - main
env: env:
VERSION: 3.7.0 VERSION: 3.7.1
jobs: jobs:
# ЧАСТЬ 1: Собираем образы и кладем в Gitea (чтобы делиться с ребятами) # ЧАСТЬ 1: Собираем образы и кладем в Gitea (чтобы делиться с ребятами)
+1 -1
View File
@@ -1,6 +1,6 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<Version>3.7.0</Version> <Version>3.7.1</Version>
<TargetFramework>net10.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<LangVersion>preview</LangVersion> <LangVersion>preview</LangVersion>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
+3 -3
View File
@@ -49,7 +49,7 @@ services:
crond -f crond -f
bot: bot:
image: git.codeanddice.ru/toutsu/gmrelay-bot:3.7.0 image: git.codeanddice.ru/toutsu/gmrelay-bot:3.7.1
restart: always restart: always
depends_on: depends_on:
db: db:
@@ -67,7 +67,7 @@ services:
retries: 3 retries: 3
discord: discord:
image: git.codeanddice.ru/toutsu/gmrelay-discord-bot:3.7.0 image: git.codeanddice.ru/toutsu/gmrelay-discord-bot:3.7.1
restart: always restart: always
depends_on: depends_on:
db: db:
@@ -86,7 +86,7 @@ services:
retries: 3 retries: 3
web: web:
image: git.codeanddice.ru/toutsu/gmrelay-web:3.7.0 image: git.codeanddice.ru/toutsu/gmrelay-web:3.7.1
restart: always restart: always
depends_on: depends_on:
db: db:
@@ -82,7 +82,7 @@
</button> </button>
</form> </form>
<div class="nav-version">v3.7.0</div> <div class="nav-version">v3.7.1</div>
</div> </div>
</Authorized> </Authorized>
<NotAuthorized> <NotAuthorized>
+10 -6
View File
@@ -470,7 +470,9 @@ public sealed class SessionService(
s.allow_direct_registration AS AllowDirectRegistration, s.allow_direct_registration AS AllowDirectRegistration,
s.description AS Description, s.description AS Description,
mp.public_slug AS MasterProfileSlug, mp.public_slug AS MasterProfileSlug,
mp.display_name AS MasterDisplayName mp.display_name AS MasterDisplayName,
s.publication_mode AS PublicationMode,
(s.publication_mode = 'ClubOnly') AS IsMembersOnly
FROM sessions s FROM sessions s
JOIN game_groups g ON g.id = s.group_id JOIN game_groups g ON g.id = s.group_id
LEFT JOIN LATERAL ( LEFT JOIN LATERAL (
@@ -548,8 +550,8 @@ public sealed class SessionService(
r.System, r.IsOneShot, r.Format, r.DurationMinutes, r.CoverImageUrl, r.System, r.IsOneShot, r.Format, r.DurationMinutes, r.CoverImageUrl,
r.MaxPlayers, r.ActivePlayerCount, r.WaitlistedPlayerCount, r.AllowDirectRegistration, r.MaxPlayers, r.ActivePlayerCount, r.WaitlistedPlayerCount, r.AllowDirectRegistration,
r.Description, r.Description,
PublicationMode: "Catalog", PublicationMode: r.PublicationMode,
IsMembersOnly: false, IsMembersOnly: r.IsMembersOnly,
r.MasterProfileSlug, r.MasterDisplayName)).ToList(); r.MasterProfileSlug, r.MasterDisplayName)).ToList();
} }
@@ -576,7 +578,9 @@ public sealed class SessionService(
s.allow_direct_registration AS AllowDirectRegistration, s.allow_direct_registration AS AllowDirectRegistration,
s.description AS Description, s.description AS Description,
mp.public_slug AS MasterProfileSlug, mp.public_slug AS MasterProfileSlug,
mp.display_name AS MasterDisplayName mp.display_name AS MasterDisplayName,
s.publication_mode AS PublicationMode,
(s.publication_mode = 'ClubOnly') AS IsMembersOnly
FROM sessions s FROM sessions s
JOIN game_groups g ON g.id = s.group_id JOIN game_groups g ON g.id = s.group_id
LEFT JOIN LATERAL ( LEFT JOIN LATERAL (
@@ -636,8 +640,8 @@ public sealed class SessionService(
row.System, row.IsOneShot, row.Format, row.DurationMinutes, row.CoverImageUrl, row.System, row.IsOneShot, row.Format, row.DurationMinutes, row.CoverImageUrl,
row.MaxPlayers, row.ActivePlayerCount, row.WaitlistedPlayerCount, row.AllowDirectRegistration, row.MaxPlayers, row.ActivePlayerCount, row.WaitlistedPlayerCount, row.AllowDirectRegistration,
row.Description, row.Description,
PublicationMode: "Catalog", PublicationMode: row.PublicationMode,
IsMembersOnly: false, IsMembersOnly: row.IsMembersOnly,
row.MasterProfileSlug, row.MasterDisplayName); row.MasterProfileSlug, row.MasterDisplayName);
} }
@@ -15,7 +15,7 @@ public sealed class CampaignTemplatesNavigationTests
public async Task NavMenu_ShouldExposeCurrentProjectVersion() public async Task NavMenu_ShouldExposeCurrentProjectVersion()
{ {
var navMenu = await File.ReadAllTextAsync(FindRepositoryFile("src/GmRelay.Web/Components/Layout/NavMenu.razor")); var navMenu = await File.ReadAllTextAsync(FindRepositoryFile("src/GmRelay.Web/Components/Layout/NavMenu.razor"));
Assert.Contains("v3.7.0", navMenu, StringComparison.Ordinal); Assert.Contains("v3.7.1", navMenu, StringComparison.Ordinal);
} }
[Fact] [Fact]