3
votes

La gestion des versions de l'API Web ne fonctionne pas avec la version par défaut

J'ai créé une application API Web avec gestion des versions. Je vais utiliser le package Microsoft.AspNet.WebApi.Versioning pour ce faire.

Configuration Webapi:

    public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        ConfigureAuth(app);
        var configuration = new System.Web.Http.HttpConfiguration();
        var httpServer = new System.Web.Http.HttpServer(configuration);

        // reporting api versions will return the headers "api-supported-versions" and "api-deprecated-versions"
        configuration.AddApiVersioning(options =>
        {
            options.ReportApiVersions = true;
            options.AssumeDefaultVersionWhenUnspecified = true;
        });
        configuration.MapHttpAttributeRoutes();
        app.UseWebApi(httpServer);

    }
}

Ici, mon hypothèse est si Je n'ai pas réussi la version, par défaut elle sélectionnera la version 1.

Code du contrôleur:

[ApiVersion("1.0")]
[RoutePrefix("api/users")]
public class UserV1Controller : BaseController
{
    public UserV1Controller()
    {
    }

    [Route("all", Name = "UsersCollection")]
    public async Task<IHttpActionResult> GetAll()
    {
        var items = await UnitOfWork.Users.GetPaged(x => x.OrderBy(y => y.Id), 1, 20);
        //Add mapping to DTO 
        return Ok(items);
    }

}

Si je teste avec http: //localhost:10280/api/users/all?api-version=1.0 URL, cela fonctionne bien. Je vais implémenter cette fonctionnalité dans le projet existant.

Pour la compatibilité ascendante, j'ai essayé http: // localhost: 10280 / api / users / all URL. Cela me donne l'erreur suivante avec 500 comme code d'état.

