Route template contains a backslash instead of a forward slash
ID |
vbnet.correctness.no_backslash_in_route_template |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Api Design |
Language |
VB.NET |
Description
Reports a backslash inside the template argument of a routing attribute - <Route>,
<RoutePrefix> or one of the <HttpGet>, <HttpPost>, <HttpPut>, <HttpDelete>,
<HttpPatch>, <HttpHead> and <HttpOptions> verb attributes, with or without the Attribute
suffix and qualified or not. The attribute is checked both on the controller class, where it
contributes a route prefix, and on the action method. Attributes with no arguments, and templates
that use only forward slashes, are not reported; a backslash in a non-routing attribute such as
<Obsolete> is not examined.
Rationale
The forward slash is the only segment separator a route template has. A backslash is not an
escape character and not an alternative separator - it is an ordinary character, so
<RoutePrefix("api\v1\orders")> declares a single segment whose literal name contains two
backslashes rather than the three-segment prefix it looks like. Nothing rejects it: the template
is valid, the route is registered, and the application starts normally. What follows is a route
that only matches a URL nobody will send, because a client sending /api/v1/orders gets a 404
while the registered pattern waits for a path segment spelled api\v1\orders - and a backslash
in a request line is either rejected by the host or normalised to a forward slash before it ever
reaches routing, so on many stacks the route becomes unreachable altogether. The mistake is easy
to make and hard to see, since the value is an ordinary string in a language where \ carries no
special meaning, so it reads as a path separator to anyone who has written a file path. It also
breaks link generation in the same direction: helpers that build a URL from the template emit the
backslash, so generated links point at a path the router does not serve.
The following code illustrates the pattern detected by this rule:
Namespace Acme.Api
' FLAGGED: Route template contains a backslash instead of a forward slash
<RoutePrefix("api\v1\orders")>
Public Class LegacyOrdersController
Inherits ApiController
Remediation
Replace each backslash with a forward slash, keeping the segments otherwise unchanged - the parameter placeholders in braces and any inline constraints do not need editing. Where a backslash really is meant to be part of a literal segment value, it must be percent-encoded in the URL and does not belong in the template. After the fix, check any generated links, tests and client code that hardcoded the previous path.
' Before: one segment literally named "api\v1\orders"
<RoutePrefix("api\v1\orders")>
Public Class OrdersController
<HttpGet("lookup\\{code}")>
Public Function Lookup(code As String) As String
' After
<RoutePrefix("api/v1/orders")>
Public Class OrdersController
<HttpGet("lookup/\{code}")>
Public Function Lookup(code As String) As String