问题
I'm trying to api versioning
using header
but in different folder structure
like below.
In Controller folder
have V1
sub folder inside that CustomerController.cs
and
In Controller folder
have V2
sub folder inside that CustomerController.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;
}
回答1:
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
来源:https://stackoverflow.com/questions/34715625/multiple-types-were-found-that-match-the-controller