{ "Message": "Une erreur s'est produite.",
"ExceptionMessage": "L'index ne peut pas être inférieur à 0 ou égal ou supérieur au nombre d'éléments de la collection. \ R \ n
Paramètre nom: index \ r \ nLa valeur réelle était 0. ",
"ExceptionType": "System.ArgumentOutOfRangeException",
"StackTrace": "sur
System.Web.Http.WebHost.Routing.HostedHttpRouteCollection.get_Item (Int32 index) \ r \ n à Microsoft.Web.Http.Dispatcher.ApiVersionControllerSelector.GetControllerName (HttpRequestMessage demande) \ r \ n à Microsoft.Web.Http.Dispatcher.ControllerSelectionContext. C__DisplayClass6_0. <. ctor> b__0 () \ r \ n à System.Lazy 1.CreateValue () \ r \ n à System.Lazy 1.LazyInitValue () \ r \ n à System.Lazy`1.get_Value () \ r \ n
à Microsoft.Web.Http.Dispatcher.ConventionRouteControllerSelector.SelectController (ControllerSelectionContext contexte) \ r \ n à Microsoft.Web.Http.Dispatcher.ApiVersionControllerSelector.SelectController (HttpRequestMessage demande) \ r \ n à System.Web.Http.Dispatcher.HttpControllerDispatcher.d__15.MoveNext () " }


Mise à jour 1:

Après des discussions et un peu d'aide, je peux confirmer que cette version par défaut fonctionne avec le routage conventionnel.

Le problème reproduit lors de l'utilisation du routage d'attributs. Veuillez vérifier mon code mis à jour.

  1. Je n'ai pas de routage API par défaut dans le fichier WebAPIConfig.
  2. Je mets à jour le préfixe d'itinéraire et l'itinéraire dans le contrôleur

Le problème est maintenant reproduit.

Vous pouvez également reproduire le problème en combinant conventionnel et attribut.

Mise à jour 2:

Maintenant, j'ai remarqué que le problème réside dans la configuration. Si j'ajoute directement les configurations de routage dans la classe de démarrage Owin, cela fonctionne correctement.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        config.AddApiVersioning(o => {
            o.AssumeDefaultVersionWhenUnspecified = true;
        });
        // Web API routes
        config.MapHttpAttributeRoutes();

    }
}

Cela crée une nouvelle HttpConfiugration autre que d'utiliser notre classe WebAPIConfig existante. Donc, je ne sais pas que cela peut avoir un impact sur d'autres fonctionnalités

Donc, si je configure Owin pour utiliser webaPI au lieu de GlobalConfiguration.Configure (WebApiConfig.Register) strong > dans Global.asax, cela fonctionne très bien.


8 commentaires

C'est la configuration de la route pour mvc. Nous avons besoin de la configuration d'itinéraire pour votre webapi. il se trouve probablement dans le fichier WebApiConfig.cs s'il n'est pas modifié


D'accord. Alors seulement j'ai confondu. En fait, j'ai supprimé ces lignes de route par défaut car je les ai configurées uniquement pour le routage d'attributs. J'ai mis à jour maintenant. Désolé si je vous ai confondu.


N / a. C'est bon. Votre configuration d'itinéraire semble correcte. Je peux maintenant reproduire votre erreur en toute sécurité. Maintenant, trouvons juste une solution pour cela


OK merci. J'ai essayé toutes les manières spécifiées. Si rien ne semble, allez-y en étendant ControllerSelector


Existe-t-il un contrôleur utilisant la version 2, qui a le même préfixe de routage? par exemple. [RoutePrefix ("api / users")] ? car cela provoque votre erreur dans mon projet local. Si je supprime le deuxième contrôleur ou son préfixe de routage, l'erreur disparaît. C'est tout à fait naturel, car il ne peut pas y avoir 2 routes identiques pour 2 contrôleurs différents.


Ok j'ai compris. Mais ici, je n'ai créé qu'un seul contrôleur comme échantillon.


continuons cette discussion dans le chat .


J'ai reproduit le comportement. En utilisant le routage conventionnel, cela fonctionne très bien. Si j'ai utilisé le routage d'attribut, reproduit le problème avec un seul contrôleur


3 Réponses :


3
votes

Si vous ne spécifiez pas de version, elle est considérée comme non versionnée. Dans ce cas, vous devez définir la propriété AssumeDefaultVersionWhenUnspecified , qui, sauf indication contraire, suppose une version par défaut de "1.0" , si aucune n'est spécifiée:

config.AddApiVersioning(o => {
    o.AssumeDefaultVersionWhenUnspecified = true;
});


5 commentaires

non. Je peux accéder si je fournis explicitement la version de l'API. J'ai également essayé le même échantillon spécifié dans la documentation mais la même erreur. Une autre configuration?


ma faute, veuillez modifier votre question avec votre configuration d'itinéraire. Je peux recréer votre erreur en ajoutant le décorateur [Route] sur une méthode d'action.


Votre configuration d'itinéraire est toujours absente de votre question


J'ai ajouté le code du fichier route.config. Comme il ne s'agit que d'API, je pense que nous ne nous soucions pas de route.config. correct? Je me soucie seulement du fichier webApiConfig


Maintenant, j'ai mis à jour avec mes dernières découvertes. Mais je ne sais pas pourquoi c'est arrivé comme ça



0
votes

Vous pouvez essayer de définir le numéro de version par défaut et configurer le middleware pour l'utiliser lorsque le numéro de version n'est pas spécifié.

Référence: Le blog de Scott sur le routage

services.AddApiVersioning(
    o =>
    {
        o.AssumeDefaultVersionWhenUnspecified = true );
        o.DefaultApiVersion = new ApiVersion("1.0");
    } );


2 commentaires

Cela ne fonctionnera pas, car ses itinéraires n'utilisent pas les DateTimes comme attributs de version. Une surcharge appropriée aurait été nouvelle ApiVersion (1,0)


Merci. mais ce n'est pas le problème. Je pense que cela est lié au routage. Ce problème se reproduit lorsque j'utilise uniquement les attributs RoutePrefix et Route. Je veux dire le routage d'attributs



2
votes

Il s'agit d'un bogue confirmé qui se produit uniquement lors de l'hébergement sur une implémentation IIS vanilla (par exemple non-OWIN). Malgré le HttpRouteCollection ayant un indexeur, le HostedHttpRouteCollection défini par System.Web ne le prend pas en charge. Au lieu de lancer NotSupportedException , une ArgumentOutOfRangeException générique est lancée.

Pour plus de détails, voir: https://github.com/Microsoft/ aspnet-api-versioning / issues / 428 .

Le correctif est disponible et est désormais disponible dans la version du package 3.0.1 .


1 commentaires

Merci. Fonctionnement comme prévu dans la version 3.0.1