REST API — Attribute Reference¶
[RestApi]¶
Marks a [Runtime] class as a REST API entry point. The generator discovers all dispatch handlers with HTTP method attributes and produces Minimal API endpoint mappings.
[Runtime]
[RestApi(RoutePrefix = "/api/catalog", Title = "eShop Catalog API")]
public partial class CatalogApp;
Target: partial class
Properties:
| Property | Type | Default | Description |
|---|---|---|---|
RoutePrefix |
string |
"/api" |
Base route prefix for all generated endpoints |
Title |
string? |
Inferred from assembly | Application title for OpenAPI metadata |
Constraints:
- One
[RestApi]per class - The class must be
partial - Generates
Add{TypeName}()andMap{TypeName}()extension methods
HTTP Method Attributes¶
These attributes map dispatch handlers to HTTP endpoints. Apply them alongside [CommandHandler] or [QueryHandler].
[HttpGet(string template)]¶
public sealed record GetCatalogItemById(CatalogItemId Id) : IQuery;
public static class GetCatalogItemByIdHandler
{
[QueryHandler, HttpGet("/items/{id}")]
public static Eff<CatalogRuntime, Option<CatalogItem>> Handle(GetCatalogItemById query) =>
CatalogStore.CatalogItems.GetById<CatalogRuntime>(query.Id);
}
Route parameters bind from the URL path. Query string parameters are also supported via record properties.
[HttpPost(string template)]¶
public sealed record CreateCatalogItem(string Name, decimal Price) : ICommand;
public static class CreateCatalogItemHandler
{
[CommandHandler, HttpPost("/items")]
public static Eff<CatalogRuntime, CatalogItem> Handle(CreateCatalogItem cmd) =>
from item in SuccessEff(new CatalogItem(CatalogItemId.New(), cmd.Name, cmd.Price))
from _ in CatalogStore.CatalogItems.Save<CatalogRuntime>(item)
select item;
}
The request body is deserialized as the command record. Returns 201 Created by default.
[HttpPut(string template)]¶
public sealed record UpdateCatalogItemPrice(CatalogItemId ItemId, decimal NewPrice) : ICommand;
public static class UpdateCatalogItemPriceHandler
{
[CommandHandler, HttpPut("/items/{catalogItemId}/price")]
public static Eff<CatalogRuntime, ProductPriceChanged> Handle(UpdateCatalogItemPrice cmd) =>
from item in CatalogStore.CatalogItems.Require<CatalogRuntime>(cmd.ItemId)
let oldPrice = item.Price
from _ in Mutate<CatalogRuntime>(() => item.Price = cmd.NewPrice)
>> CatalogStore.CatalogItems.Save<CatalogRuntime>(item)
select new ProductPriceChanged(cmd.ItemId, oldPrice, cmd.NewPrice);
}
Full resource replacement. Returns 204 No Content.
[HttpPatch(string template)]¶
public sealed record UpdateCatalogItemDescription(
CatalogItemId ItemId, string Description) : ICommand;
public static class UpdateCatalogItemDescriptionHandler
{
[CommandHandler, HttpPatch("/items/{catalogItemId}/description")]
public static Eff<CatalogRuntime, Unit> Handle(UpdateCatalogItemDescription cmd) =>
from item in CatalogStore.CatalogItems.Require<CatalogRuntime>(cmd.ItemId)
from _ in Mutate<CatalogRuntime>(() => item.Description = cmd.Description)
>> CatalogStore.CatalogItems.Save<CatalogRuntime>(item)
select unit;
}
Partial resource update. Returns 200 OK.
[HttpDelete(string template)]¶
public sealed record DeleteCatalogItem(CatalogItemId ItemId) : ICommand;
public static class DeleteCatalogItemHandler
{
[CommandHandler, HttpDelete("/items/{catalogItemId}")]
public static Eff<CatalogRuntime, Unit> Handle(DeleteCatalogItem cmd) =>
CatalogStore.CatalogItems.Delete<CatalogRuntime>(cmd.ItemId);
}
Returns 204 No Content by default (no response body).
Common Properties¶
All HTTP method attributes inherit from HttpMethodAttribute:
| Property | Type | Description |
|---|---|---|
Template |
string |
The route template (e.g., "/api/items/{id}") |
Route parameters use ASP.NET Core conventions: {id}, {id:guid}, etc.
[Public]¶
Marks a handler as publicly accessible — no authentication required, even when [WebAuth] is configured on the runtime.
public sealed record GetCatalogItems(int Page = 1, int PageSize = 10) : IQuery;
public static class GetCatalogItemsHandler
{
[QueryHandler, HttpGet("/items"), Public]
public static Eff<CatalogRuntime, QueryResult<CatalogItem>> Handle(GetCatalogItems query) =>
CatalogStore.CatalogItems.QueryPage<CatalogRuntime>(query.Page, query.PageSize);
}
Without [Public], all endpoints require a valid JWT Bearer token when [WebAuth] is present.
[WebAuth(params string[] providers)]¶
Enables authentication endpoint generation on a [RestApi] runtime. Each provider gets its own login endpoint.
Generated endpoints:
| Endpoint | Method | Description |
|---|---|---|
/api/auth/{provider}/login |
POST | Verify provider token, issue JWT access + refresh tokens |
/api/auth/refresh |
POST | Exchange refresh token for new access token |
/api/auth/logout |
POST | Revoke refresh token |
Supported providers: "google" (via IGoogleTokenVerifier). Additional providers can be added by implementing the auth interface pattern.
Requires: Deepstaging.Auth package for IJwtService, IGoogleTokenVerifier, and HttpContextUserContext implementations.
[WebSocket(WebSocketProvider provider)]¶
Enables WebSocket support on a [RestApi] runtime. Generates a WebSocket upgrade endpoint.
[RestApi(RoutePrefix = "/api", Title = "eShop")]
[WebSocket(WebSocketProvider.InMemory)]
public partial class AppApi;
Generated endpoint:
| Endpoint | Description |
|---|---|
/ws |
WebSocket upgrade with JWT authentication from ?token= query parameter |
Providers:
| Value | Description |
|---|---|
WebSocketProvider.InMemory |
Single-server ConcurrentDictionary-backed connection manager |
See WebSocket for the connection manager API.
[AzureFunctionsApi]¶
Marks a partial class as the Azure Functions Isolated Worker API entry point. The generator produces [Function] classes with [HttpTrigger] bindings for all dispatch handlers that have HTTP route attributes.
Target: partial class
Properties:
| Property | Type | Default | Description |
|---|---|---|---|
RoutePrefix |
string |
"" |
Base route prefix for all generated function endpoints |
Notes:
- Can coexist with
[RestApi]on the same class — both generators emit independently - Does not use group prefixes like Minimal APIs — Azure Functions routing applies its own conventions
var host = new HostBuilder()
.ConfigureFunctionsWebApplication()
.AddAppRuntime()
.Build();
host.Run();
[Webhook<TValidator>]¶
Marks a handler method as a webhook endpoint requiring signature validation before processing. Apply alongside an HTTP verb attribute (typically [HttpPost]).
[CommandHandler]
[HttpPost("/webhooks/twilio/sms")]
[Webhook<TwilioWebhookValidator>]
public static Eff<AppRuntime, Unit> HandleInboundSms(AcceptReply cmd) => ...
Type parameter: TValidator must implement IWebhookValidator — the runtime calls its ValidateAsync method to verify the inbound request signature before the handler executes.
Usage: Webhook validators are typically provided by infrastructure packages (e.g., TwilioWebhookValidator from Deepstaging.Twilio). The generated endpoint reads the raw request body and headers, passes them to the validator, and short-circuits with 401 Unauthorized on failure.