dotnet/aspnetcore

TransformOutbound of route constraint is not called when the route segment is optional

Open

#23,063 opened on Jun 17, 2020

View on GitHub
 (5 comments) (2 reactions) (0 assignees)C# (10,653 forks)batch import
affected-fewarea-mvcbugfeature-routinghelp wantedseverity-major

Repository metrics

Stars
 (37,933 stars)
PR merge metrics
 (Avg merge 16d 9h) (258 merged PRs in 30d)

Description

Describe the bug

TransformOutbound is not callled when generating url when the constraint in the route template is is optional.

To Reproduce

https://github.com/vjacquet/bugs/blob/3fbc2924345021175b911b651b5afe3524cde361/aspnetcore/RouteConstraint/Startup.cs#L51

The Index page show that the last segment of the 2 urls are different when they shouldn't Route.cshtml as the route definition @page "{id:hex}" RouteWithOptionalSegment.cshtml as the route definition @page "{id:hex?}"

The problem is that OptionalRouteConstraint, that wrap the specified route contraint, does not implement IOutboundParameterTransformer, therefore _parameterTransformers in TemplateBinder is not initialized correctly.

One possible fix is to define

class OutboundParameterTransformerOptionalRouteConstraint : OptionalRouteConstraint, IOutboundParameterTransformer
{
    public OutboundParameterTransformerOptionalRouteConstraint(IRouteConstraint innerConstraint) : base(innerConstraint)
    {
    }

    public string TransformOutbound(object value) => ((IOutboundParameterTransformer)InnerConstraint).TransformOutbound(value);
}

and have the DefaultParameterPolicy's InitializeRouteConstraint method return an instance of it when the constraint is optional and the routeConstraint implements IOutboundParameterTransformer.

private IParameterPolicy InitializeRouteConstraint(bool optional, IRouteConstraint routeConstraint)
{
    if (!optional)
        return routeConstraint;
    else if (routeConstraint is IOutboundParameterTransformer)
        return new OutboundParameterTransformerOptionalRouteConstraint(routeConstraint);
    else
        return new OptionalRouteConstraint(routeConstraint);
}

Further technical details

  • ASP.NET Core version 3.1

.NET Core SDK (reflecting any global.json): Version: 3.1.301 Commit: 7feb845744

Runtime Environment: OS Name: Windows OS Version: 10.0.18362 OS Platform: Windows RID: win10-x64 Base Path: C:\Program Files\dotnet\sdk\3.1.301\

Host (useful for support): Version: 3.1.5 Commit: 65cd789777

.NET Core SDKs installed: 1.1.14 [C:\Program Files\dotnet\sdk] 2.1.401 [C:\Program Files\dotnet\sdk] 2.1.802 [C:\Program Files\dotnet\sdk] 2.2.103 [C:\Program Files\dotnet\sdk] 3.1.200 [C:\Program Files\dotnet\sdk] 3.1.202 [C:\Program Files\dotnet\sdk] 3.1.301 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed: Microsoft.AspNetCore.All 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.All 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.All 2.1.19 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.All 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.App 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 2.1.19 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.NETCore.App 1.0.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 1.1.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.1.19 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.WindowsDesktop.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Contributor guide