title: Asp.net WebForm Web API version handling using namespace and persist old API
body: <p>I have a asp.net WebForm project that contain Web Api v2. I didn't consider api versioning and add my whole api with simple route below:</p>
  
  <pre><code>RouteTable.Routes.MapHttpRoute(
  name: "DefaultApi",
  routeTemplate: "api/{controller}"
  );
  </code></pre>
  
  <p>But, now, I need to create versioning because I have lots of change and don't want to disappoint my older client which use old api. So I create a new folder called APIv2 and create my controller there (which has the same name as the old api). The problem is how could I route something like this :</p>
  
  <pre><code>MyWebsite/API/Item =&gt; For ItemController OF OLD API
  MyWebsite/APIv2/Item =&gt; For ItemController Of New API (Version 2)
  </code></pre>
  
  <p>I've read lots of post but none of them work for me ! Also I create NamespaceHttpControllerSelector, But it doesn't work too.</p>
  
  <p>please give me some example of how to handle this.</p>
  
  <p>P.S : when I create simple routing such as the old one for new api, it says duplicate controller found ! (Although I am using different namespace)</p>
  
  <p>Edit (Add My Complete Code) :</p>
  
  <pre><code>GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector), new NamespaceHttpControllerSelector(GlobalConfiguration.Configuration));
  
          RouteTable.Routes.MapHttpRoute(
          name: "VersionedApi",
          routeTemplate: "api/v2/{controller}");
  
          RouteTable.Routes.MapHttpRoute(
          name: "DefaultApi",
          routeTemplate: "api/{controller}");
  </code></pre>
  
  <p>And the NamespaceHttpControllerSelector:</p>
  
  <pre><code>public class NamespaceHttpControllerSelector : DefaultHttpControllerSelector
  {
      private const string ControllerKey = "controller";
      private readonly HttpConfiguration _configuration;
      private readonly Lazy&lt;IEnumerable&lt;Type&gt;&gt; _duplicateControllerTypes;
  
      public NamespaceHttpControllerSelector(HttpConfiguration configuration) : base(configuration)
      {
          _configuration = configuration;
          _duplicateControllerTypes = new Lazy&lt;IEnumerable&lt;Type&gt;&gt;(GetDuplicateControllerTypes);
      }
  
      public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
      {
          var routeData = request.GetRouteData();
          if (routeData == null || routeData.Route == null || routeData.Route.DataTokens == null || routeData.Route.DataTokens["Namespaces"] == null) 
              return base.SelectController(request);
  
          // Look up controller in route data
          object controllerName;
          routeData.Values.TryGetValue(ControllerKey, out controllerName);
          var controllerNameAsString = controllerName as string;
          if (controllerNameAsString == null) 
              return base.SelectController(request);
  
          //get the currently cached default controllers - this will not contain duplicate controllers found so if
          // this controller is found in the underlying cache we don't need to do anything
          var map = base.GetControllerMapping();
          if (map.ContainsKey(controllerNameAsString)) 
              return base.SelectController(request);
  
          //the cache does not contain this controller because it's most likely a duplicate, 
          // so we need to sort this out ourselves and we can only do that if the namespace token
          // is formatted correctly.
          var namespaces = routeData.Route.DataTokens["Namespaces"] as IEnumerable&lt;string&gt;;
          if (namespaces == null)
              return base.SelectController(request);
  
          //see if this is in our cache
          var found = _duplicateControllerTypes.Value
              .Where(x =&gt; string.Equals(x.Name, controllerNameAsString + ControllerSuffix, StringComparison.OrdinalIgnoreCase))
              .FirstOrDefault(x =&gt; namespaces.Contains(x.Namespace));
  
          if (found == null)
              return base.SelectController(request);
  
          return new HttpControllerDescriptor(_configuration, controllerNameAsString, found);
      }
  
      private IEnumerable&lt;Type&gt; GetDuplicateControllerTypes()
      {
          var assembliesResolver = _configuration.Services.GetAssembliesResolver();
          var controllersResolver = _configuration.Services.GetHttpControllerTypeResolver();
          var controllerTypes = controllersResolver.GetControllerTypes(assembliesResolver);
  
          //we have all controller types, so just store the ones with duplicate class names - we don't
          // want to cache too much and the underlying selector caches everything else
  
          var duplicates = controllerTypes.GroupBy(x =&gt; x.Name)
              .Where(x =&gt; x.Count() &gt; 1)
              .SelectMany(x =&gt; x)
              .ToArray();
  
          return duplicates;
      }
  
  }
  </code></pre>