API.DataRouter
Version 1 · Document the API.DataRouter data-feed API: endpoints, services, middleware, config
API.DataRouter
The central data-feed REST API. It routes and serves racing data (race cards, results, trials, meetings, master data, lookups) from MySQL, and applies per-customer [[data-fingerprinting]] to outbound feeds. It is the only project in the solution with a Dockerfile and docker-compose.yml.
SDK: Microsoft.NET.Sdk.Web. Key packages: MySql.Data 9.1.0, Newtonsoft.Json 13.0.4, Swashbuckle.AspNetCore 6.4.0, Microsoft.AspNetCore.OpenApi 8.0.7. Project reference: DataFingerprinting.
Startup
Program.cs registers controllers, Swagger (currently always on), and AddFingerprinting(Configuration). It reads three connection strings — RasDb, QdsDb, QdsDbTemp — and registers the data services as singletons: RaceCardService, RaceResultService (injected IFingerprintService), LookupService, MasterDataService, MeetingService, TrialService. ApiKeyCustomerMiddleware runs before MapControllers().
Data access is raw ADO.NET over MySqlConnection with SQL strings — no ORM.
Endpoints
| Controller | Route(s) |
|---|---|
RaceCardController |
GET /api/RaceCard/{meetingId}, GET /api/RaceCard/racecard10/{meetingId} |
RaceResultController |
GET /api/RaceResult/{meetingId} — reads the resolved customer id from HttpContext.Items and passes it to the service for fingerprinting |
TrialController |
GET /api/Trial?date=yyyy-MM-dd&courseId=… |
MeetingController |
GET /api/Meeting?type={racecard|result|trial}&date=&token=&discipline= |
MasterDataController |
POST /api/v1/masterdata/weather |
LookupController |
POST /api/v1/lookup/read, POST /api/v1/lookup/write (write rejects array payloads; maps 200/201/400/404/409/413/500) |
IdTranslatorController |
POST /api/IdTranslator/encode, POST /api/IdTranslator/decode |
Services
LookupService—generic_lookupread/write.MasterDataService— weather upsert across multiple QDS connections, with country / course resolution.MeetingService— meeting lists by type / date / discipline.RaceCardService— race cards (plus weather-by-race and stewards incidents).RaceResultService— race results; injectsIFingerprintServiceand fingerprintsrace_time_seconds,runner_time_seconds, and sectional times.TrialService— barrier-trial data.
Utilities
IdTranslator— encodes/decodes record ids to/from ROT13-obfuscated GUIDs carrying table enum, record id, and version.IdResolver—Resolve(encodedId, TableType).Helpers,Common,JsonExtensions.
Middleware
ApiKeyCustomerMiddleware reads the X-Api-Key header, matches it to a configured customer's ApiKey, and stashes the customer id in HttpContext.Items. Non-blocking: an absent or unknown key simply means no fingerprinting — the request is still served. This header identifies a fingerprinting customer only; it does not authenticate or authorize the request.
Configuration
appsettings.json holds the three connection strings and the Fingerprinting section (Customers and Policies). docker-compose.yml runs the service as api-datarouter on 8080:8080 with ASPNETCORE_ENVIRONMENT=Production, overriding RasDb / QdsDb (→ qds_dev) via env vars. The Dockerfile is a multi-stage build on the .NET 8 aspnet/sdk images, exposing 8080.
Live MySQL credentials are currently committed in
appsettings.jsonanddocker-compose.yml. Treat them as secrets and move them to a secret store before deployment.
Naming note
The QDG.* namespaces (QDG.Services.LookupService, QDG.Controllers.LookupController, QDG.DTOs) physically live in this project, not in the separate QDG MVC project.