1
votes

Gestion des versions Web-Api avec l'URL c #

Je me bats depuis des jours maintenant, j'essaie de faire passer mon API à la version avec le suffixe URL. par exemple http: // localhost / api / v1 / sites & http: // localhost / api / v2 / sites .

J'étais assez proche je suppose, mais du coup, j'ai tout gâché .. p>

Merci beaucoup de m'avoir aidé.

Maintenant, je reçois: "System.invalidOperationException: 'Le type de contrainte' ApiVersionRouteConstraint 'qui est mappé à la clé de contrainte' apiVersion 'doit implémenter IhttpRouteConstraint interface.' sur Global.asax.cs

Global.asax.cs

using FirebirdSql.Data.FirebirdClient;
using System;
using System.Web.Http;
using System.Configuration;
using System.Collections;
using Microsoft.Web.Http;

        namespace HIDDEN.Controllers.V1
        {
        [ApiVersion("1.0")]
        [Route("api/v{version:apiVersion}/[controller]")]

        public class SitesController : ApiController
        {
              //code for V1
        }

        namespace HIDDEN.Controllers.V2
        {
        [ApiVersion("2.0")]
        [Route("api/v{version:apiVersion}/[controller]")]

        public class SitesController : ApiController
        {
              //code for V2
        }
    }

WebApiConfig.cs

using System.Web.Mvc;
using System.Web.Routing;


namespace HIDDEN
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
        }
    }
}

using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.Owin.Security.OAuth;
using System.Web.Http;
using System.Web.Http.Routing;

namespace HIDDEN
{
    public static class WebApiConfig
        {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services  
            // Configure Web API to use only bearer token authentication.  
            config.SuppressDefaultHostAuthentication();
            config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

            var contraintResolver = new DefaultInlineConstraintResolver()
            {
                ConstraintMap =
                {
                    ["apiVersion"] = typeof(ApiVersionRouteConstraint)
                }
            };

            // Web API routes  
            config.MapHttpAttributeRoutes(contraintResolver);
            config.AddApiVersioning(o =>
            {
                o.AssumeDefaultVersionWhenUnspecified = true;
                //o.DefaultApiVersion = new ApiVersion(1, 0);
            });

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                //routeTemplate: "api/v{version:apiVersion}/{controller}/{id}",
                routeTemplate: "api/v{version:apiVersion}/{controller}",
                //routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            // WebAPI when dealing with JSON & JavaScript!  
            // Setup json serialization to serialize classes to camel (std. Json format)  
            var formatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
            formatter.SerializerSettings.ContractResolver = new     Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();

            // Adding JSON type web api formatting.  
            config.Formatters.Clear();
            config.Formatters.Add(formatter);

        }
    }
}   

SitesController p>

using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace HIDDEN
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }
}


6 commentaires

vous utilisez ConfigureAuth?


Oui pour l'authentification oAuth2


Quel est l'avantage de configurer des attributs de version d'API dans le pipeline et de spécifier ApiVersion sur chaque contrôleur (qui utilise le routage d'attributs), lorsque vous pouvez faire [Route ("api / v2 / [ controller] ")] quand même? Ajoute-t-il d'autres fonctionnalités ailleurs?


Salut Craig, je pourrais donc laisser [Route ("api / v {version: apiVersion} / [controller]")] hors du contrôleur?


@CraigH - oui, il y a des fonctionnalités supplémentaires. Le contrôle de version d'API fournit un cadre complet pour les stratégies de contrôle de version, la découverte, la documentation, etc. L'utilisation de la chaîne littérale v2 sera inconnue du contrôle de version de l'API car elle n'autorise pas, n'utilise ni n'analyse les chaînes magiques . Le paramètre de route {version: apiVersion} définit le nom version , qui utilise ApiVersionRouteConstraint . Voici comment la gestion des versions d'API sait d'où extraire la valeur.


@Gregory - non, la gestion des versions d'API ne fonctionnera pas si vous supprimez le paramètre de route avec la contrainte de route apiVersion . C'est ainsi que la gestion des versions d'API extrait le numéro de version de votre modèle. Sans cela, v2 sera un segment de chaîne constant et le contrôle de version d'API pensera qu'aucune version n'a été spécifiée car il ne saura pas comment le lire à partir d'une requête.


4 Réponses :


4
votes

Assurez-vous d'utiliser le bon ApiVersionRouteConstraint car il semble y avoir un conflit entre Microsoft.AspNetCore.Mvc.Routing et Microsoft.Web.Http. Routage

Si vous utilisez cette bibliothèque de versionnage Microsoft.AspNet .WebApi.Versioning vous devez utiliser Microsoft.Web.Http.Routing

config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/v{apiVersion}/{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional },
                constraints: new { apiVersion = new ApiVersionRouteConstraint() }
);

En outre, vous pouvez également ajouter apiVersion contraintes à vos itinéraires comme ci-dessous

