Skip to content

fix(quality): add ConfigureAwait(false) and specific exception catches#149

Merged
mpaulosky merged 3 commits into
sprint/6-code-qualityfrom
squad/139-configureawait-exception-specificity
Apr 24, 2026
Merged

fix(quality): add ConfigureAwait(false) and specific exception catches#149
mpaulosky merged 3 commits into
sprint/6-code-qualityfrom
squad/139-configureawait-exception-specificity

Conversation

@mpaulosky

Copy link
Copy Markdown
Owner

Closes #139

Working as Sam (Backend Developer)

Addresses CA2007 and CA1031 across all MediatR handler files:

CA2007 — ConfigureAwait(false)

  • Added .ConfigureAwait(false) to all Task/Task<T> awaits in:
    • CreateBlogPostHandler
    • DeleteBlogPostHandler
    • EditBlogPostHandler
    • GetBlogPostsHandler
    • UserManagementHandler
  • await foreach loops are intentionally excluded (CA2007 does not apply)

CA1031 — Catch specific exceptions

  • Added catch (OperationCanceledException) { throw; } before each broad catch (Exception ex) block in all handlers so cancellation propagates naturally

All 27 unit/arch tests pass.

- Add .ConfigureAwait(false) to all Task awaits in all MediatR handlers
  (skipping await foreach per CA2007 scope)
- Add catch (OperationCanceledException) { throw; } before each broad
  catch (Exception ex) block in all handlers to satisfy CA1031

Addresses CA2007 and CA1031.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 24, 2026 18:55
@github-actions github-actions Bot added the squad Squad triage inbox — Lead will assign to a member label Apr 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🏗️ PR Added to Squad Triage Queue

This PR has been labeled with squad and added to the triage queue.

Next steps:

  • The squad Lead will review and assign to an appropriate team member
  • A squad:member label will be added after triage

If you know which squad member should handle this, you can add the appropriate squad:member label yourself.

@github-actions

github-actions Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Test Results Summary

209 tests   209 ✅  14s ⏱️
  5 suites    0 💤
  5 files      0 ❌

Results for commit bf243ae.

♻️ This comment has been updated with latest results.

@codecov

codecov Bot commented Apr 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 22.07792% with 60 lines in your changes missing coverage. Please review.
✅ Project coverage is 72.12%. Comparing base (2e00442) to head (29f8ff2).
⚠️ Report is 21 commits behind head on sprint/6-code-quality.

Files with missing lines Patch % Lines
...b/Features/UserManagement/UserManagementHandler.cs 0.00% 39 Missing ⚠️
...Web/Features/BlogPosts/Edit/EditBlogPostHandler.cs 43.75% 9 Missing ⚠️
...Features/BlogPosts/Create/CreateBlogPostHandler.cs 42.85% 4 Missing ⚠️
...Features/BlogPosts/Delete/DeleteBlogPostHandler.cs 50.00% 4 Missing ⚠️
...Web/Features/BlogPosts/List/GetBlogPostsHandler.cs 42.85% 4 Missing ⚠️
Additional details and impacted files
@@                    Coverage Diff                    @@
##           sprint/6-code-quality     #149      +/-   ##
=========================================================
- Coverage                  77.23%   72.12%   -5.12%     
=========================================================
  Files                         43       43              
  Lines                        672      721      +49     
  Branches                     111      112       +1     
=========================================================
+ Hits                         519      520       +1     
- Misses                       103      150      +47     
- Partials                      50       51       +1     
Files with missing lines Coverage Δ
...Features/BlogPosts/Create/CreateBlogPostHandler.cs 71.42% <42.85%> (-28.58%) ⬇️
...Features/BlogPosts/Delete/DeleteBlogPostHandler.cs 77.77% <50.00%> (-22.23%) ⬇️
...Web/Features/BlogPosts/List/GetBlogPostsHandler.cs 76.47% <42.85%> (-23.53%) ⬇️
...Web/Features/BlogPosts/Edit/EditBlogPostHandler.cs 72.97% <43.75%> (-20.14%) ⬇️
...b/Features/UserManagement/UserManagementHandler.cs 0.00% <0.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to resolve analyzer warnings in the Web project’s MediatR handlers by adding ConfigureAwait(false) on awaited operations and ensuring cancellation flows through by rethrowing OperationCanceledException.

