feat: implement identity authentication, authorization policies, and MAUI platform support with Docker orchestration
This commit is contained in:
+2
-1
@@ -4,10 +4,11 @@
|
||||
- **Role:** Lead Architect & Creative Technologist (.NET 10 & Blazor)
|
||||
- **Persona:** Professional, precise, Senior Full-Stack Engineer focused on performance and "invisible UI".
|
||||
- **Architecture Role:** Lead Clean Architecture Specialist.
|
||||
- **Skills:** [nexus-clean-architecture, nexus-ui-engine, nexus-graph-d3, blazor-state-performance, blazor-hybrid-bridge, semantic-kernel-orchestrator, nexus-identity-saas]
|
||||
- **Skills:** [nexus-clean-architecture, nexus-ui-engine, nexus-graph-d3, blazor-state-performance, blazor-hybrid-bridge, semantic-kernel-orchestrator, nexus-identity-saas, dotnet-async-void]
|
||||
- **Technical Constraints:**
|
||||
- **Directory Structure:** Strict separation: `/src` (app code) and `/tests` (testing code) at solution root level.
|
||||
- **Patterns:** Mandatory CQRS via `MediatR` (LuckyPennySoftware implementation). No business logic in UI components.
|
||||
- **Async:** Strict zero-tolerance for `async void`. All async operations must return `Task` or `ValueTask`. Event handlers must use `Func<Task>` or async-compatible patterns.
|
||||
- **Error Handling:** All handlers must return `Result<T>` via `FluentResult`.
|
||||
- **Mapping:** Use `Mapster` exclusively. Zero-tolerance for AutoMapper.
|
||||
- **Platform:** Target .NET 10 with Native AOT compatibility in mind for mobile performance.
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
# .NET Async Best Practices: Avoiding `async void`
|
||||
|
||||
This document defines the core rules for handling asynchronous operations in .NET, specifically focused on the dangers of `async void`.
|
||||
|
||||
## The Rule: NEVER Use `async void`
|
||||
`async void` is a critical anti-pattern in .NET that must be avoided in almost all scenarios.
|
||||
|
||||
### Why `async void` is Dangerous:
|
||||
1. **Untraceable Crashes**: Exceptions thrown in an `async void` method cannot be caught by a `try-catch` block outside the method. They often crash the entire process.
|
||||
2. **Impossible to Await**: Callers cannot know when the operation has finished, leading to race conditions and "disposed object" exceptions (especially with `DbContext`).
|
||||
3. **Broken Lifecycle**: In Blazor and ASP.NET Core, the DI container might dispose of scoped services (like `DbContext`) before the `async void` method completes its work.
|
||||
|
||||
## Correct Patterns
|
||||
|
||||
### 1. Standard Methods
|
||||
Always return `Task` or `ValueTask` instead of `void`.
|
||||
```csharp
|
||||
// BAD
|
||||
public async void SaveDataAsync() { ... }
|
||||
|
||||
// GOOD
|
||||
public async Task SaveDataAsync() { ... }
|
||||
```
|
||||
|
||||
### 2. Async Events (Blazor/Services)
|
||||
When dealing with events that are defined as `Action` or `EventHandler`, do not use `async void` in the handler. Instead, refactor the event to support `Task`.
|
||||
|
||||
#### Pattern A: Use `Func<Task>` for Events
|
||||
Instead of `Action`, use `Func<Task>` so the invoker can await all handlers.
|
||||
```csharp
|
||||
// Interface
|
||||
event Func<Task>? OnChanged;
|
||||
|
||||
// Invoker
|
||||
if (OnChanged != null)
|
||||
{
|
||||
foreach (var handler in OnChanged.GetInvocationList().Cast<Func<Task>>())
|
||||
{
|
||||
await handler();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Pattern B: Wrapper for Legacy Events
|
||||
If you *must* subscribe to a legacy `void` event, use a Task-returning method and a lambda, but be aware of the "fire-and-forget" risks.
|
||||
```csharp
|
||||
// Better than async void, but still has lifecycle risks
|
||||
NavigationService.OnChanged += () => { _ = HandleChangedAsync(); };
|
||||
```
|
||||
|
||||
## Special Exceptions
|
||||
The ONLY valid place for `async void` is in **Top-level Event Handlers** in legacy UI frameworks (WinForms/WPF) where the event signature is fixed and cannot be changed. Even then, the method body should be wrapped in a `try-catch` that logs or handles all exceptions.
|
||||
|
||||
In modern Blazor and Web development, there is **zero justification** for `async void`.
|
||||
Reference in New Issue
Block a user