Multiple types were found that match the controller

不问归期 提交于 2019-12-07 21:24:36

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!