using Microsoft.Web.Http.Routing;


10 commentaires

Merci Hasta, corrigé comme vous l'avez suggéré. Mais toujours en train de recevoir 'System.invalidOperationException'.


Pourriez-vous confirmer que vous utilisez x.x.WebApi.Versioning si oui, avez-vous using Microsoft.Web.Http.Routing; dans votre WebApiConfig?


Salut Hasta, Consultez le code ci-dessus, comme vous pouvez le voir `` en utilisant System.Web.Http.Routing '' lorsque vous essayez d'utiliser Microsoft.Web.Http.Routing je reçois une nouvelle erreur: `` ApiVersionRouteConstraint '' est une référence ambiguë entre «Microsoft.Web.Http.Routing.ApiVersionRouteConstraint» et «Microsoft.AspNetCore.Mvc.routing.ApiVersionRouteConstraint.


Je pense que c'est votre problème. Utilisez plutôt Microsoft.Web.Http.Routing.


Lorsque vous essayez «d'utiliser Microsoft.Web.Http.Routing», alors DefaultInlineConstraintResolver ne fonctionne plus «Référence d'assembly manquante»


Vous devez installer ce package à partir de Nuget nuget.org/packages/ Microsoft.AspNet.WebApi.Versioning / 3.0.4


Vérifiez vos références, vous devriez avoir System.Web.Http .


Ce package est installé, vient de faire une réinstallation et System.Web.Http est référencé


Et avez-vous utilisant System.Web.Http.Routing ? DefaultInlineConstraintResolve vit à l'intérieur de Espace de noms System.Web.Http.Routing


Il convient également de mentionner que le mélange d'attributs et de routage basé sur des conventions doit être évité. Oui, c'est pris en charge, mais dans la pratique, cela peut devenir très déroutant avec le temps. Je recommande de choisir l'un ou l'autre, puis de s'y tenir.



1
votes

Je pense que vous n'avez pas bien configuré la gestion des versions de l'API Web ASP.Net

http://www.intstrings.com/ramivemula/articles/asp-net-web-api-versioning/

Vous pouvez consulter ce post, vous pourriez avoir une propriété sans la configuration correcte telle que:

ReportApiVersions = true;


2 commentaires

Salut Ahmed, cette approche fonctionnera-t-elle? Depuis 'Api-version' ne sera pas fourni dans les paramètres de la demande. (uniquement dans l'URL)


@Gregory - oui, cela fonctionnera. La gestion des versions de l'API ne se soucie pas de l'endroit où la version de l'API est demandée lors du rapport des versions de l'API. Toutes les informations de version de l'API sont découvertes et mises en cache dès le départ. Si vous y réfléchissez, il doit le faire afin de prendre une décision à partir des actions du candidat. La mise en correspondance d'un candidat nécessite la lecture d'une ou plusieurs sources de demande contenant la version de l'API entrante. Une fois qu'une correspondance est établie, tous les autres candidats sont déjà connus et leurs versions d'API peuvent être signalées si elles sont configurées.



0
votes

Vous pouvez utiliser swagger pour une meilleure documentation de l'API également pour la gestion des versions de l'API.


0 commentaires

0
votes

Correction du problème, le plus gros problème était que les différentes versions du contrôleur se trouvaient dans un espace de noms différent.

Cela a fait l'affaire:

 namespace HIDDEN.Controllers.Sites
 {
     [Authorize]
     [ApiVersion("1.0")]
     [Route("v{version:apiVersion}/sites")]   
     public class valuesV1Controller : ApiController
     {
         // GET: api/values
         public IEnumerable<string> Get()
         {
             return new string[] { "value1", "value2" };
         }
     }

     [Authorize]
     [ApiVersion("2.0")]
     [ApiVersion("2.1")]
     [Route("v{version:apiVersion}/sites")]
     public class valuesV2Controller : ApiController
     {
         // GET: api/values
         public IEnumerable<string> Get()
         {
             return new string[] { "value3", "value4" };
         }
     }
 }


2 commentaires

Bien que cela puisse être la réponse acceptée, j'ajouterai que les espaces de noms ne sont pas un problème. Les contrôleurs peuvent avoir le même nom de type dans différents espaces de noms. Exemple de Version By Namespace dans l'API Le dépôt de version montre une façon de le configurer.


Une autre chose à mentionner est que la question d'origine utilise le jeton [controller] , mais je pense que cela n'est pris en charge que dans les modèles de route ASP.NET Core. Cette question et ce fil de discussion concernent l'API Web ASP.NET. Je répète également que le mélange des styles de routage (basés sur des conventions ou basés sur des attributs) peut rendre le dépannage difficile. Je recommande fortement de choisir une méthode ou une autre. Il existe des cas extrêmes où la gestion des versions d'API ne fonctionnera pas correctement dans l'API Web si vous mélangez les deux.