Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <pre>
- namespace WebAPiVersioningHybrid.Routing
- {
- // This version for custome attribute routing
- public class NamespaceHttpControllerSelector : IHttpControllerSelector
- {
- private readonly HttpConfiguration _configuration;
- private readonly Lazy<Dictionary<string, HttpControllerDescriptor>> _controllers;
- public NamespaceHttpControllerSelector(HttpConfiguration config)
- {
- _configuration = config;
- _controllers = new Lazy<Dictionary<string, HttpControllerDescriptor>>(InitializeControllerDictionary);
- }
- public HttpControllerDescriptor SelectController(HttpRequestMessage request)
- {
- var routeData = request.GetRouteData();
- if (routeData == null)
- {
- throw new HttpResponseException(HttpStatusCode.NotFound);
- }
- var controllerName = GetControllerName(routeData);
- if (controllerName == null)
- {
- throw new HttpResponseException(HttpStatusCode.NotFound);
- }
- var namespaceName = GetVersion(routeData);
- if (namespaceName == null)
- {
- throw new HttpResponseException(HttpStatusCode.NotFound);
- }
- var controllerKey = String.Format(CultureInfo.InvariantCulture, "{0}.{1}",
- namespaceName, controllerName);
- HttpControllerDescriptor controllerDescriptor;
- if (_controllers.Value.TryGetValue(controllerKey, out controllerDescriptor))
- {
- return controllerDescriptor;
- }
- throw new HttpResponseException(HttpStatusCode.NotFound);
- }
- public IDictionary<string, HttpControllerDescriptor> GetControllerMapping()
- {
- return _controllers.Value;
- }
- private Dictionary<string, HttpControllerDescriptor> InitializeControllerDictionary()
- {
- var dictionary = new Dictionary<string, HttpControllerDescriptor>(StringComparer.OrdinalIgnoreCase);
- var assembliesResolver = _configuration.Services.GetAssembliesResolver();
- var controllersResolver = _configuration.Services.GetHttpControllerTypeResolver();
- var controllerTypes = controllersResolver.GetControllerTypes(assembliesResolver);
- foreach (var controllerType in controllerTypes)
- {
- var segments = controllerType.Namespace.Split(Type.Delimiter);
- var controllerName = controllerType.Name.Remove(controllerType.Name.Length - DefaultHttpControllerSelector.ControllerSuffix.Length);
- var controllerKey = String.Format(CultureInfo.InvariantCulture, "{0}.{1}",
- segments[segments.Length - 1], controllerName);
- if (!dictionary.Keys.Contains(controllerKey))
- {
- dictionary[controllerKey] = new HttpControllerDescriptor(_configuration,
- controllerType.Name,
- controllerType);
- }
- }
- return dictionary;
- }
- private static T GetRouteVariable<T>(IHttpRouteData routeData, IEnumerable<string> names)
- {
- object result;
- foreach (var name in names)
- {
- if (routeData.Values.TryGetValue(name, out result))
- {
- return (T)result;
- }
- }
- return default(T);
- }
- private string GetControllerName(IHttpRouteData routeData)
- {
- var subroute = routeData.GetSubRoutes().FirstOrDefault();
- if (subroute == null) return null;
- //var dataTokenValue = subroute.Route.DataTokens.Last().Value;
- var dataTokenValue = subroute.Route.DataTokens.First().Value;
- if (dataTokenValue == null) return null;
- var controllername = ((HttpActionDescriptor[])dataTokenValue).First().ControllerDescriptor.ControllerName.Replace("Controller", string.Empty);
- return controllername;
- }
- private string GetVersion(IHttpRouteData routeData)
- {
- var subRouteData = routeData.GetSubRoutes().FirstOrDefault();
- if (subRouteData == null) return null;
- var routevariable = GetRouteVariable<string>(subRouteData, versionnumber);
- return routevariable;
- }
- private List<string> versionnumber = new List<string>()
- {
- "apiVersion1" ,
- "apiVersion2"
- };
- }
- }
- </pre>
- Each control are decorated by custom route attribute , that defines the version of current control and helps the NamespaceHttpControllerSelector.cs to return the correct descriptor
- <pre>
- <code>
- namespace WebAPiVersioningHybrid.Routing
- {
- public class ApiVersion1Constraint : IHttpRouteConstraint
- {
- public ApiVersion1Constraint(string allowedVersion)
- {
- AllowedVersion = allowedVersion.ToLowerInvariant();
- }
- public string AllowedVersion { get; private set; }
- //Matching the version from requested route
- public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName,
- IDictionary<string, object> values, HttpRouteDirection routeDirection)
- {
- object value;
- if (values.TryGetValue(parameterName, out value) && value != null)
- {
- return AllowedVersion.Equals(value.ToString().ToLowerInvariant());
- }
- return false;
- }
- }
- }
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net.Http;
- using System.Web;
- using System.Web.Http.Routing;
- namespace WebAPiVersioningHybrid.Routing
- {
- public class ApiVersion2Constraint : IHttpRouteConstraint
- {
- public ApiVersion2Constraint(string allowedVersion)
- {
- AllowedVersion2 = allowedVersion.ToLowerInvariant();
- }
- public string AllowedVersion2 { get; private set; }
- //Matching the version from requested route
- public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName,
- IDictionary<string, object> values, HttpRouteDirection routeDirection)
- {
- object value;
- if (values.TryGetValue(parameterName, out value) && value != null)
- {
- return AllowedVersion2.Equals(value.ToString().ToLowerInvariant());
- }
- return false;
- }
- }
- }
- </code>
- </pre>
- The Web API that used custom namespace versioning are working fine that are listed below
- <pre>
- <code>
- using WebAPiVersioningHybrid.Models;
- namespace WebAPiVersioningHybrid.Controllers.V1
- {
- [RoutePrefix("api/{apiVersion1:apiVersion1Constraint(v1)}/Teacher")]
- public class TeacherController : ApiController
- {
- // http://localhost/WebAPiVersioningHybrid/api/V1/Teacher/GetTeacher
- [Route("GetTeacher")]
- public HttpResponseMessage GetValue()
- {
- return Request.CreateResponse(HttpStatusCode.Accepted, new Teacher(1, "Dale", "Carn", 40));
- }
- }
- }
- using WebAPiVersioningHybrid.Models;
- namespace WebAPiVersioningHybrid.Controllers.V2
- {
- [RoutePrefix("api/{apiVersion2:apiVersion2Constraint(v2)}/Teacher")]
- public class TeacherController : ApiController
- {
- [Route("GetTeacher")]
- public HttpResponseMessage GetValue()
- {
- return Request.CreateResponse(HttpStatusCode.Accepted,
- new TeacherDetails(1,"Dan","Carn",40,"XY@gmail.com","009827788","XYZ","20"));
- }
- }
- }
- </code>
- </pre>
- The old Web API thaht are used conventional , that is not working with the conventional routing any more and can not be modified for namespace versioning web api for backward purposes
- <pre>
- <code>
- using System.Net;
- using System.Net.Http;
- using System.Web.Http;
- using WebAPiVersioningHybrid.Models;
- namespace WebAPiVersioningHybrid.Controllers
- {
- // http://localhost/WebAPiVersioningHybrid/api/Person
- public class PersonController : ApiController
- {
- public HttpResponseMessage GetPerson()
- {
- return Request.CreateResponse(HttpStatusCode.Accepted,new Person("782901865","Male"));
- }
- }
- }
- </code>
- </pre>
- The follwoing classes at Model folder
- <pre>
- <code>
- namespace WebAPiVersioningHybrid.Models
- {
- public class Person
- {
- public string SSN { get; set; }
- public string Gender { get; set; }
- public Person(string SSN,string Gender)
- {
- this.Gender =Gender;
- this.SSN = SSN;
- }
- }
- }
- namespace WebAPiVersioningHybrid.Models
- {
- public class Teacher
- {
- public int Id { get; set; }
- public string FirstName { get; set; }
- public string LastName { get; set; }
- public int Age { get; set; }
- public Teacher(int Id,string FirstName,string LastName,int Age)
- {
- this.Id = Id;
- this.FirstName = FirstName;
- this.LastName = LastName;
- this.Age = Age;
- }
- }
- }
- namespace WebAPiVersioningHybrid.Models
- {
- public class TeacherDetails: Teacher
- {
- public string email { get; set; }
- public string MobileNum { get; set; }
- public string Street { get; set; }
- public string BuildingNum { get; set; }
- public TeacherDetails(int Id,string FirstName,string LastName,int Age,
- string email,string MobileNum,string Street,string BuildingNum)
- :base(Id,FirstName,LastName,Age)
- {
- this.email = email;
- this.MobileNum = MobileNum;
- this.Street = Street;
- this.BuildingNum = BuildingNum;
- }
- }
- }
- </pre>
- <pre>
- <code>
- namespace WebAPiVersioningHybrid
- {
- public static class WebApiConfig
- {
- public static void Register(HttpConfiguration config)
- {
- // Web API configuration and services
- // Web API routes
- var constraintsResolver = new DefaultInlineConstraintResolver();
- constraintsResolver.ConstraintMap.Add("apiVersion1Constraint", typeof(ApiVersion1Constraint));
- constraintsResolver.ConstraintMap.Add("apiVersion2Constraint", typeof(ApiVersion2Constraint));
- config.MapHttpAttributeRoutes(constraintsResolver);
- // this work in conventional routing
- // config.Services.Replace(typeof(IHttpControllerSelector), new NamespaceHttpControllerSelector(config));
- config.Services.Replace(typeof(IHttpControllerSelector), new NamespaceHttpControllerSelector(config));
- config.Routes.MapHttpRoute(
- name: "DefaultApi",
- routeTemplate: "api/{controller}/{id}",
- defaults: new { id = RouteParameter.Optional }
- );
- }
- }
- }
- <code>
- </pre>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement