Ambiguous Controller Names with Routing attributes: controllers with same name and different namespace for versioning

前端 未结 3 1858
迷失自我
迷失自我 2020-12-15 06:39

I am trying to add API versioning and my plan is to create a controller for each version in different namespace. My project structure looks like this (note: no separate area

3条回答
  •  暗喜
    暗喜 (楼主)
    2020-12-15 07:14

    I know this was answered a while a go and has already been accepted by the original poster. However if you are like me and require the use of attribute routing and have tried the suggested answer you will know that it wont quite work.

    When I tried this I found out that it was actually missing the routing information that should have been generated by calling the extension method MapHttpAttributeRoutes of theHttpConfiguration class:

    config.MapHttpAttributeRoutes();
    

    This meant that the method SelectController of the replacement IHttpControllerSelector implementation never actually gets called and is why the request produces a http 404 response.

    The issue is caused by an internal class called HttpControllerTypeCache which is an internal class in the System.Web.Http assembly under the System.Web.Http.Dispatcher namespace. The code in question is the following:

        private Dictionary> InitializeCache()
        {
          return this._configuration.Services.GetHttpControllerTypeResolver().GetControllerTypes(this._configuration.Services.GetAssembliesResolver()).GroupBy((Func) (t => t.Name.Substring(0, t.Name.Length - DefaultHttpControllerSelector.ControllerSuffix.Length)), (IEqualityComparer) StringComparer.OrdinalIgnoreCase).ToDictionary, string, ILookup>((Func, string>) (g => g.Key), (Func, ILookup>) (g => g.ToLookup((Func) (t => t.Namespace ?? string.Empty), (IEqualityComparer) StringComparer.OrdinalIgnoreCase)), (IEqualityComparer) StringComparer.OrdinalIgnoreCase);
        }
    

    You will see in this code that it is grouping by the type name without the namespace. The DefaultHttpControllerSelector class uses this functionality when it builds up an internal cache of HttpControllerDescriptor for each controller. When using the MapHttpAttributeRoutes method it use another internal class called AttributeRoutingMapper which is part of the System.Web.Http.Routing namespace. This class uses the method GetControllerMapping of the IHttpControllerSelector in order to configure the routes.

    So if you are going to write a custom IHttpControllerSelector then you need to overload the GetControllerMapping method for it to work. The reason I mention this is that none of the implementations I have seen on the internet does this.

提交回复
热议问题