A one-page checklist of the recommendations from the tutorials. Each item links to the tutorial that explains it.
Project layout (recommended)
This is the layout the tutorials use. It is a recommendation, not a requirement. The things that are required are called out in tutorial 01.
MyApp.Shared/ references RForge.Blazor.AutoApi.Abstractions only, no ASP.NET
├── I<Feature>Service.cs [RForgeAutoApi] interfaces
├── <Feature>Dto.cs the types the interfaces send and return
└── AppJsonContext.cs the JsonSerializerContext, plus [assembly: RForgeAutoApiDefaults(...)]
MyApp/ server project (references the Generator package)
├── Program.cs register services, AddRForgeAutoApiServer(), MapRForgeAutoApi()
├── AutoApiEndpoints.cs the [RForgeAutoApiHost] class
└── Services/<Feature>Service.cs the real implementations
MyApp.Client/ WebAssembly project (references the Generator package)
├── Program.cs AddRForgeAutoApi()
├── AutoApiClients.cs the [RForgeAutoApiClient] class
└── Features/… components that inject the interfaces
MyApp.Tests/ round-trip, server-mode and component tests
Where each file goes
| File | Put it in | Why | Tutorial |
|---|---|---|---|
Interfaces, DTOs, JsonSerializerContext | MyApp.Shared | Both the server and the client need them, and the generators read them from a referenced assembly | 01, 03 |
[assembly: RForgeAutoApiDefaults] | MyApp.Shared | Both generators read it, so the server and client always agree on prefix, default method and JSON context | 01, 03 |
[RForgeAutoApiHost] class | The server project | It generates ASP.NET code | 01 |
[RForgeAutoApiClient] class | The WebAssembly project | It generates the HttpClient implementation | 01 |
| Generator package reference | Every project that has a marker class | NuGet doesn't pass analyzers through project references | 01, 10 |
| The real services | The server project, registered before AddRForgeAutoApiServer() | Server mode and prerendering call them directly | 05, 06 |
| Handlers and client names | MyApp.Client/Program.cs, on the builder AddRForgeAutoApi() returns | One place to add tokens and extra clients | 07 |
| Rate limiting and other endpoint conventions | Program.cs, chained on MapRForgeAutoApi() | They apply to every generated endpoint | 08 |
| Tests | MyApp.Tests | One fixture shares an in-memory server | 09 |
Naming
| Thing | Convention | Example |
|---|---|---|
| Interface | I<Feature>Service | IBookService |
| Method | Verb, ends in Async | GetBookAsync, AddBookAsync |
| Data type | <Noun>Dto | BookDto |
| Marker classes | AutoApiEndpoints and AutoApiClients | |
Error code | Lower snake case, one per reason | title_required, book_not_found |
Interfaces and methods
- [ ] Every method returns
Task,Task<T>,ValueTaskorValueTask<T>. No generics, noref/out/in, no properties or events. (02, 10) - [ ] Remember that
[RForgeAutoApi]opts in every method of the interface. Split an interface if some methods should not be callable from the browser. (02) - [ ] Keep the default
Postunless a method is a safe read. UseGetandDeleteonly with simple parameters. (02, 03) - [ ] Take a
CancellationToken(at most one) and pass it on to your async calls. (03) - [ ] Avoid overloads, or give each its own
Route. Default routes for overloads are numbered in declaration order. (02) - [ ] Add new parameters with a default value. Adding one is not a breaking change. (03)
Serialization
- [ ] Declare one
JsonSerializerContextin the shared library and pointRForgeAutoApiDefaults.JsonContextat it. (03) - [ ] List every parameter and return type in it, including
List<T>and simple types such asint. (03) - [ ] Treat
RFAA009as an error in CI, so a missing type can't fall back to reflection unnoticed. (10)
Errors
- [ ] Throw
RfException(with acode) for expected failures, andRfNotFoundExceptionfor a missing item. (04) - [ ] Write
RfExceptionmessages you are happy to show a user. They are sent to the browser. (04) - [ ] In components,
catch (RfException)to show the message, and log everything else. The samecatchworks in every render mode. (04) - [ ] Don't catch
Exceptionto hide failures. Unexpected errors arrive asRfApiExceptionin WebAssembly, with the details left on the server. (04)
Authorization
- [ ] Put
[RfAuthorize]on the interface and[RfAllowAnonymous]on the few methods that are public. (05) - [ ] Register services that have authorization rules as Scoped or Transient. A Singleton throws at startup. (05, 10)
- [ ] Call
AddRForgeAutoApiServer()after all your service registrations. (05, 10) - [ ] Remember that Interactive Server mode makes no HTTP call. The decorator, not the endpoint, enforces the rules there. (05, 06)
Components and render modes
- [ ] Inject the interface and nothing else. Don't check the render mode in the component. (06)
- [ ] Don't assume a call is cheap or free of serialization. In WebAssembly it is an HTTP request. (06)
HttpClient and endpoints
- [ ] Add handlers (for example a token handler) to the builder
AddRForgeAutoApi()returns. (07) - [ ] Use
HttpClientNameonly when an interface really talks to a different host. (07) - [ ] Chain rate limiting and other conventions onto
MapRForgeAutoApi(). (08)
Deploying
- [ ] Deploy the server and the WebAssembly client from the same build. The routes are generated from the same source, so mixed versions can disagree. (02, 10)
Testing
- [ ] One round-trip fixture with
TestServerand a test auth scheme. Cover each exception type and each authorization rule. (09) - [ ] Test Interactive Server mode for any interface with
[RfAuthorize]. (09) - [ ] Test components with a fake of the interface, not with a server. (09)
- [ ] Run the fixture with
EnvironmentName = "Production", so unexpected errors are tested the way users see them. (09)