2

我试图api versioning使用header但在different folder structure像下面。发现多个类型与控制器匹配

Controller folder有内部的CustomerController.cs

CustomerController.cs

Controller folderV2子文件夹内V1子文件夹时,上面使用URL我的用户API版本工作正常。

我的问题是,当我尝试这种方法与header它给我下面的错误:

{ "Message": "An error has occurred.", "ExceptionMessage": "Multiple types were found that match the controller named 'customer'. This can happen if the route that services this request ('api/{controller}/{id}') found multiple controllers defined with the same name but differing namespaces, which is not supported.\r\n\r\nThe request for 'customer' has found the following matching controllers:\r\nApiVersion.Controllers.V1.CustomerController\r\nApiVersion.Controllers.V2.CustomerController", "ExceptionType": "System.InvalidOperationException", "StackTrace": " at System.Web.Http.Dispatcher.DefaultHttpControllerSelector.SelectController(HttpRequestMessage request)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()" }

WebApiConfig.cs

public static void Register(HttpConfiguration config) 
     { 
      config.MapHttpAttributeRoutes(); 
      config.Routes.MapHttpRoute(
       name: "DefaultApi", 
       routeTemplate: "api/{controller}/{id}", 
       defaults: new { id = RouteParameter.Optional } 
      ); 
     } 

CustomeControllerSelector.cs

 public override HttpControllerDescriptor SelectController(HttpRequestMessage request) 
     { 
      var controllers = GetControllerMapping(); 
      var routeData = request.GetRouteData(); 
      var controllerName = routeData.Values["controller"].ToString(); 
      //HttpControllerDescriptor controllerDescriptor; 

      var version = GetVersionFromAcceptHeaderVersion(request); 
      var controllerKey = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", 
         version, controllerName); 


      //if (controllers.TryGetValue(controllerName, out controllerDescriptor)) 
      // { 

      if (!string.IsNullOrEmpty(version)) 
      { 
       HttpControllerDescriptor versionedControllerDescriptor; 
       if (controllers.TryGetValue(controllerKey, out versionedControllerDescriptor)) 
       { 
        return versionedControllerDescriptor; 
       } 
      } 
      return null; 
     } 

      private string GetVersionFromAcceptHeaderVersion(HttpRequestMessage request) 
     { 
      var acceptHeader = request.Headers.Accept; 
      foreach (var mime in acceptHeader) 
      { 
       if (mime.MediaType == "application/json" || mime.MediaType == "text/html") 
       { 
        var version = mime.Parameters 
            .Where(v => v.Name.Equals("version", StringComparison.OrdinalIgnoreCase)) 
            .FirstOrDefault(); 
        if (version != null) 
        { 
         return version.Value; 
        } 
        return string.Empty; 
       } 
      } 
      return string.Empty; 
     } 

回答

1

我试着以下。作品以现在 -

public class CustomControllerSelector : DefaultHttpControllerSelector 
{ 
    //const string partName = "Webapi.Controllers"; 
    private readonly HttpConfiguration _config; 

    public CustomControllerSelector(HttpConfiguration config) 
     : base(config) 
    { 
     _config = config; 
    } 

    public override System.Web.Http.Controllers.HttpControllerDescriptor SelectController(HttpRequestMessage request) 
    { 
     var _route = request.GetRouteData(); 

     var controllerName = base.GetControllerName(request); 

     var type = _config.Services.GetAssembliesResolver(); 
     var controlles = _config.Services.GetHttpControllerTypeResolver().GetControllerTypes(type); 

     object name; 
     _route.Values.TryGetValue("route", out name); 

     //No more hard coding 
     var partName = controllers.FirstOrDefault().Namespace; 
     var st = name as string; 
     if (st != null) 
     { 
      var conType = controlles.FirstOrDefault(a => a.Namespace == string.Format("{0}.{1}", partName, st)); 
         if (conType != null) 
          return new System.Web.Http.Controllers.HttpControllerDescriptor(_config, controllerName, conType); 
     } 

     return base.SelectController(request); 
    } 
} 

在WebApiConfig.cs -

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

测试路线 -

http://localhost:60957/api/Another/Route/a 
http://localhost:60957/api/Another/Route2/aaaaa 
+0

没有我的电话是一样通过'http://本地主机:58892/API /客户'和在头'接受:应用程序/ JSON;版本= 1' 你做的是静态:(检查我的类'CustomeControllerSelector.cs ' – Neo

+0

这是一个有效的'接受'头? –

+0

是的,当Controller在控制器文件夹'CustomerV1Controller.cs'和'CustomerV2Controller.cs'中时工作正常,代码为 'var versionedControllerName = string.Concat(controllerName,“V”,version); HttpControllerDescriptor versionedControllerDescriptor; (controllers.TryGetValue(versionedControllerName,out versionedControllerDescriptor)) { return versionedControllerDescriptor; }' – Neo

相关问题