web-dev-qa-db-fra.com

Obtenir la liste de tous les itinéraires

Dans ASP.NET Core, existe-t-il un moyen de voir une liste de toutes les routes définies dans Démarrage? Nous utilisons la méthode d'extension MapRoute de IRouteBuilder pour définir les routes.

Nous migrons un ancien projet WebAPI. Là, nous pourrions utiliser GlobalConfiguration.Configuration.Routes pour obtenir tous les itinéraires.

Plus précisément, nous le faisons dans un filtre d'action.

public class MyFilter : ActionFilterAttribute
{      
    public override void OnActionExecuting(ActionExecutingContext actionContext)
    {
        base.OnActionExecuting(actionContext);

        // This no longer works
        // var allRoutes = GlobalConfiguration.Configuration.Routes;

        // var allRoutes = ???
    }
}
21
clhereistian

Pour obtenir tous les itinéraires, vous devez utiliser la partie ApiExplorer de MVC. Vous pouvez soit marquer toutes vos actions avec un attribut, soit utiliser une convention comme celle-ci:

public class ApiExplorerVisibilityEnabledConvention : IApplicationModelConvention
{
    public void Apply(ApplicationModel application)
    {
        foreach (var controller in application.Controllers)
        {
            if (controller.ApiExplorer.IsVisible == null)
            {
                controller.ApiExplorer.IsVisible = true;
                controller.ApiExplorer.GroupName = controller.ControllerName;
            }
        }
    }
}

Dans Startup.cs, ajoutez votre nouveau dans ConfigureServices(...)

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(
        options => 
        {
            options.Conventions.Add(new ApiExplorerVisibilityEnabledConvention());
            options.
        }
}

Dans votre ActionFilter, vous pouvez ensuite utiliser l'injection de constructeur pour obtenir l'ApiExplorer:

public class MyFilter : ActionFilterAttribute
{      
    private readonly IApiDescriptionGroupCollectionProvider descriptionProvider;

    public MyFilter(IApiDescriptionGroupCollectionProvider descriptionProvider) 
    {
        this.descriptionProvider = descriptionProvider;
    }

    public override void OnActionExecuting(ActionExecutingContext actionContext)
    {
        base.OnActionExecuting(actionContext);

        // The convention groups all actions for a controller into a description group
        var actionGroups = descriptionProvider.ApiDescriptionGroups.Items;

        // All the actions in the controller are given by
        var apiDescription = actionGroup.First().Items.First();

        // A route template for this action is
        var routeTemplate = apiDescription.RelativePath
    }
}

ApiDescription, qui a le RelativePath, qui est le modèle de route pour cette route:

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.ModelBinding;

namespace Microsoft.AspNetCore.Mvc.ApiExplorer
{
    public class ApiDescription
    {
        public string GroupName { get; set; }
        public string HttpMethod { get; set; }
        public IList<ApiParameterDescription> ParameterDescriptions { get; } = new List<ApiParameterDescription>();
        public IDictionary<object, object> Properties { get; } = new Dictionary<object, object>();
        public string RelativePath { get; set; }
        public ModelMetadata ResponseModelMetadata { get; set; }
        public Type ResponseType { get; set; }
        public IList<ApiRequestFormat> SupportedRequestFormats { get; } = new List<ApiRequestFormat>();
        public IList<ApiResponseFormat> SupportedResponseFormats { get; } = new List<ApiResponseFormat>();
    }
}
20
Dr Rob Lang

Vous pouvez jeter un œil à cet impressionnant projet GitHub:

https://github.com/kobake/AspNetCore.RouteAnalyzer

Lisez-moi du projet

=======================

AspNetCore.RouteAnalyzer

Afficher toutes les informations sur l'itinéraire pour le projet ASP.NET Core.

Capture d'écran ramassée

screenshot

Utilisation sur votre projet ASP.NET Core

Installer le package NuGet

PM> Install-Package AspNetCore.RouteAnalyzer

Modifier Startup.cs

Insérez le code services.AddRouteAnalyzer(); et la directive using requise dans Startup.cs comme suit.

using AspNetCore.RouteAnalyzer; // Add

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddRouteAnalyzer(); // Add
}

Cas 1: Afficher les informations d'itinéraire sur le navigateur

Insérez le code routes.MapRouteAnalyzer("/routes"); dans Startup.cs comme suit.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    ....
    app.UseMvc(routes =>
    {
        routes.MapRouteAnalyzer("/routes"); // Add
        routes.MapRoute(
            name: "default",
            template: "{controller}/{action=Index}/{id?}");
    });
}

