Overview
The runtime routing system maps incoming HTTP requests or RPC calls to specific service entries (ServiceEntry) for execution. The process has two phases:
- Startup: Static route table generation from application service interface definitions
- Runtime: Matching requests against the route table and dispatching to the correct service entry
Route Template Generation
[ServiceRoute] and Route Templates
Every application service interface must be annotated with [ServiceRoute], which specifies the route prefix template for all service entries under that interface:
// Default template: api/{appservice}
[ServiceRoute]
public interface IOrderAppService { }
// Generated prefix: api/order
// Custom appservice name
[ServiceRoute("{appservice=orders}")]
public interface IOrderAppService { }
// Generated prefix: api/orders
// Fully custom prefix
[ServiceRoute("v2/orders")]
public interface IOrderAppServiceV2 { }
// Generated prefix: v2/orders
The {appservice} placeholder is automatically replaced with the interface name (strip I prefix and AppService suffix, convert to kebab-case).
Route Segment Types
Templates are split into segments:
| Type | Description | Example |
|---|---|---|
Literal | Fixed string path segment | api, v2, orders |
AppService | {appservice} placeholder replaced by the service name | {appservice} → order |
Path | {paramName} or {paramName:type} dynamic path parameter | {id}, {id:long} |
HTTP Verb Inference from Method Name
When no explicit HTTP verb attribute is used, Silky infers the HTTP method from the method name prefix:
| HTTP Method | Stripped Method Name Prefixes |
|---|---|
GET | Get, Query, Search, Find |
POST | Create, Add, Post, Submit |
PUT | Update, Edit, Put |
DELETE | Delete, Remove |
PATCH | Patch |
Example: GetByIdAsync(long id) → GET /api/order/{id}
Explicit HTTP Verb Attributes
Override inference with explicit attributes:
[HttpGet("detail/{id}")] // full custom route
[HttpPost] // POST, method name as action
[HttpPut("{id}")]
[HttpDelete("{id}")]
Runtime Route Matching
Endpoint Registration
SilkyServiceEntryEndpointDataSource registers every ServiceEntry as an ASP.NET Core Endpoint at startup. Standard ASP.NET Core routing matches the HTTP method + URL path to the endpoint.
On a successful match, ServiceEntry and ServiceEntryDescriptor are written to HttpContext.Items for downstream handlers.
Local vs. Remote Dispatch
After route matching resolves a ServiceEntry:
RouteMatchResult (ServiceEntry found)
│
▼
DefaultExecutor.Execute(serviceEntry, parameters)
│
├── serviceEntry.IsLocal = true → LocalExecutor → business method (this instance)
└── serviceEntry.IsLocal = false → RemoteExecutor → DotNetty RPC → target microservice
IsLocal is determined at startup: if the current host has an implementation class for the interface, IsLocal = true; otherwise it's a proxy for another microservice.
Parameter Extraction
Parameters are extracted from multiple sources and bound by ParameterDescriptor.From:
Source (ParameterFrom) | Description |
|---|---|
Path | Extracted from URL path segment (e.g., /api/order/{id}) |
Query | Extracted from query string (?key=value) |
Body | Deserialized from the JSON request body |
Form | From multipart form data |
Header | From request headers |
