多种类型的发现控制器匹配 [英] Multiple types were found that match the controller

查看:201
本文介绍了多种类型的发现控制器匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图 API版本使用不同的文件夹结构象下面这样。

控制器文件夹 V1 里面的子文件 CustomerController.cs

控制器文件夹 V2 里面的子文件 CustomerController.cs

当我用户API版本使用上述网​​址正常工作

我的问题是,当我试着使用这是给我下面的错误这种方式:


  

{消息:发生错误,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到/ AAAAA

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;
        }

解决方案

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