From fd4e6d1cce8bd55d68b00f0227e94118dd5da4c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20K=C3=BCsters?= Date: Wed, 10 Jul 2024 12:05:40 +0200 Subject: [PATCH 1/4] fix: improved error handling in remote processing --- src/Wemogy.Cqrs.sln | 322 +++++++++--------- src/core/Wemogy.CQRS/Wemogy.CQRS.csproj | 2 +- .../ThrowError/ThrowErrorCommandHandler.cs | 35 +- .../CommandEndpointBaseExceptionTests.cs | 50 +++ .../PostProcessorContextExtensionsTests.cs | 71 ++++ ....Extensions.FastEndpoints.UnitTests.csproj | 1 + .../Endpoints/CommandEndpointBase`1.cs | 2 + .../Endpoints/CommandEndpointBase`2.cs | 2 + .../Endpoints/QueryEndpointBase.cs | 2 + .../EndpointDefinitionExtensions.cs | 3 +- .../ExceptionInformationExtensions.cs | 16 - .../PostProcessorContextExtensions.cs | 18 + .../CqrsEndpointExceptionPostProcessor`1.cs | 5 + .../CqrsEndpointExceptionPostProcessor`2.cs | 28 ++ .../ErrorHandlerPostProcessor.cs | 2 +- .../HttpRemoteCommandRunner`1.cs | 12 +- .../HttpRemoteCommandRunner`2.cs | 21 +- .../HttpRemoteQueryRunner.cs | 25 +- src/switcher.json | 2 +- 19 files changed, 419 insertions(+), 200 deletions(-) create mode 100644 src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests/Endpoints/CommandEndpointBaseExceptionTests.cs create mode 100644 src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests/Extensions/PostProcessorContextExtensionsTests.cs delete mode 100644 src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Extensions/ExceptionInformationExtensions.cs create mode 100644 src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Extensions/PostProcessorContextExtensions.cs create mode 100644 src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/PostProcessors/CqrsEndpointExceptionPostProcessor`1.cs create mode 100644 src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/PostProcessors/CqrsEndpointExceptionPostProcessor`2.cs diff --git a/src/Wemogy.Cqrs.sln b/src/Wemogy.Cqrs.sln index 22f168c..8d41b72 100644 --- a/src/Wemogy.Cqrs.sln +++ b/src/Wemogy.Cqrs.sln @@ -36,165 +36,165 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wemogy.CQRS.UnitTests.AssemblyB", "core\Wemogy.CQRS.UnitTests.AssemblyB\Wemogy.CQRS.UnitTests.AssemblyB.csproj", "{D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}" EndProject Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Debug|x64.ActiveCfg = Debug|Any CPU - {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Debug|x64.Build.0 = Debug|Any CPU - {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Debug|x86.ActiveCfg = Debug|Any CPU - {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Debug|x86.Build.0 = Debug|Any CPU - {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Release|Any CPU.Build.0 = Release|Any CPU - {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Release|x64.ActiveCfg = Release|Any CPU - {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Release|x64.Build.0 = Release|Any CPU - {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Release|x86.ActiveCfg = Release|Any CPU - {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Release|x86.Build.0 = Release|Any CPU - {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Debug|x64.ActiveCfg = Debug|Any CPU - {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Debug|x64.Build.0 = Debug|Any CPU - {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Debug|x86.ActiveCfg = Debug|Any CPU - {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Debug|x86.Build.0 = Debug|Any CPU - {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Release|Any CPU.Build.0 = Release|Any CPU - {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Release|x64.ActiveCfg = Release|Any CPU - {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Release|x64.Build.0 = Release|Any CPU - {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Release|x86.ActiveCfg = Release|Any CPU - {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Release|x86.Build.0 = Release|Any CPU - {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Debug|x64.ActiveCfg = Debug|Any CPU - {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Debug|x64.Build.0 = Debug|Any CPU - {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Debug|x86.ActiveCfg = Debug|Any CPU - {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Debug|x86.Build.0 = Debug|Any CPU - {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Release|Any CPU.Build.0 = Release|Any CPU - {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Release|x64.ActiveCfg = Release|Any CPU - {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Release|x64.Build.0 = Release|Any CPU - {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Release|x86.ActiveCfg = Release|Any CPU - {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Release|x86.Build.0 = Release|Any CPU - {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Debug|x64.ActiveCfg = Debug|Any CPU - {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Debug|x64.Build.0 = Debug|Any CPU - {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Debug|x86.ActiveCfg = Debug|Any CPU - {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Debug|x86.Build.0 = Debug|Any CPU - {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Release|Any CPU.Build.0 = Release|Any CPU - {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Release|x64.ActiveCfg = Release|Any CPU - {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Release|x64.Build.0 = Release|Any CPU - {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Release|x86.ActiveCfg = Release|Any CPU - {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Release|x86.Build.0 = Release|Any CPU - {72D23525-0519-4655-8BC5-E9158CD27E10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {72D23525-0519-4655-8BC5-E9158CD27E10}.Debug|Any CPU.Build.0 = Debug|Any CPU - {72D23525-0519-4655-8BC5-E9158CD27E10}.Debug|x64.ActiveCfg = Debug|Any CPU - {72D23525-0519-4655-8BC5-E9158CD27E10}.Debug|x64.Build.0 = Debug|Any CPU - {72D23525-0519-4655-8BC5-E9158CD27E10}.Debug|x86.ActiveCfg = Debug|Any CPU - {72D23525-0519-4655-8BC5-E9158CD27E10}.Debug|x86.Build.0 = Debug|Any CPU - {72D23525-0519-4655-8BC5-E9158CD27E10}.Release|Any CPU.ActiveCfg = Release|Any CPU - {72D23525-0519-4655-8BC5-E9158CD27E10}.Release|Any CPU.Build.0 = Release|Any CPU - {72D23525-0519-4655-8BC5-E9158CD27E10}.Release|x64.ActiveCfg = Release|Any CPU - {72D23525-0519-4655-8BC5-E9158CD27E10}.Release|x64.Build.0 = Release|Any CPU - {72D23525-0519-4655-8BC5-E9158CD27E10}.Release|x86.ActiveCfg = Release|Any CPU - {72D23525-0519-4655-8BC5-E9158CD27E10}.Release|x86.Build.0 = Release|Any CPU - {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Debug|x64.ActiveCfg = Debug|Any CPU - {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Debug|x64.Build.0 = Debug|Any CPU - {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Debug|x86.ActiveCfg = Debug|Any CPU - {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Debug|x86.Build.0 = Debug|Any CPU - {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Release|Any CPU.Build.0 = Release|Any CPU - {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Release|x64.ActiveCfg = Release|Any CPU - {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Release|x64.Build.0 = Release|Any CPU - {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Release|x86.ActiveCfg = Release|Any CPU - {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Release|x86.Build.0 = Release|Any CPU - {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Debug|x64.ActiveCfg = Debug|Any CPU - {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Debug|x64.Build.0 = Debug|Any CPU - {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Debug|x86.ActiveCfg = Debug|Any CPU - {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Debug|x86.Build.0 = Debug|Any CPU - {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Release|Any CPU.Build.0 = Release|Any CPU - {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Release|x64.ActiveCfg = Release|Any CPU - {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Release|x64.Build.0 = Release|Any CPU - {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Release|x86.ActiveCfg = Release|Any CPU - {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Release|x86.Build.0 = Release|Any CPU - {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Debug|x64.ActiveCfg = Debug|Any CPU - {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Debug|x64.Build.0 = Debug|Any CPU - {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Debug|x86.ActiveCfg = Debug|Any CPU - {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Debug|x86.Build.0 = Debug|Any CPU - {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Release|Any CPU.Build.0 = Release|Any CPU - {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Release|x64.ActiveCfg = Release|Any CPU - {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Release|x64.Build.0 = Release|Any CPU - {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Release|x86.ActiveCfg = Release|Any CPU - {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Release|x86.Build.0 = Release|Any CPU - {4F113940-017F-4468-ACCD-AF3781B98BA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4F113940-017F-4468-ACCD-AF3781B98BA1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4F113940-017F-4468-ACCD-AF3781B98BA1}.Debug|x64.ActiveCfg = Debug|Any CPU - {4F113940-017F-4468-ACCD-AF3781B98BA1}.Debug|x64.Build.0 = Debug|Any CPU - {4F113940-017F-4468-ACCD-AF3781B98BA1}.Debug|x86.ActiveCfg = Debug|Any CPU - {4F113940-017F-4468-ACCD-AF3781B98BA1}.Debug|x86.Build.0 = Debug|Any CPU - {4F113940-017F-4468-ACCD-AF3781B98BA1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4F113940-017F-4468-ACCD-AF3781B98BA1}.Release|Any CPU.Build.0 = Release|Any CPU - {4F113940-017F-4468-ACCD-AF3781B98BA1}.Release|x64.ActiveCfg = Release|Any CPU - {4F113940-017F-4468-ACCD-AF3781B98BA1}.Release|x64.Build.0 = Release|Any CPU - {4F113940-017F-4468-ACCD-AF3781B98BA1}.Release|x86.ActiveCfg = Release|Any CPU - {4F113940-017F-4468-ACCD-AF3781B98BA1}.Release|x86.Build.0 = Release|Any CPU - {119E0731-0006-403D-B6EB-07917562FD81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {119E0731-0006-403D-B6EB-07917562FD81}.Debug|Any CPU.Build.0 = Debug|Any CPU - {119E0731-0006-403D-B6EB-07917562FD81}.Debug|x64.ActiveCfg = Debug|Any CPU - {119E0731-0006-403D-B6EB-07917562FD81}.Debug|x64.Build.0 = Debug|Any CPU - {119E0731-0006-403D-B6EB-07917562FD81}.Debug|x86.ActiveCfg = Debug|Any CPU - {119E0731-0006-403D-B6EB-07917562FD81}.Debug|x86.Build.0 = Debug|Any CPU - {119E0731-0006-403D-B6EB-07917562FD81}.Release|Any CPU.ActiveCfg = Release|Any CPU - {119E0731-0006-403D-B6EB-07917562FD81}.Release|Any CPU.Build.0 = Release|Any CPU - {119E0731-0006-403D-B6EB-07917562FD81}.Release|x64.ActiveCfg = Release|Any CPU - {119E0731-0006-403D-B6EB-07917562FD81}.Release|x64.Build.0 = Release|Any CPU - {119E0731-0006-403D-B6EB-07917562FD81}.Release|x86.ActiveCfg = Release|Any CPU - {119E0731-0006-403D-B6EB-07917562FD81}.Release|x86.Build.0 = Release|Any CPU - {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Debug|x64.ActiveCfg = Debug|Any CPU - {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Debug|x64.Build.0 = Debug|Any CPU - {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Debug|x86.ActiveCfg = Debug|Any CPU - {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Debug|x86.Build.0 = Debug|Any CPU - {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Release|Any CPU.Build.0 = Release|Any CPU - {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Release|x64.ActiveCfg = Release|Any CPU - {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Release|x64.Build.0 = Release|Any CPU - {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Release|x86.ActiveCfg = Release|Any CPU - {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11} = {E6804802-3416-4223-92CD-12B350ADCBF6} - {54845A61-CB13-4B26-82E2-45AFEC4836D4} = {E6804802-3416-4223-92CD-12B350ADCBF6} - {DC4B4FAD-C380-4F1E-9916-01D72C086112} = {A42B1288-6E03-4461-89AF-992C53858FCE} - {EE542E0A-21AE-4944-A355-25AC6C2D8652} = {DC4B4FAD-C380-4F1E-9916-01D72C086112} - {AACF455B-C8CB-4033-BA3B-F0C87326835C} = {DC4B4FAD-C380-4F1E-9916-01D72C086112} - {86B10300-5C83-4584-9A0D-4AD83B329F42} = {A42B1288-6E03-4461-89AF-992C53858FCE} - {72D23525-0519-4655-8BC5-E9158CD27E10} = {86B10300-5C83-4584-9A0D-4AD83B329F42} - {9F66FFF6-E802-4495-AAD8-5199FF7BACB2} = {86B10300-5C83-4584-9A0D-4AD83B329F42} - {3475DA24-0233-4B56-BE6A-3A5CA3B6010A} = {E6804802-3416-4223-92CD-12B350ADCBF6} - {2F0AC891-A63E-4467-ADE4-73251BB8AF59} = {A42B1288-6E03-4461-89AF-992C53858FCE} - {143DE5FA-114E-46D4-B9B9-11B57FB3546C} = {2F0AC891-A63E-4467-ADE4-73251BB8AF59} - {4F113940-017F-4468-ACCD-AF3781B98BA1} = {2F0AC891-A63E-4467-ADE4-73251BB8AF59} - {119E0731-0006-403D-B6EB-07917562FD81} = {2F0AC891-A63E-4467-ADE4-73251BB8AF59} - {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4} = {E6804802-3416-4223-92CD-12B350ADCBF6} - EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Debug|x64.ActiveCfg = Debug|Any CPU + {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Debug|x64.Build.0 = Debug|Any CPU + {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Debug|x86.ActiveCfg = Debug|Any CPU + {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Debug|x86.Build.0 = Debug|Any CPU + {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Release|Any CPU.Build.0 = Release|Any CPU + {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Release|x64.ActiveCfg = Release|Any CPU + {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Release|x64.Build.0 = Release|Any CPU + {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Release|x86.ActiveCfg = Release|Any CPU + {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11}.Release|x86.Build.0 = Release|Any CPU + {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Debug|x64.ActiveCfg = Debug|Any CPU + {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Debug|x64.Build.0 = Debug|Any CPU + {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Debug|x86.ActiveCfg = Debug|Any CPU + {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Debug|x86.Build.0 = Debug|Any CPU + {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Release|Any CPU.Build.0 = Release|Any CPU + {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Release|x64.ActiveCfg = Release|Any CPU + {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Release|x64.Build.0 = Release|Any CPU + {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Release|x86.ActiveCfg = Release|Any CPU + {54845A61-CB13-4B26-82E2-45AFEC4836D4}.Release|x86.Build.0 = Release|Any CPU + {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Debug|x64.ActiveCfg = Debug|Any CPU + {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Debug|x64.Build.0 = Debug|Any CPU + {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Debug|x86.ActiveCfg = Debug|Any CPU + {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Debug|x86.Build.0 = Debug|Any CPU + {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Release|Any CPU.Build.0 = Release|Any CPU + {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Release|x64.ActiveCfg = Release|Any CPU + {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Release|x64.Build.0 = Release|Any CPU + {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Release|x86.ActiveCfg = Release|Any CPU + {EE542E0A-21AE-4944-A355-25AC6C2D8652}.Release|x86.Build.0 = Release|Any CPU + {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Debug|x64.ActiveCfg = Debug|Any CPU + {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Debug|x64.Build.0 = Debug|Any CPU + {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Debug|x86.ActiveCfg = Debug|Any CPU + {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Debug|x86.Build.0 = Debug|Any CPU + {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Release|Any CPU.Build.0 = Release|Any CPU + {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Release|x64.ActiveCfg = Release|Any CPU + {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Release|x64.Build.0 = Release|Any CPU + {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Release|x86.ActiveCfg = Release|Any CPU + {AACF455B-C8CB-4033-BA3B-F0C87326835C}.Release|x86.Build.0 = Release|Any CPU + {72D23525-0519-4655-8BC5-E9158CD27E10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {72D23525-0519-4655-8BC5-E9158CD27E10}.Debug|Any CPU.Build.0 = Debug|Any CPU + {72D23525-0519-4655-8BC5-E9158CD27E10}.Debug|x64.ActiveCfg = Debug|Any CPU + {72D23525-0519-4655-8BC5-E9158CD27E10}.Debug|x64.Build.0 = Debug|Any CPU + {72D23525-0519-4655-8BC5-E9158CD27E10}.Debug|x86.ActiveCfg = Debug|Any CPU + {72D23525-0519-4655-8BC5-E9158CD27E10}.Debug|x86.Build.0 = Debug|Any CPU + {72D23525-0519-4655-8BC5-E9158CD27E10}.Release|Any CPU.ActiveCfg = Release|Any CPU + {72D23525-0519-4655-8BC5-E9158CD27E10}.Release|Any CPU.Build.0 = Release|Any CPU + {72D23525-0519-4655-8BC5-E9158CD27E10}.Release|x64.ActiveCfg = Release|Any CPU + {72D23525-0519-4655-8BC5-E9158CD27E10}.Release|x64.Build.0 = Release|Any CPU + {72D23525-0519-4655-8BC5-E9158CD27E10}.Release|x86.ActiveCfg = Release|Any CPU + {72D23525-0519-4655-8BC5-E9158CD27E10}.Release|x86.Build.0 = Release|Any CPU + {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Debug|x64.ActiveCfg = Debug|Any CPU + {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Debug|x64.Build.0 = Debug|Any CPU + {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Debug|x86.ActiveCfg = Debug|Any CPU + {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Debug|x86.Build.0 = Debug|Any CPU + {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Release|Any CPU.Build.0 = Release|Any CPU + {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Release|x64.ActiveCfg = Release|Any CPU + {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Release|x64.Build.0 = Release|Any CPU + {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Release|x86.ActiveCfg = Release|Any CPU + {9F66FFF6-E802-4495-AAD8-5199FF7BACB2}.Release|x86.Build.0 = Release|Any CPU + {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Debug|x64.ActiveCfg = Debug|Any CPU + {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Debug|x64.Build.0 = Debug|Any CPU + {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Debug|x86.ActiveCfg = Debug|Any CPU + {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Debug|x86.Build.0 = Debug|Any CPU + {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Release|Any CPU.Build.0 = Release|Any CPU + {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Release|x64.ActiveCfg = Release|Any CPU + {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Release|x64.Build.0 = Release|Any CPU + {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Release|x86.ActiveCfg = Release|Any CPU + {3475DA24-0233-4B56-BE6A-3A5CA3B6010A}.Release|x86.Build.0 = Release|Any CPU + {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Debug|x64.ActiveCfg = Debug|Any CPU + {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Debug|x64.Build.0 = Debug|Any CPU + {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Debug|x86.ActiveCfg = Debug|Any CPU + {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Debug|x86.Build.0 = Debug|Any CPU + {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Release|Any CPU.Build.0 = Release|Any CPU + {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Release|x64.ActiveCfg = Release|Any CPU + {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Release|x64.Build.0 = Release|Any CPU + {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Release|x86.ActiveCfg = Release|Any CPU + {143DE5FA-114E-46D4-B9B9-11B57FB3546C}.Release|x86.Build.0 = Release|Any CPU + {4F113940-017F-4468-ACCD-AF3781B98BA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F113940-017F-4468-ACCD-AF3781B98BA1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F113940-017F-4468-ACCD-AF3781B98BA1}.Debug|x64.ActiveCfg = Debug|Any CPU + {4F113940-017F-4468-ACCD-AF3781B98BA1}.Debug|x64.Build.0 = Debug|Any CPU + {4F113940-017F-4468-ACCD-AF3781B98BA1}.Debug|x86.ActiveCfg = Debug|Any CPU + {4F113940-017F-4468-ACCD-AF3781B98BA1}.Debug|x86.Build.0 = Debug|Any CPU + {4F113940-017F-4468-ACCD-AF3781B98BA1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4F113940-017F-4468-ACCD-AF3781B98BA1}.Release|Any CPU.Build.0 = Release|Any CPU + {4F113940-017F-4468-ACCD-AF3781B98BA1}.Release|x64.ActiveCfg = Release|Any CPU + {4F113940-017F-4468-ACCD-AF3781B98BA1}.Release|x64.Build.0 = Release|Any CPU + {4F113940-017F-4468-ACCD-AF3781B98BA1}.Release|x86.ActiveCfg = Release|Any CPU + {4F113940-017F-4468-ACCD-AF3781B98BA1}.Release|x86.Build.0 = Release|Any CPU + {119E0731-0006-403D-B6EB-07917562FD81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {119E0731-0006-403D-B6EB-07917562FD81}.Debug|Any CPU.Build.0 = Debug|Any CPU + {119E0731-0006-403D-B6EB-07917562FD81}.Debug|x64.ActiveCfg = Debug|Any CPU + {119E0731-0006-403D-B6EB-07917562FD81}.Debug|x64.Build.0 = Debug|Any CPU + {119E0731-0006-403D-B6EB-07917562FD81}.Debug|x86.ActiveCfg = Debug|Any CPU + {119E0731-0006-403D-B6EB-07917562FD81}.Debug|x86.Build.0 = Debug|Any CPU + {119E0731-0006-403D-B6EB-07917562FD81}.Release|Any CPU.ActiveCfg = Release|Any CPU + {119E0731-0006-403D-B6EB-07917562FD81}.Release|Any CPU.Build.0 = Release|Any CPU + {119E0731-0006-403D-B6EB-07917562FD81}.Release|x64.ActiveCfg = Release|Any CPU + {119E0731-0006-403D-B6EB-07917562FD81}.Release|x64.Build.0 = Release|Any CPU + {119E0731-0006-403D-B6EB-07917562FD81}.Release|x86.ActiveCfg = Release|Any CPU + {119E0731-0006-403D-B6EB-07917562FD81}.Release|x86.Build.0 = Release|Any CPU + {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Debug|x64.ActiveCfg = Debug|Any CPU + {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Debug|x64.Build.0 = Debug|Any CPU + {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Debug|x86.ActiveCfg = Debug|Any CPU + {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Debug|x86.Build.0 = Debug|Any CPU + {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Release|Any CPU.Build.0 = Release|Any CPU + {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Release|x64.ActiveCfg = Release|Any CPU + {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Release|x64.Build.0 = Release|Any CPU + {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Release|x86.ActiveCfg = Release|Any CPU + {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {AFAE7B9D-A464-408B-B3F7-40BCA0F5FA11} = {E6804802-3416-4223-92CD-12B350ADCBF6} + {54845A61-CB13-4B26-82E2-45AFEC4836D4} = {E6804802-3416-4223-92CD-12B350ADCBF6} + {DC4B4FAD-C380-4F1E-9916-01D72C086112} = {A42B1288-6E03-4461-89AF-992C53858FCE} + {EE542E0A-21AE-4944-A355-25AC6C2D8652} = {DC4B4FAD-C380-4F1E-9916-01D72C086112} + {AACF455B-C8CB-4033-BA3B-F0C87326835C} = {DC4B4FAD-C380-4F1E-9916-01D72C086112} + {86B10300-5C83-4584-9A0D-4AD83B329F42} = {A42B1288-6E03-4461-89AF-992C53858FCE} + {72D23525-0519-4655-8BC5-E9158CD27E10} = {86B10300-5C83-4584-9A0D-4AD83B329F42} + {9F66FFF6-E802-4495-AAD8-5199FF7BACB2} = {86B10300-5C83-4584-9A0D-4AD83B329F42} + {3475DA24-0233-4B56-BE6A-3A5CA3B6010A} = {E6804802-3416-4223-92CD-12B350ADCBF6} + {2F0AC891-A63E-4467-ADE4-73251BB8AF59} = {A42B1288-6E03-4461-89AF-992C53858FCE} + {143DE5FA-114E-46D4-B9B9-11B57FB3546C} = {2F0AC891-A63E-4467-ADE4-73251BB8AF59} + {4F113940-017F-4468-ACCD-AF3781B98BA1} = {2F0AC891-A63E-4467-ADE4-73251BB8AF59} + {119E0731-0006-403D-B6EB-07917562FD81} = {2F0AC891-A63E-4467-ADE4-73251BB8AF59} + {D7B4C2FD-50BB-4DEE-AC8C-4FCCC4685CD4} = {E6804802-3416-4223-92CD-12B350ADCBF6} + EndGlobalSection EndGlobal diff --git a/src/core/Wemogy.CQRS/Wemogy.CQRS.csproj b/src/core/Wemogy.CQRS/Wemogy.CQRS.csproj index 0e2ed63..611d2e3 100644 --- a/src/core/Wemogy.CQRS/Wemogy.CQRS.csproj +++ b/src/core/Wemogy.CQRS/Wemogy.CQRS.csproj @@ -21,6 +21,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + diff --git a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.TestWebApp/Commands/ThrowError/ThrowErrorCommandHandler.cs b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.TestWebApp/Commands/ThrowError/ThrowErrorCommandHandler.cs index b0a4bd3..319104d 100644 --- a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.TestWebApp/Commands/ThrowError/ThrowErrorCommandHandler.cs +++ b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.TestWebApp/Commands/ThrowError/ThrowErrorCommandHandler.cs @@ -1,25 +1,36 @@ +using Wemogy.Core.Errors; using Wemogy.Core.Errors.Enums; -using Wemogy.Core.Errors.Exceptions; using Wemogy.CQRS.Commands.Abstractions; namespace Wemogy.CQRS.Extensions.FastEndpoints.TestWebApp.Commands.ThrowError; public class ThrowErrorCommandHandler : ICommandHandler { - public Task HandleAsync(ThrowErrorCommand command) - { - throw new CustomErrorException( - command.ErrorType, - "CustomError", - "This is a custom error", - null); - } + private const string DummyErrorCode = "DummyErrorCode"; + private const string DummyErrorDescription = "DummyErrorDescription"; - class CustomErrorException : ErrorException + public Task HandleAsync(ThrowErrorCommand command) { - public CustomErrorException(ErrorType errorType, string code, string description, Exception? innerException) - : base(errorType, code, description, innerException) + switch (command.ErrorType) { + case ErrorType.Failure: + throw Error.Failure(DummyErrorCode, DummyErrorDescription); + case ErrorType.Unexpected: + throw Error.Unexpected(DummyErrorCode, DummyErrorDescription); + case ErrorType.Validation: + throw Error.Validation(DummyErrorCode, DummyErrorDescription); + case ErrorType.Conflict: + throw Error.Conflict(DummyErrorCode, DummyErrorDescription); + case ErrorType.NotFound: + throw Error.NotFound(DummyErrorCode, DummyErrorDescription); + case ErrorType.Authorization: + throw Error.Authorization(DummyErrorCode, DummyErrorDescription); + case ErrorType.PreconditionFailed: + throw Error.PreconditionFailed(DummyErrorCode, DummyErrorDescription); } + + throw Error.Unexpected( + "ErrorTypeNotSupported", + $"The ErrorType {command.ErrorType} is not supported!"); } } diff --git a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests/Endpoints/CommandEndpointBaseExceptionTests.cs b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests/Endpoints/CommandEndpointBaseExceptionTests.cs new file mode 100644 index 0000000..5819d01 --- /dev/null +++ b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests/Endpoints/CommandEndpointBaseExceptionTests.cs @@ -0,0 +1,50 @@ +using System.Collections; +using FluentAssertions; +using Microsoft.AspNetCore.Mvc.Testing; +using Wemogy.Core.Errors; +using Wemogy.Core.Errors.Enums; +using Wemogy.Core.Errors.Exceptions; +using Wemogy.CQRS.Commands.Abstractions; +using Wemogy.CQRS.Extensions.FastEndpoints.TestWebApp.Commands.ThrowError; + +namespace Wemogy.CQRS.Extensions.FastEndpoints.UnitTests.Endpoints; + + +public class CommandEndpointBaseExceptionTests : IClassFixture> +{ + private readonly WebApplicationFactory _factory; + + public CommandEndpointBaseExceptionTests(WebApplicationFactory factory) + { + _factory = factory; + } + + [Theory] + [InlineData(ErrorType.Failure)] + [InlineData(ErrorType.Unexpected)] + [InlineData(ErrorType.Validation)] + [InlineData(ErrorType.Conflict)] + [InlineData(ErrorType.NotFound)] + [InlineData(ErrorType.Authorization)] + [InlineData(ErrorType.PreconditionFailed)] + public async Task PrintHelloWorldCommand_ShouldReturnCorrectErrorException(ErrorType errorType) + { + // Arrange + var client = _factory.CreateClient(); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddCQRS(typeof(ThrowErrorCommand).Assembly) + .AddRemoteHttpServer(client) + .ConfigureRemoteCommandProcessing("api/commands/throw-error"); + var commands = serviceCollection.BuildServiceProvider().GetRequiredService(); + var throwErrorCommand = new ThrowErrorCommand(errorType); + + // Act + var exception = await Record.ExceptionAsync(() => commands.RunAsync(throwErrorCommand)); + + // Assert + exception.Should().NotBeNull().And.BeAssignableTo() + .Which.ErrorType.Should().Be(errorType); + exception?.GetType().Name.Should().Be($"{errorType}ErrorException"); + } +} + diff --git a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests/Extensions/PostProcessorContextExtensionsTests.cs b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests/Extensions/PostProcessorContextExtensionsTests.cs new file mode 100644 index 0000000..dde0289 --- /dev/null +++ b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests/Extensions/PostProcessorContextExtensionsTests.cs @@ -0,0 +1,71 @@ +using FastEndpoints; +using FluentAssertions; +using Moq; +using Wemogy.CQRS.Extensions.FastEndpoints.Extensions; + +namespace Wemogy.CQRS.Extensions.FastEndpoints.UnitTests.Extensions; + +public class PostProcessorContextExtensionsTests +{ + /// + /// This method checks if the MarkExceptionAsHandled implementation from FastEndpoints is working as expected + /// This is required, because the implementation is only internal accessible, so we need to hardcode the key + /// + [Fact] + public void MarkExceptionAsHandled_ShouldHaveTheExpectedImplementation() + { + // Arrange + var defaultHttpContext = new DefaultHttpContext(); + var mockContext = new Mock + { + // enable CallBase to tell Moq to use the default interface implementations (like MarkExceptionAsHandled) + CallBase = true + }; + mockContext.SetupGet(m => m.HttpContext).Returns(defaultHttpContext); + + // Act + mockContext.Object.MarkExceptionAsHandled(); + + // Assert + defaultHttpContext.Items.Should().ContainSingle(x => ReferenceEquals(x.Key, "3") && x.Value == null); + } + + [Fact] + public void IsExceptionHandled_ShouldBeTrueIfMarkExceptionAsHandledWasCalled() + { + // Arrange + var defaultHttpContext = new DefaultHttpContext(); + var mockContext = new Mock + { + // enable CallBase to tell Moq to use the default interface implementations (like MarkExceptionAsHandled) + CallBase = true + }; + mockContext.SetupGet(m => m.HttpContext).Returns(defaultHttpContext); + mockContext.Object.MarkExceptionAsHandled(); + + // Act + var result = mockContext.Object.IsExceptionHandled(); + + // Assert + result.Should().BeTrue(); + } + + [Fact] + public void IsExceptionHandled_ShouldBeFalseIfMarkExceptionAsHandledWasNotCalled() + { + // Arrange + var defaultHttpContext = new DefaultHttpContext(); + var mockContext = new Mock + { + // enable CallBase to tell Moq to use the default interface implementations (like MarkExceptionAsHandled) + CallBase = true + }; + mockContext.SetupGet(m => m.HttpContext).Returns(defaultHttpContext); + + // Act + var result = mockContext.Object.IsExceptionHandled(); + + // Assert + result.Should().BeFalse(); + } +} diff --git a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests.csproj b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests.csproj index 6ef1e76..7e309e1 100644 --- a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests.csproj +++ b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests.csproj @@ -12,6 +12,7 @@ + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Endpoints/CommandEndpointBase`1.cs b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Endpoints/CommandEndpointBase`1.cs index 1c92f09..a8e6d2b 100644 --- a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Endpoints/CommandEndpointBase`1.cs +++ b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Endpoints/CommandEndpointBase`1.cs @@ -7,6 +7,7 @@ using Wemogy.CQRS.Abstractions; using Wemogy.CQRS.Commands.Abstractions; using Wemogy.CQRS.Common.ValueObjects; +using Wemogy.CQRS.Extensions.FastEndpoints.PostProcessors; using Wemogy.CQRS.Setup; using ICommand = Wemogy.CQRS.Commands.Abstractions.ICommand; @@ -30,6 +31,7 @@ public override void Configure() // ToDo: remove this AllowAnonymous(); + PostProcessor>>(); } public override async Task HandleAsync(CommandRequest req, CancellationToken ct) diff --git a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Endpoints/CommandEndpointBase`2.cs b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Endpoints/CommandEndpointBase`2.cs index 3c562fb..bfb8e5e 100644 --- a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Endpoints/CommandEndpointBase`2.cs +++ b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Endpoints/CommandEndpointBase`2.cs @@ -7,6 +7,7 @@ using Wemogy.CQRS.Abstractions; using Wemogy.CQRS.Commands.Abstractions; using Wemogy.CQRS.Common.ValueObjects; +using Wemogy.CQRS.Extensions.FastEndpoints.PostProcessors; using Wemogy.CQRS.Setup; namespace Wemogy.CQRS.Extensions.FastEndpoints.Endpoints; @@ -29,6 +30,7 @@ public override void Configure() // ToDo: remove this AllowAnonymous(); + PostProcessor, TResult>>(); } public override async Task HandleAsync(CommandRequest req, CancellationToken ct) diff --git a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Endpoints/QueryEndpointBase.cs b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Endpoints/QueryEndpointBase.cs index 02f5165..0f1ddf5 100644 --- a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Endpoints/QueryEndpointBase.cs +++ b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Endpoints/QueryEndpointBase.cs @@ -7,6 +7,7 @@ using Wemogy.Core.Extensions; using Wemogy.CQRS.Abstractions; using Wemogy.CQRS.Common.ValueObjects; +using Wemogy.CQRS.Extensions.FastEndpoints.PostProcessors; using Wemogy.CQRS.Queries.Abstractions; using Wemogy.CQRS.Setup; @@ -30,6 +31,7 @@ public override void Configure() // ToDo: remove this AllowAnonymous(); + PostProcessor, TResult>>(); } public override async Task HandleAsync(QueryRequest req, CancellationToken ct) diff --git a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Extensions/EndpointDefinitionExtensions.cs b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Extensions/EndpointDefinitionExtensions.cs index 6e76a08..3086062 100644 --- a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Extensions/EndpointDefinitionExtensions.cs +++ b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Extensions/EndpointDefinitionExtensions.cs @@ -7,6 +7,7 @@ public static class EndpointDefinitionExtensions { public static void AddErrorHandlerPostProcessor(this EndpointDefinition endpointDefinition) { - endpointDefinition.PostProcessor(Order.Before); + // Add the global ErrorHandlerPostProcessor after the endpoint post processors are executed + endpointDefinition.PostProcessor(Order.After); } } diff --git a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Extensions/ExceptionInformationExtensions.cs b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Extensions/ExceptionInformationExtensions.cs deleted file mode 100644 index 74d87db..0000000 --- a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Extensions/ExceptionInformationExtensions.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Wemogy.Core.Json.ExceptionInformation; - -namespace Wemogy.CQRS.Extensions.FastEndpoints.Extensions; - -public static class ExceptionInformationExtensions -{ - public static Exception ToException(this ExceptionInformation exceptionInformation) - { - throw new NotImplementedException(); - } - - private static Type GetExceptionType(this ExceptionInformation exceptionInformation) - { - return Type.GetType(exceptionInformation.ExceptionType) ?? typeof(Exception); - } -} diff --git a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Extensions/PostProcessorContextExtensions.cs b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Extensions/PostProcessorContextExtensions.cs new file mode 100644 index 0000000..8200921 --- /dev/null +++ b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/Extensions/PostProcessorContextExtensions.cs @@ -0,0 +1,18 @@ +using FastEndpoints; + +namespace Wemogy.CQRS.Extensions.FastEndpoints.Extensions; + +public static class PostProcessorContextExtensions +{ + /// + /// The MarkExceptionAsHandled method add the CtxKey.EdiIsHandled key to the HttpContext.Items dictionary + /// This method checks if the CtxKey.EdiIsHandled key is present in the HttpContext.Items dictionary + /// + public static bool IsExceptionHandled(this IPostProcessorContext context) + { + // The CtxKey class is an internal class of FastEndpoints which means that we can't access it + // for that reason we hardcoded the value of the key + // The PostProcessorContextExtensionsTests class tests this implementation, so if the key changes the tests will fail + return context.HttpContext.Items.ContainsKey("3"); + } +} diff --git a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/PostProcessors/CqrsEndpointExceptionPostProcessor`1.cs b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/PostProcessors/CqrsEndpointExceptionPostProcessor`1.cs new file mode 100644 index 0000000..1b4fa2b --- /dev/null +++ b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/PostProcessors/CqrsEndpointExceptionPostProcessor`1.cs @@ -0,0 +1,5 @@ +namespace Wemogy.CQRS.Extensions.FastEndpoints.PostProcessors; + +public class CqrsEndpointExceptionPostProcessor : CqrsEndpointExceptionPostProcessor +{ +} diff --git a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/PostProcessors/CqrsEndpointExceptionPostProcessor`2.cs b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/PostProcessors/CqrsEndpointExceptionPostProcessor`2.cs new file mode 100644 index 0000000..ffb6458 --- /dev/null +++ b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/PostProcessors/CqrsEndpointExceptionPostProcessor`2.cs @@ -0,0 +1,28 @@ +using System.Net; +using FastEndpoints; +using Wemogy.Core.Errors.Exceptions; +using Wemogy.Core.Errors.Extensions; +using Wemogy.Core.Json.ExceptionInformation; +using Wemogy.CQRS.Extensions.FastEndpoints.Extensions; + +namespace Wemogy.CQRS.Extensions.FastEndpoints.PostProcessors; + +public class CqrsEndpointExceptionPostProcessor : IPostProcessor +{ + public Task PostProcessAsync(IPostProcessorContext context, CancellationToken ct) + { + if (!context.HasExceptionOccurred) + { + return Task.CompletedTask; + } + + var exception = context.ExceptionDispatchInfo.SourceException; + + var statusCode = (exception as ErrorException)?.ErrorType.ToHttpStatusCode() ?? HttpStatusCode.InternalServerError; + + context.MarkExceptionAsHandled(); + + context.HttpContext.Response.Headers.AppendJsonTypeHeader(); + return context.HttpContext.Response.SendStringAsync(exception.ToJson(), (int)statusCode, cancellation: ct); + } +} diff --git a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/PostProcessors/ErrorHandlerPostProcessor.cs b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/PostProcessors/ErrorHandlerPostProcessor.cs index 848e573..709dee9 100644 --- a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/PostProcessors/ErrorHandlerPostProcessor.cs +++ b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/PostProcessors/ErrorHandlerPostProcessor.cs @@ -10,7 +10,7 @@ public class ErrorHandlerPostProcessor : IGlobalPostProcessor { public async Task PostProcessAsync(IPostProcessorContext context, CancellationToken ct) { - if (!context.HasExceptionOccurred) + if (!context.HasExceptionOccurred || context.IsExceptionHandled()) { return; } diff --git a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/RemoteCommandRunners/HttpRemoteCommandRunner`1.cs b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/RemoteCommandRunners/HttpRemoteCommandRunner`1.cs index a2e9089..2b07771 100644 --- a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/RemoteCommandRunners/HttpRemoteCommandRunner`1.cs +++ b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/RemoteCommandRunners/HttpRemoteCommandRunner`1.cs @@ -1,4 +1,5 @@ using RestSharp; +using Wemogy.Core.Errors; using Wemogy.Core.Extensions; using Wemogy.Core.Json.ExceptionInformation; using Wemogy.CQRS.Abstractions; @@ -41,8 +42,17 @@ public async Task RunAsync(CommandRequest command) throw response.ErrorException ?? new Exception(response.Content); } - // ToDo: Handle the exception information var exceptionInformation = response.Content?.FromJson(); + + if (exceptionInformation == null) + { + throw Error.Unexpected( + "ExceptionInformationMissing", + "The response from the remote service did not contain any exception information."); + } + + var exception = exceptionInformation.ToException(); + throw exception; } } catch (HttpRequestException e) diff --git a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/RemoteCommandRunners/HttpRemoteCommandRunner`2.cs b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/RemoteCommandRunners/HttpRemoteCommandRunner`2.cs index 04ddac3..960288d 100644 --- a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/RemoteCommandRunners/HttpRemoteCommandRunner`2.cs +++ b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/RemoteCommandRunners/HttpRemoteCommandRunner`2.cs @@ -1,9 +1,13 @@ using System.Text.Json; using RestSharp; +using Wemogy.Core.Errors; +using Wemogy.Core.Extensions; +using Wemogy.Core.Json.ExceptionInformation; using Wemogy.CQRS.Abstractions; using Wemogy.CQRS.Commands.Abstractions; using Wemogy.CQRS.Common.ValueObjects; using Wemogy.CQRS.Extensions.FastEndpoints.Common; +using Wemogy.CQRS.Extensions.FastEndpoints.Extensions; namespace Wemogy.CQRS.Extensions.FastEndpoints.RemoteCommandRunners; @@ -33,7 +37,22 @@ public async Task RunAsync(CommandRequest command) if (!response.IsSuccessful) { - throw new Exception($"Failed to run command {command.Command.GetType().Name}"); + if (response.Headers == null || !response.Headers.HasJsonTypeHeader()) + { + throw response.ErrorException ?? new Exception(response.Content); + } + + var exceptionInformation = response.Content?.FromJson(); + + if (exceptionInformation == null) + { + throw Error.Unexpected( + "ExceptionInformationMissing", + "The response from the remote service did not contain any exception information."); + } + + var exception = exceptionInformation.ToException(); + throw exception; } if (response.Content == null) diff --git a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/RemoteQueryRunners/HttpRemoteQueryRunner.cs b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/RemoteQueryRunners/HttpRemoteQueryRunner.cs index d0c24e6..12e8d06 100644 --- a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/RemoteQueryRunners/HttpRemoteQueryRunner.cs +++ b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints/RemoteQueryRunners/HttpRemoteQueryRunner.cs @@ -1,9 +1,12 @@ using System.Text.Json; -using System.Text.Json.Serialization; using RestSharp; +using Wemogy.Core.Errors; +using Wemogy.Core.Extensions; +using Wemogy.Core.Json.ExceptionInformation; using Wemogy.CQRS.Abstractions; using Wemogy.CQRS.Common.ValueObjects; using Wemogy.CQRS.Extensions.FastEndpoints.Common; +using Wemogy.CQRS.Extensions.FastEndpoints.Extensions; using Wemogy.CQRS.Queries.Abstractions; namespace Wemogy.CQRS.Extensions.FastEndpoints.RemoteQueryRunners; @@ -26,9 +29,6 @@ public HttpRemoteQueryRunner(RestClient restClient, string urlPath) public async Task QueryAsync(QueryRequest query, CancellationToken cancellationToken) { - // ToDo: Get configuration for the TCommand - - // ToDo: Http call to the remote service var request = new RestRequest(_urlPath) .AddJsonBody(query); @@ -36,7 +36,22 @@ public async Task QueryAsync(QueryRequest query, CancellationTo if (!response.IsSuccessful) { - throw new Exception($"Failed to run query {query.Query.GetType().Name}"); + if (response.Headers == null || !response.Headers.HasJsonTypeHeader()) + { + throw response.ErrorException ?? new Exception(response.Content); + } + + var exceptionInformation = response.Content?.FromJson(); + + if (exceptionInformation == null) + { + throw Error.Unexpected( + "ExceptionInformationMissing", + "The response from the remote service did not contain any exception information."); + } + + var exception = exceptionInformation.ToException(); + throw exception; } if (response.Content == null) diff --git a/src/switcher.json b/src/switcher.json index 88a8393..67bb859 100644 --- a/src/switcher.json +++ b/src/switcher.json @@ -1,7 +1,7 @@ { "solution": "Wemogy.CQRS.sln", "mappings": { - "Wemogy.Core": "../../libs/helpers/src/Wemogy.Core/Wemogy.Core.csproj", + "Wemogy.Core": "../../libs-core/src/Wemogy.Core/Wemogy.Core.csproj", "Wemogy.Infrastructure.Database.Core": "../../libs-infrastructure-database/src/core/Wemogy.Infrastructure.Database.Core/Wemogy.Infrastructure.Database.Core.csproj", "Wemogy.Infrastructure.Database.InMemory": "../../libs-infrastructure-database/src/in-memory/Wemogy.Infrastructure.Database.InMemory/Wemogy.Infrastructure.Database.InMemory.csproj" }, From d0a93a84d3ec0604ebce8e876fcc09d1354218ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20K=C3=BCsters?= Date: Wed, 10 Jul 2024 12:06:27 +0200 Subject: [PATCH 2/4] chore: fixed styling --- .../Endpoints/CommandEndpointBaseExceptionTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests/Endpoints/CommandEndpointBaseExceptionTests.cs b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests/Endpoints/CommandEndpointBaseExceptionTests.cs index 5819d01..8c3a052 100644 --- a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests/Endpoints/CommandEndpointBaseExceptionTests.cs +++ b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests/Endpoints/CommandEndpointBaseExceptionTests.cs @@ -47,4 +47,3 @@ public async Task PrintHelloWorldCommand_ShouldReturnCorrectErrorException(Error exception?.GetType().Name.Should().Be($"{errorType}ErrorException"); } } - From f2cfc49664a9caff24541340a91480b93a386fc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20K=C3=BCsters?= Date: Wed, 10 Jul 2024 12:09:11 +0200 Subject: [PATCH 3/4] fix: fixed build errors --- .../Endpoints/CommandEndpointBaseExceptionTests.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests/Endpoints/CommandEndpointBaseExceptionTests.cs b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests/Endpoints/CommandEndpointBaseExceptionTests.cs index 8c3a052..6e1cedc 100644 --- a/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests/Endpoints/CommandEndpointBaseExceptionTests.cs +++ b/src/extensions/fastEndpoints/Wemogy.CQRS.Extensions.FastEndpoints.UnitTests/Endpoints/CommandEndpointBaseExceptionTests.cs @@ -1,7 +1,5 @@ -using System.Collections; using FluentAssertions; using Microsoft.AspNetCore.Mvc.Testing; -using Wemogy.Core.Errors; using Wemogy.Core.Errors.Enums; using Wemogy.Core.Errors.Exceptions; using Wemogy.CQRS.Commands.Abstractions; @@ -9,7 +7,6 @@ namespace Wemogy.CQRS.Extensions.FastEndpoints.UnitTests.Endpoints; - public class CommandEndpointBaseExceptionTests : IClassFixture> { private readonly WebApplicationFactory _factory; From d4b5497ad3bb6ec1b9e355ea507695f0e7e1830c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20K=C3=BCsters?= Date: Wed, 10 Jul 2024 12:18:46 +0200 Subject: [PATCH 4/4] chore: fixed permissions of pipeline --- .github/workflows/test.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 806ca66..3beedab 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -10,6 +10,9 @@ jobs: tests: name: Tests runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write steps: - uses: actions/checkout@v3