Changes:

  • Added .ConfigureAwait(false) to awaited Task/Task<T> calls in blog post and user management handlers.
  • Added catch (OperationCanceledException) { throw; } before broad exception handling blocks to avoid converting cancellations into failure results.
  • Updated Auth0 Management API client acquisition and related calls to use ConfigureAwait(false).

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/Web/Features/UserManagement/UserManagementHandler.cs Adds ConfigureAwait(false) to Auth0 Management API calls and rethrows cancellation before broad exception handling.
src/Web/Features/BlogPosts/List/GetBlogPostsHandler.cs Adds ConfigureAwait(false) in cache/repo awaits and rethrows cancellation before broad exception handling.
src/Web/Features/BlogPosts/Edit/EditBlogPostHandler.cs Adds ConfigureAwait(false) to repo/cache awaits and rethrows cancellation before broad exception handling in both handlers.
src/Web/Features/BlogPosts/Delete/DeleteBlogPostHandler.cs Adds ConfigureAwait(false) to repo/cache awaits and rethrows cancellation before broad exception handling.
src/Web/Features/BlogPosts/Create/CreateBlogPostHandler.cs Adds ConfigureAwait(false) to repo/cache awaits and rethrows cancellation before broad exception handling.
Comments suppressed due to low confidence (9)

src/Web/Features/BlogPosts/Delete/DeleteBlogPostHandler.cs:41

  • This still catches Exception and turns it into Result.Fail(ex.Message), which likely continues to trigger CA1031 and also exposes raw exception details to the UI. Prefer catching expected exception types (e.g., data store/cache exceptions) and returning a user-safe message with logging; if you must keep a broad catch, explicitly suppress/justify CA1031 and avoid returning ex.Message directly.
catch (Exception ex)
{
return Result.Fail(ex.Message);
}

src/Web/Features/BlogPosts/Edit/EditBlogPostHandler.cs:47

  • This broad catch (Exception ex) still violates CA1031, and returning ex.Message will surface internal exception details to the UI. Consider catching expected exception types (or centralizing exception handling in a MediatR pipeline behavior) and return a user-safe message while logging the exception; if a broad catch is required, add a CA1031 suppression with justification and avoid exposing ex.Message directly.
catch (Exception ex)
{
return Result.Fail(ex.Message);
}

src/Web/Features/UserManagement/UserManagementHandler.cs:57

  • This broad catch (Exception ex) likely continues to trigger CA1031 (general exception catch). It also returns ex.Message, which can expose internal details to the UI. Consider catching expected exceptions from the Auth0 Management API / HTTP calls (and logging), or centralize exception-to-Result mapping in a pipeline behavior; if you must keep the broad catch, explicitly suppress/justify CA1031 and avoid returning ex.Message directly.
catch (Exception ex)
{
return Result.Fail<IReadOnlyList<UserWithRolesDto>>(ex.Message);
}

src/Web/Features/UserManagement/UserManagementHandler.cs:99

  • This broad catch (Exception ex) likely continues to trigger CA1031 (general exception catch). It also returns ex.Message, which can expose internal details to the UI. Consider catching expected exceptions from the Auth0 Management API / HTTP calls (and logging), or centralize exception-to-Result mapping in a pipeline behavior; if you must keep the broad catch, explicitly suppress/justify CA1031 and avoid returning ex.Message directly.
catch (Exception ex)
{
return Result.Fail(ex.Message);
}

src/Web/Features/BlogPosts/Create/CreateBlogPostHandler.cs:35

  • This still catches Exception and turns it into Result.Fail(ex.Message), which likely continues to trigger CA1031 (catching a general exception type) and also surfaces raw exception messages to the UI. Prefer catching expected exception types (or centralizing exception-to-Result mapping in a MediatR pipeline behavior with logging) and return a user-safe message; if a broad catch is truly required, add an explicit suppression/justification for CA1031 and avoid returning ex.Message directly.
catch (Exception ex)
{
return Result.Fail<Guid>(ex.Message);
}

src/Web/Features/BlogPosts/Edit/EditBlogPostHandler.cs:70

  • This broad catch (Exception ex) still violates CA1031, and returning ex.Message will surface internal exception details to the UI. Consider catching expected exception types (or centralizing exception handling in a MediatR pipeline behavior) and return a user-safe message while logging the exception; if a broad catch is required, add a CA1031 suppression with justification and avoid exposing ex.Message directly.
catch (Exception ex)
{
return Result.Fail<BlogPostDto?>(ex.Message);
}

