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

Configuration

This detector does not need any configuration.