Dto — Real-time with SignalR
Real-time push with [SignalRHub]
Section titled “Real-time push with [SignalRHub]”Add [SignalRHub] to an entity to generate a strongly-typed SignalR hub and client interface. When paired with [CrudApi], the generated POST/PATCH/DELETE endpoints automatically inject IHubContext and push notifications to connected clients after each store operation.
Standalone usage
Section titled “Standalone usage”[SignalRHub]public class Order{ public int Id { get; set; } public required string Product { get; set; } public decimal Total { get; set; }}This generates:
// Generated hub + client interfacepublic interface IOrderHubClient{ Task OnCreated(OrderResponse item); Task OnUpdated(OrderResponse item); Task OnDeleted(int id);}
public class OrderHub : Hub<IOrderHubClient> { }Paired with [CrudApi]
Section titled “Paired with [CrudApi]”When both attributes are present, the generated CRUD endpoints inject IHubContext<OrderHub, IOrderHubClient> and push automatically:
[CrudApi][SignalRHub]public class Order{ [DtoIgnore(DtoTarget.Create | DtoTarget.Update | DtoTarget.Query)] public int Id { get; set; } public required string Product { get; set; } public decimal Total { get; set; } public OrderStatus Status { get; set; }}The generated endpoints behave as:
| Endpoint | Store operation | SignalR push |
|---|---|---|
POST /api/orders | Create | Clients.All.OnCreated(response) |
PATCH /api/orders/{id} | Update | Clients.All.OnUpdated(response) |
DELETE /api/orders/{id} | Delete | Clients.All.OnDeleted(id) |
Map the generated hub in Program.cs:
builder.Services.AddSignalR();
var app = builder.Build();
app.MapOrderEndpoints(); // CRUD endpoints (generated)app.MapHub<OrderHub>("/api/orders/hub"); // SignalR hubClient interface shape
Section titled “Client interface shape”The generated IOrderHubClient always follows the same pattern:
public interface I{Entity}HubClient{ Task OnCreated({Entity}Response item); Task OnUpdated({Entity}Response item); Task OnDeleted(int id); // key type matches the entity's primary key}Frontend connection (TypeScript)
Section titled “Frontend connection (TypeScript)”Connect from a JavaScript/TypeScript client using the @microsoft/signalr package:
import { HubConnectionBuilder } from "@microsoft/signalr";
const connection = new HubConnectionBuilder() .withUrl("/api/orders/hub") .withAutomaticReconnect() .build();
connection.on("OnCreated", (order) => { console.log("New order:", order);});
connection.on("OnUpdated", (order) => { console.log("Updated order:", order);});
connection.on("OnDeleted", (id) => { console.log("Deleted order:", id);});
await connection.start();[SignalRHub]without[CrudApi]only generates the hub and interface — you callIHubContextyourself in custom endpoints or services.- The hub class is
partial, so you can addOnConnectedAsync/OnDisconnectedAsyncoverrides in a separate file. - Group-based broadcasting (e.g. per-tenant) is not generated — use the partial hub to add group logic when needed.