src/Web/Features/BlogPosts/List/GetBlogPostsHandler.cs:39

  • This still catches Exception and turns it into Result.Fail(ex.Message), which likely continues to trigger CA1031 and also exposes raw exception details to the UI. Prefer catching expected exception types (or centralizing exception-to-Result mapping with logging) and returning a user-safe message; if a broad catch is required, explicitly suppress/justify CA1031 and avoid returning ex.Message directly.
catch (Exception ex)
{
return Result.Fail<IReadOnlyList<BlogPostDto>>(ex.Message);
}

src/Web/Features/UserManagement/UserManagementHandler.cs:78

  • This broad catch (Exception ex) likely continues to trigger CA1031 (general exception catch). It also returns ex.Message, which can expose internal details to the UI. Consider catching expected exceptions from the Auth0 Management API / HTTP calls (and logging), or centralize exception-to-Result mapping in a pipeline behavior; if you must keep the broad catch, explicitly suppress/justify CA1031 and avoid returning ex.Message directly.
catch (Exception ex)
{
return Result.Fail(ex.Message);
}

src/Web/Features/UserManagement/UserManagementHandler.cs:122

  • This broad catch (Exception ex) likely continues to trigger CA1031 (general exception catch). It also returns ex.Message, which can expose internal details to the UI. Consider catching expected exceptions from the Auth0 Management API / HTTP calls (and logging), or centralize exception-to-Result mapping in a pipeline behavior; if you must keep the broad catch, explicitly suppress/justify CA1031 and avoid returning ex.Message directly.
catch (Exception ex)
{
return Result.Fail<IReadOnlyList<RoleDto>>(ex.Message);
}

Boromir and others added 2 commits April 24, 2026 12:37
…d/139-configureawait-exception-specificity
Add specific exception catches (InvalidOperationException, HttpRequestException)
before broad catch blocks to satisfy CA1031. Suppress the unavoidable final
catch (Exception) with #pragma warning disable CA1031 and a justification
comment. The broad catch is intentional: top-level handlers must convert all
unexpected failures to Result to keep the UI stable.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mpaulosky
mpaulosky merged commit b0f30f9 into sprint/6-code-quality Apr 24, 2026
3 checks passed
@mpaulosky
mpaulosky deleted the squad/139-configureawait-exception-specificity branch April 24, 2026 19:45
mpaulosky added a commit that referenced this pull request Apr 25, 2026
## Sprint 6: Code Quality

**Goal:** Eliminate analyzer warnings, enforce internal visibility on
Web feature types, expand test coverage, and migrate Unit.Tests into
Web.Tests.

---

## Merged Feature PRs

- Closes #137 — PR #144 — fix(quality): rename `ct` →
`cancellationToken` in all MediatR handlers
- Closes #138 — PR #145 — test: add unit tests for BlogPost, Result, and
ValidationBehavior (42 tests)
- Closes #139 — PR #146 — test: add unit tests for UserManagementHandler
(16 tests)
- Closes #140 — PR #147 — fix(quality): make Web feature types
`internal` (CA1515, ~28 types)
- Closes #141 — PR #148 — test: add unit tests for BlogPostMappings (22
tests)
- Closes #142 — PR #149 — fix(quality): add ConfigureAwait(false) and
specific exception catches
- Closes #143 — PR #150 — fix(quality): address Domain and
ServiceDefaults analyzer warnings
- Closes #151 — PR #152 — feat(tests): migrate Unit.Tests → Web.Tests
and remove Unit.Tests project

---

## Test Summary

- **80+ new tests** added across all PRs
- **105 Web.Tests passing** (0 failures)
- `DynamicProxyGenAssembly2` added to `InternalsVisibleTo` in Web.csproj
for NSubstitute support

## Notable Changes

- `Unit.Tests` project removed; all tests now live in `Web.Tests`
- ~28 Web feature types changed from `public` to `internal` (CA1515
compliance)
- All MediatR handler parameters renamed from `ct` to
`cancellationToken` for clarity
- `ConfigureAwait(false)` applied to all async calls in service layer
- Domain and ServiceDefaults analyzer warnings resolved

---

## Checklist

- [x] All sprint issues closed (#137#143, #151)
- [x] CI green (0 build errors)
- [x] 105 Web.Tests passing
- [x] Milestone at 100%

---------

Co-authored-by: Boromir <boromir@squad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

squad Squad triage inbox — Lead will assign to a member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants