Spurious "Ignoring registering duplicate route" warning under MapEndpoints() for same-path/different-verb DTOs

ServiceStack 10.0.8, ASP.NET Core Endpoint Routing (o.MapEndpoints()).

Two request DTOs that share a base path but use different verbs produce a startup warning:

[Route("/things/{Id}", "GET")] public class GetThing : IReturnVoid { public int Id { get; set; } }
[Route("/things/{Id}", "PUT")] public class UpdateThing : IReturnVoid { public int Id { get; set; } }

WARN Ignoring registering duplicate route: /things/{Id}.{format} for UpdateThing and GetThing

The base route /things/{Id} registers fine under both verbs - only the synthesized .{format} route warns. Looking at AppHostBase.MapUserDefinedRoutes, the .{format} branch dedups via a Dictionary<string, RestPath> keyed by path only - the verb isn’t in the key, even though it’s passed straight into the following MapMethods(routePath, verb, ...). So both DTOs compute the same /things/{Id}.{format} key, the second collides and is skipped + warned, despite [GET] and [PUT] variants being distinct valid endpoints. The base route escapes because it’s an unconditional overwrite with no check-then-warn.

Impact is minor - base verb endpoints work, content negotiation still works via ?format=/Accept, and AllowRouteContentTypeExtensions doesn’t gate this path - but it’s noisy at startup for an idiomatic resource-centric layout (separate read/mutate DTOs on one path), and the second DTO’s .{format} route silently doesn’t register.

Is this expected, or worth including the verb in the .{format} dedup key so the variants don’t collide?

It should most likely only be registered for GET routes, but I’ve changed it to included the Verb in the deduplication dictionary so it registers the .{format} route for different Verbs with the same path.

This change is available from v10.0.9+ that’s now available in pre-release packages.

Note: It’s recommended for APIs to have IVerb interface markers, e.g. IGet, IPut, etc.

1 Like