Search code examples
asp.net-coreurl-routingasp.net-mvc-routing

How to detect reason of wrong routing in ASP.NET Core 6


I try to change existing project and failed. For understanding issue I have write route analyzer, this is simple code

    App.Use(Async Function(context, [next])
                Dim CurrentEndpoint = context.GetEndpoint()
                If (CurrentEndpoint Is Nothing) Then
                    Debug.WriteLine($"RequestPath {context.Request.Path} endpoint nothing.")
                    Await [next](context)
                Else
                    Debug.WriteLine($"Endpoint: {CurrentEndpoint.DisplayName}")
                    Dim Endpoint As RouteEndpoint = TryCast(CurrentEndpoint, RouteEndpoint)
                    Debug.WriteLine($"RoutePattern: {Endpoint?.RoutePattern.RawText}")
                    For j As Integer = 0 To CurrentEndpoint.Metadata.Count - 1
                        Debug.WriteLine($"Endpoint Metadata {j}: {CurrentEndpoint.Metadata(j)}")
                    Next
                    Await [next](context)
                End If
            End Function)

For correct project I see this result in log

 Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request starting HTTP/2 GET https://localhost:7167/Identity/Account/Login - -
 Endpoint: /Account/Login
 RoutePattern: Identity/Account/Login
 Endpoint Metadata 0: Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute
 Endpoint Metadata 1: Microsoft.AspNetCore.Identity.UI.IdentityDefaultUIAttribute
 Endpoint Metadata 2: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageModelAttribute
 Endpoint Metadata 3: Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute
 Endpoint Metadata 4: System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute
 Endpoint Metadata 5: Microsoft.AspNetCore.Mvc.ApplicationModels.PageRouteMetadata
 Endpoint Metadata 6: Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor
 Endpoint Metadata 7: Microsoft.AspNetCore.Routing.RouteNameMetadata
 Endpoint Metadata 8: Microsoft.AspNetCore.Mvc.Filters.PageHandlerPageFilter
 Endpoint Metadata 9: Microsoft.AspNetCore.Mvc.ViewFeatures.SaveTempDataAttribute
 Endpoint Metadata 10: Microsoft.AspNetCore.Mvc.ModelBinding.UnsupportedContentTypeFilter
 Endpoint Metadata 11: Microsoft.AspNetCore.Mvc.Filters.PageSaveTempDataPropertyFilterFactory
 Endpoint Metadata 12: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.HandleOptionsRequestsPageFilter   
 Endpoint Metadata 13: Microsoft.AspNetCore.Mvc.AutoValidateAntiforgeryTokenAttribute Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executing endpoint '/Account/Login'
 Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker: Information: Route matched with {page = "/Account/Login", area = "Identity", action = "", controller = ""}. Executing page /Account/Login

After my changing I receive absolutely wrong routing

 Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request starting HTTP/2 GET https://localhost:7168/?area=Identity&page=%2FAccount%2FLogin - -
 Endpoint: FrontEnd.Controllers.HomeController.Index (FrontEndCode)
 RoutePattern: {controller=Home}/{action=Index}/{id?}
 Endpoint Metadata 0: Microsoft.AspNetCore.Mvc.ControllerAttribute
 Endpoint Metadata 1: Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor
 Endpoint Metadata 2: Microsoft.AspNetCore.Routing.DataTokensMetadata
 Endpoint Metadata 3: Microsoft.AspNetCore.Routing.RouteNameMetadata
 Endpoint Metadata 4: Microsoft.AspNetCore.Mvc.Filters.ControllerActionFilter
 Endpoint Metadata 5: Microsoft.AspNetCore.Mvc.ViewFeatures.SaveTempDataAttribute
 Endpoint Metadata 6: Microsoft.AspNetCore.Mvc.ModelBinding.UnsupportedContentTypeFilter
 Endpoint Metadata 7: Microsoft.AspNetCore.Routing.SuppressLinkGenerationMetadata   
 Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executing endpoint 'FrontEnd.Controllers.HomeController.Index (FrontEndCode)'   
 Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Information: Route matched with {action = "Index", controller = "Home"}. Executing controller action with signature Microsoft.AspNetCore.Mvc.IActionResult Index() on controller FrontEnd.Controllers.HomeController (FrontEndCode).

my changing is not simple and I can not right for full describe it from site owner, but my changing is related to database and not related to routing pattern at all.

I want to understand what happens with routing and making something patch additionally to my changing, maybe additionally attributes or something options. But I can not understand reason of this huge changing of routing - after my changing always executing only Home Controller, Areas endpoint fully ignored, routing metadata is disappear and so on.

And how to use check all MVC project endpoint like we usually doing with backend API by Swagger?


Solution

  • In this case there are 14 rules to define finally endpoint mapping to request. We need carefully look one by one rules. In this case - top rules is AllowAnonymousAttribute. Usually this is not set route. Next rules for priority UI.IdentityDefaultUIAttribute.

    <AttributeUsage(AttributeTargets.[Class], Inherited:=False, AllowMultiple:=False)>
    Friend NotInheritable Class IdentityDefaultUIAttribute
        Inherits Attribute
        Public ReadOnly Property Template As Type
    
        Public Sub New(ByVal implementationTemplate As Type)
            MyBase.New()
            Me.Template = implementationTemplate
        End Sub
    End Class
    

    this two attribute added to each DefaultUI page

    <AllowAnonymous>
    <IdentityDefaultUI(GetType(ConfirmEmailChangeModel(Of )))>
    Public MustInherit Class ConfirmEmailChangeModel
        Inherits PageModel
        ''' <summary>
        '''     This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
        '''     directly from your code. This API may change or be removed in future releases.
        ''' </summary>
        <TempData>
        Public Property StatusMessage As String
    
        Protected Sub New()
            MyBase.New()
        End Sub
    

    This is a reference, that this rules added by DefaultUI what changed Microsoft.AspNetCore.Mvc.RazorPages.RazorPagesOptions.Conventions what full change routing of the site by adding custom actions to routing.

    For experienced programmer this is enough that 4 top priority routing rules adding by default UI. Therefore in second project is lost DefultUI, so

    Routing for first project created as

     Builder.Services.
     AddIdentity(Of ApplicationUser, ApplcationRole).
     AddDefaultUI().
     AddDefaultTokenProviders().
     AddUserStore(Of CustomUserStore).
     AddRoleStore(Of CustomRoleStore)()
    

    routing for second project created as

     Builder.Services.
     AddIdentity(Of ApplicationUser, ApplcationRole).
     AddDefaultTokenProviders().
     AddUserStore(Of CustomUserStore).
     AddRoleStore(Of CustomRoleStore)()