Customize MapHttpAttributeRoutes for Web Api Versioning

后端 未结 3 663
感动是毒
感动是毒 2021-02-10 16:52

I am implementing Web API versioning as in Web API Versioning. My controllers are in 2 separate namespaces, and I\'ve used a custom SelectController method to choose which versi

3条回答
  •  借酒劲吻你
    2021-02-10 17:29

    Here is a solution that will let you use the Web API 2 way of versioned routes (headers), in addition to query parameter support (i.e. use a header called 'api-version' or a querystring parameter named '?api-version=XXX'.

    The HTTP Route constraint does the work:

    /// 
    /// Add a route constraint to detect version header or by query string
    /// 
    public class RouteVersionHttpConstraint : IHttpRouteConstraint
    {
        public const string VersionHeaderName = "api-version";
        private const int DefaultVersion = 1;
        /// 
        /// Add a route constraint to detect version header or by query string
        /// 
        /// 
        public RouteVersionHttpConstraint(int allowedVersion)
        {
            AllowedVersion = allowedVersion;
        }
    
        public int AllowedVersion
        {
            get;
            private set;
        }
    
        /// 
        /// Perform the controller match
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary values, HttpRouteDirection routeDirection)
        {
            if (routeDirection == HttpRouteDirection.UriResolution)
            {
                int version = GetVersionHeaderOrQuery(request) ?? DefaultVersion;
                if (version == AllowedVersion)
                {
                    return true;
                }
            }
            return false;
        }
    
        /// 
        /// Check the request header, and the query string to determine if a version number has been provided
        /// 
        /// 
        /// 
        private int? GetVersionHeaderOrQuery(HttpRequestMessage request)
        {
            string versionAsString;
            IEnumerable headerValues;
            if (request.Headers.TryGetValues(VersionHeaderName, out headerValues) && headerValues.Count() == 1)
            {
                versionAsString = headerValues.First();
                int version;
                if (versionAsString != null && Int32.TryParse(versionAsString, out version))
                {
                    return version;
                }
            }
            else
            {
                var query = System.Web.HttpUtility.ParseQueryString(request.RequestUri.Query);
                string versionStr = query[VersionHeaderName];
                int version = 0;
                int.TryParse(versionStr, out version);
                if (version > 0)
                    return version;
            }
            return null;
        }
    }
    

    And the route factory:

    /// 
    /// Versioning support for the WebAPI controllers
    /// 
    public class RouteVersionAttribute : RouteFactoryAttribute
    {
        public int Version { get; private set; }
    
        public RouteVersionAttribute() : this(null, 1) 
        { 
        }
        /// 
        /// Specify a version for the WebAPI controller
        /// 
        /// 
        public RouteVersionAttribute(int version) : this(null, version)
        {
        }
    
        public RouteVersionAttribute(string template, int version)
            : base(template)
        {
            Version = version;
        }
    
        public override IDictionary Constraints
        {
            get
            {
                var constraints = new HttpRouteValueDictionary();
                constraints.Add("version", new RouteVersionHttpConstraint(Version));
                return constraints;
            }
        }
    
        public override IDictionary Defaults
        {
            get
            {
                var defaults = new HttpRouteValueDictionary();
                defaults.Add("version", 1);
                return defaults;
            }
        }
    
    }
    

    Usage:

    [RouteVersion("api/versiontest", 1)]
    public class Version1TestController : BaseApiController
    {
        // get: api/versiontest
        [HttpGet]
        public HttpResponseMessage get()
        {
            return Request.CreateResponse(HttpStatusCode.OK, new { Version = "API Version 1 selected" });
        }
    
    }
    
    [RouteVersion("api/versiontest", 2)]
    public class Version2TestController : ApiController
    {
        // get: api/versiontest
        [HttpGet]
        public HttpResponseMessage get()
        {
            return Request.CreateResponse(HttpStatusCode.OK, new { Version = "API Version 2 selected" });
        }
    
    }
    

提交回复
热议问题