@@ -26,9 +26,10 @@ public static class TurboRoutingExtensions
2626When no type parameter is provided, entity keys are boxed ` object ` :
2727
2828``` csharp
29- app .MapTurboEntity (" /users/{id}" , builder =>
29+ app .MapTurboEntity (" /users/{id}" , entity =>
3030{
31- builder .OnGet (ctx => new GetUser (ctx .RouteValues [" id" ]));
31+ entity .UseActorRef <UserActor >();
32+ entity .OnGet ((string id ) => new GetUser (id ));
3233});
3334```
3435
@@ -37,13 +38,11 @@ app.MapTurboEntity("/users/{id}", builder =>
3738Specify a typed key for type safety:
3839
3940``` csharp
40- app .MapTurboEntity <int >(" /orders/{orderId}" , builder =>
41+ app .MapTurboEntity <int >(" /orders/{orderId}" , entity =>
4142{
42- builder .OnGet (ctx =>
43- {
44- var orderId = (int )ctx .RouteValues [" orderId" ];
45- return new GetOrder (orderId );
46- });
43+ entity .UseResolver <OrderEntityResolver >();
44+ entity .OnGet ((int orderId ) => new GetOrder (orderId ));
45+ entity .OnPost ((int orderId , CreateOrderRequest req ) => new CreateOrder (orderId , req .Items ));
4746});
4847```
4948
@@ -88,29 +87,28 @@ public sealed class TurboEntityBuilder
8887Specify what message to send for each HTTP method:
8988
9089``` csharp
91- builder .OnGet (ctx => new GetUser (ctx .RouteValues [" id" ]));
92- builder .OnPost (ctx => JsonConvert .DeserializeObject <CreateUserRequest >(
93- Encoding .UTF8 .GetString (ctx .Request .Body )));
94- builder .OnPut (ctx => new UpdateUser (ctx .RouteValues [" id" ], ctx .Request .Body ));
95- builder .OnDelete (ctx => new DeleteUser (ctx .RouteValues [" id" ]));
96- builder .OnPatch (ctx => new PatchUser (ctx .RouteValues [" id" ], ctx .Request .Body ));
90+ entity .OnGet ((int id ) => new GetUser (id ));
91+ entity .OnPost ((int id , CreateUserRequest req ) => new CreateUser (id , req .Name ));
92+ entity .OnPut ((int id , UpdateUserRequest req ) => new UpdateUser (id , req .Name ));
93+ entity .OnDelete ((int id ) => new DeleteUser (id ));
94+ entity .OnPatch ((int id , PatchUserRequest req ) => new PatchUser (id , req ));
9795```
9896
99- Each handler receives the ` TurboHttpContext ` and returns a message to send to the actor.
97+ Each handler receives typed parameters from the route and request body, and returns a message to send to the actor.
10098
10199### Response Mapping
102100
103101By default, responses from actors are serialized as JSON. Customize mapping with ` MapResponse<T> ` :
104102
105103``` csharp
106- builder .MapResponse <User >(async (context , user ) =>
104+ entity .MapResponse <User >(async (context , user ) =>
107105{
108106 context .Response .StatusCode = 200 ;
109107 context .Response .ContentType = " application/json" ;
110108 await context .Response .WriteAsJsonAsync (user );
111109});
112110
113- builder .MapResponse <ErrorResponse >(async (context , error ) =>
111+ entity .MapResponse <ErrorResponse >(async (context , error ) =>
114112{
115113 context .Response .StatusCode = error .StatusCode ;
116114 await context .Response .WriteAsJsonAsync (new { error = error .Message });
@@ -123,7 +121,7 @@ Set per-route timeout for actor responses:
123121
124122``` csharp
125123// Default: 30 seconds
126- builder .WithTimeout (TimeSpan .FromSeconds (60 ));
124+ entity .WithTimeout (TimeSpan .FromSeconds (60 ));
127125```
128126
129127If the actor doesn't respond within the timeout, the response is ` 504 Gateway Timeout ` .
@@ -145,7 +143,7 @@ public sealed class TurboEntityMethodBuilder
145143Respond with ` 202 Accepted ` instead of waiting for the actor's full response:
146144
147145``` csharp
148- builder .OnPost (ctx => new CreateUser (.. . ))
146+ entity .OnPost (( int id , CreateUserRequest req ) => new CreateUser (id , req . Name ))
149147 .AcceptedResponse ();
150148```
151149
@@ -156,10 +154,10 @@ Useful for long-running operations where you want to return immediately.
156154Override the route-level timeout for a specific method:
157155
158156``` csharp
159- builder .OnGet (ctx => new GetUser (.. . ))
157+ entity .OnGet (( int id ) => new GetUser (id ))
160158 .WithTimeout (TimeSpan .FromSeconds (5 ));
161159
162- builder .OnPost (ctx => new CreateUser (.. . ))
160+ entity .OnPost (( int id , CreateUserRequest req ) => new CreateUser (id , req . Name ))
163161 .WithTimeout (TimeSpan .FromSeconds (30 ));
164162```
165163
@@ -196,9 +194,9 @@ public class OrderActorResolver : IEntityActorResolver
196194}
197195
198196// Register it
199- builder .UseResolver (new OrderActorResolver (orderManagerRef ));
197+ entity .UseResolver (new OrderActorResolver (orderManagerRef ));
200198// Or as a type
201- builder .UseResolver <OrderActorResolver >();
199+ entity .UseResolver <OrderActorResolver >();
202200```
203201
204202### 2. ActorRef Factory
@@ -207,13 +205,13 @@ Direct reference to a specific actor:
207205
208206``` csharp
209207// From dependency injection
210- builder .UseActorRef ((serviceProvider ) =>
208+ entity .UseActorRef ((serviceProvider ) =>
211209{
212210 return serviceProvider .GetRequiredService <IActorRef >(" userActorRef" );
213211});
214212
215213// From actor registry
216- builder .UseActorRef ((registry ) =>
214+ entity .UseActorRef ((registry ) =>
217215{
218216 return registry .Resolve <UserActor >();
219217});
@@ -224,7 +222,7 @@ builder.UseActorRef((registry) =>
224222Use the type system to locate actors by type:
225223
226224``` csharp
227- builder .UseActorRef <UserActor >();
225+ entity .UseActorRef <UserActor >();
228226```
229227
230228This looks up ` UserActor ` in the actor registry.
@@ -259,36 +257,20 @@ public class UserActor : ReceiveActor
259257}
260258
261259// Route registration
262- app .MapTurboEntity <int >(" /users/{id}" , builder =>
260+ app .MapTurboEntity <int >(" /users/{id}" , entity =>
263261{
264- // GET /users/123
265- builder .OnGet (ctx =>
266- {
267- var id = (int )ctx .RouteValues [" id" ];
268- return new UserActor .GetUser { Id = id };
269- });
262+ entity .UseActorRef <UserActor >();
270263
271- // POST /users (body contains name)
272- builder .OnPost (async ctx =>
273- {
274- var body = await ctx .Request .BodyReader .ReadAsync ();
275- var json = Encoding .UTF8 .GetString (body .Buffer );
276- var req = JsonConvert .DeserializeObject <CreateUserRequest >(json );
277- return new UserActor .CreateUser { Name = req .Name };
278- });
264+ entity .OnGet ((int id ) => new UserActor .GetUser { Id = id });
265+ entity .OnPost ((int id , CreateUserRequest req ) => new UserActor .CreateUser { Name = req .Name });
279266
280- // Custom response mapping
281- builder .MapResponse <UserActor .User >(async (context , user ) =>
267+ entity .MapResponse <UserActor .User >(async (context , user ) =>
282268 {
283269 context .Response .ContentType = " application/json" ;
284270 await context .Response .WriteAsJsonAsync (user );
285271 });
286272
287- // 30-second timeout for responses
288- builder .WithTimeout (TimeSpan .FromSeconds (30 ));
289-
290- // Resolve to the UserActor
291- builder .UseActorRef <UserActor >();
273+ entity .WithTimeout (TimeSpan .FromSeconds (30 ));
292274});
293275```
294276
@@ -314,7 +296,7 @@ If the actor doesn't respond within the timeout, the response is `504 Gateway Ti
314296If the actor throws an exception or the message doesn't match a handler, the gateway responds with ` 500 Internal Server Error ` . Use status code routing or custom response mappers to handle errors from the actor:
315297
316298``` csharp
317- builder .MapResponse <Result <User >>(async (context , result ) =>
299+ entity .MapResponse <Result <User >>(async (context , result ) =>
318300{
319301 if (result .IsSuccess )
320302 {
@@ -332,7 +314,7 @@ builder.MapResponse<Result<User>>(async (context, result) =>
332314Or use a wrapper response type:
333315
334316``` csharp
335- builder .MapResponse <ApiResponse >(async (context , response ) =>
317+ entity .MapResponse <ApiResponse >(async (context , response ) =>
336318{
337319 context .Response .StatusCode = response .StatusCode ;
338320 await context .Response .WriteAsJsonAsync (response );
0 commit comments