dotnet/aspnetcore

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

开放

#23,063 创建于 2020年6月17日

 (5 条评论) (2 个反应) (0 位负责人)C# (10,653 个派生)batch import
affected-fewarea-mvcbugfeature-routinghelp wantedseverity-major

仓库指标

星标
 (37,933 个星标)
PR 合并指标
 (PR 指标待抓取)

描述

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]

贡献者指南