Ensuite, vous pouvez accéder à l'URL de http://..../routes Pour afficher toutes les informations sur l'itinéraire sur votre navigateur. (Cette URL /routes Peut être personnalisée par MapRouteAnalyzer().)

screenshot

Cas 2: Imprimer les itinéraires sur le panneau de sortie VS

Insérez un bloc de code comme ci-dessous dans Startup.cs.

public void Configure(
    IApplicationBuilder app,
    IHostingEnvironment env,
    IApplicationLifetime applicationLifetime, // Add
    IRouteAnalyzer routeAnalyzer // Add
)
{
    ...

    // Add this block
    applicationLifetime.ApplicationStarted.Register(() =>
    {
        var infos = routeAnalyzer.GetAllRouteInformations();
        Debug.WriteLine("======== ALL ROUTE INFORMATION ========");
        foreach (var info in infos)
        {
            Debug.WriteLine(info.ToString());
        }
        Debug.WriteLine("");
        Debug.WriteLine("");
    });
}

Ensuite, vous pouvez afficher toutes les informations d'itinéraire sur le panneau de sortie VS.

screenshot

6

Pas réussi avec ce qui précède, car je voulais une URL complète que je n'ai pas eu à jouer avec les choses pour construire l'URL, mais à la place laisser le framework gérer la résolution. Donc, à la suite de AspNetCore.RouteAnalyzer et d'innombrables recherches et recherches sur Google, je n'ai pas trouvé de réponse définitive.

Ce qui suit fonctionne pour moi pour un contrôleur domestique typique et un contrôleur de zone:

public class RouteInfoController : Controller
{
    // for accessing conventional routes...
    private readonly IActionDescriptorCollectionProvider _actionDescriptorCollectionProvider;

    public RouteInfoController(
        IActionDescriptorCollectionProvider actionDescriptorCollectionProvider)
    {
        _actionDescriptorCollectionProvider = actionDescriptorCollectionProvider;
    }

    public IActionResult Index()
    {
        StringBuilder sb = new StringBuilder();

        foreach (ActionDescriptor ad in _actionDescriptorCollectionProvider.ActionDescriptors.Items)
        {
            var action = Url.Action(new UrlActionContext()
            {
                Action = ad.RouteValues["action"],
                Controller = ad.RouteValues["controller"],
                Values = ad.RouteValues
            });

            sb.AppendLine(action).AppendLine().AppendLine();
        }

        return Ok(sb.ToString());
    }

Cela produira ce qui suit dans ma solution simple:

/
/Home/Error
/RouteInfo
/RouteInfo/Links
/Area51/SecureArea

Ce qui précède a été fait en utilisant l'aperçu dotnetcore 3 mais je pense que cela devrait fonctionner avec dotnetcore 2.2. De plus, obtenir l'url de cette manière prendra en considération toutes les conventions qui ont été mises en place, y compris l'excellent slugify mis en évidence Blog de Scott Hanselman

4
Andez

Vous pouvez obtenir une HttpRouteCollection à partir de HttpActionContext via:

actionContext.RequestContext.Configuration.Routes

RequestContext

HttpConfiguration

HttpRouteCollection

- Après la mise à jour de la question -

ActionExecutingContext a une propriété RouteData qu'il hérite de ControllerContext, qui expose la propriété DataTokens (qui est un dictionnaire de valeurs de route). Ce n'est probablement pas la même collection avec laquelle vous avez l'habitude de travailler, mais elle donne accès à cette collection:

actionContext.RouteData.DataTokens

DataTokens

3
pwnyexpress

Ceci est utile pour le débogage uniquement:

var routes = System.Web.Http.GlobalConfiguration.Configuration.Routes;
var field = routes.GetType().GetField("_routeCollection", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
var collection = field.GetValue(routes) as System.Web.Routing.RouteCollection;
var routeList = collection
    .OfType<IEnumerable<System.Web.Routing.RouteBase>>()
    .SelectMany(c => c)
    .Cast<System.Web.Routing.Route>()
    .Concat(collection.OfType<System.Web.Routing.Route>())
    .Select(r => $"{r.Url} ({ r.GetType().Name})")
    .OrderBy(r => r)
    .ToArray();

routeList contiendra un tableau de chaînes de routes et de types.

0
N-ate