多种类型的发现控制器匹配 [英] Multiple types were found that match the controller
问题描述
我试图 API版本
使用头
但不同的文件夹结构
象下面这样。
在控制器文件夹
有 V1
里面的子文件 CustomerController.cs
和
在控制器文件夹
有 V2
里面的子文件 CustomerController.cs
网址
正常工作
我的问题是,当我试着使用头
这是给我下面的错误这种方式:
{消息:发生错误,ExceptionMessage:
多种类型的发现命名为客户控制器匹配。
如果路由服务这个请求会发生这种情况
(API / {控制器} / {ID}')发现定义多个控制器
同名但不同的命名空间,这是不支持的。\\ r \\ n \\ r \\ n此
请求客户发现下列匹配
controllers:\\r\
ApiVersion.Controllers.V1.CustomerController\\r\
ApiVersion.Controllers.V2.CustomerController\", ExceptionType:System.InvalidOperationException,堆栈跟踪:
在
System.Web.Http.Dispatcher.DefaultHttpControllerSelector.SelectController(HTT prequestMessage
申请个)\\ r \\ n在
System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()
}
块引用>WebApiConfig.cs
公共静态无效的注册(HttpConfiguration配置)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
名称:DefaultApi
routeTemplate:API / {}控制器/(编号),
默认:新{ID = RouteParameter.Optional}
);
}CustomeControllerSelector.cs
公众覆盖HttpControllerDescriptor SelectController(HTT prequestMessage要求)
{
变种控制器= GetControllerMapping();
变种的RouteData = request.GetRouteData();
。VAR controllerName = routeData.Values [控制器]的ToString();
// HttpControllerDescriptor controllerDescriptor; VAR的版本= GetVersionFromAcceptHeaderVersion(请求);
VAR controllerKey =的String.Format(CultureInfo.InvariantCulture,{0}。{1},
版本,controllerName);
//如果(controllers.TryGetValue(controllerName,出controllerDescriptor))
// { 如果(!string.IsNullOrEmpty(版本))
{
HttpControllerDescriptor versionedControllerDescriptor;
如果(controllers.TryGetValue(controllerKey,出versionedControllerDescriptor))
{
返回versionedControllerDescriptor;
}
}
返回null;
} 私人字符串GetVersionFromAcceptHeaderVersion(HTT prequestMessage要求)
{
VAR acceptHeader = request.Headers.Accept;
的foreach(在acceptHeader VAR MIME)
{
如果(mime.MediaType ==应用/ JSON|| mime.MediaType ==text / html的)
{
VAR的版本= mime.Parameters
。凡(V => v.Name.Equals(版本,StringComparison.OrdinalIgnoreCase))
.FirstOrDefault();
如果(版本!= NULL)
{
返回version.Value;
}
返回的String.Empty;
}
}
返回的String.Empty;
}
解决方案我试过以下。作品以现在 -
公共类CustomControllerSelector:DefaultHttpControllerSelector
{
//常量字符串零件名称=Webapi.Controllers;
私人只读HttpConfiguration _config; 公共CustomControllerSelector(HttpConfiguration配置)
:基部(配置)
{
_config =配置;
} 公众覆盖System.Web.Http.Controllers.HttpControllerDescriptor SelectController(HTT prequestMessage要求)
{
变种_route = request.GetRouteData(); VAR controllerName = base.GetControllerName(请求); VAR类型= _config.Services.GetAssembliesResolver();
变种controlles = _config.Services.GetHttpControllerTypeResolver()GetControllerTypes(类型)。 对象名称;
_route.Values.TryGetValue(路线,从名); //没有更多的硬编码
VAR零件名称= controllers.FirstOrDefault()命名空间。
VAR ST =的字符串类型;
如果(ST!= NULL)
{
VAR ConType首= controlles.FirstOrDefault(A => a.Namespace ==的String.Format({0} {1},零件名称,ST));
如果(ConType报!= NULL)
返回新System.Web.Http.Controllers.HttpControllerDescriptor(_config,controllerName,ConType首);
} 返回base.SelectController(请求);
}
}在WebApiConfig.cs -
config.Routes.MapHttpRoute(
名称:DefaultApi
routeTemplate:API / {控制器} / {}路由/(编号),
默认:新{ID = RouteParameter.Optional}
);测试路线 -
的http://本地主机:60957 / API /另一/路由/ A
HTTP://本地主机:60957 / API /另一/ Route2到/ AAAAAI'm trying to
api versioning
usingheader
but indifferent folder structure
like below.In
Controller folder
haveV1
sub folder inside thatCustomerController.cs
andIn
Controller folder
haveV2
sub folder inside thatCustomerController.cs
when I user api version using
URL
above works fine.my issue is When I try this approach with
header
it is giving me below error:{ "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; }
解决方案I tried following. Works as of now -
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); } }
In the WebApiConfig.cs -
config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{route}/{id}", defaults: new { id = RouteParameter.Optional } );
Test routes -
http://localhost:60957/api/Another/Route/a http://localhost:60957/api/Another/Route2/aaaaa
这篇关于多种类型的发现控制器匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!