Asp.net web api HttpControllerDispatcher中的异常

Asp.net web api HttpControllerDispatcher中的异常,asp.net-web-api,asp.net-web-api2,asp.net-web-api-routing,Asp.net Web Api,Asp.net Web Api2,Asp.net Web Api Routing,在我的WebApiConfig::Register(…)中,我用自己的控制器选择器替换了HttpControllerSelector。当我发出POST请求时,SelectController成员被正确调用,我返回一个具有正确控制器类型的ControllerDescriptor。 但是HttpControllerDispatcher提出了一个异常,说“字典中没有给定的”。有人知道如何调试这样的错误吗 完全例外的消息是: The given key was not present in the di

在我的WebApiConfig::Register(…)中,我用自己的控制器选择器替换了HttpControllerSelector。当我发出POST请求时,SelectController成员被正确调用,我返回一个具有正确控制器类型的ControllerDescriptor。 但是HttpControllerDispatcher提出了一个异常,说“字典中没有给定的”。有人知道如何调试这样的错误吗

完全例外的消息是:

The given key was not present in the dictionary.","ExceptionType":"System.Collections.Generic.KeyNotFoundException","StackTrace":"   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)\r\n   
at System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.FindActionMatchRequiredRouteAndQueryParameters(IEnumerable`1 candidatesFound)\r\n   
at System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.FindMatchingActions(HttpControllerContext controllerContext, Boolean ignoreVerbs)\r\n   
at System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext controllerContext)\r\n   
at System.Web.Http.Controllers.ApiControllerActionSelector.SelectAction(HttpControllerContext controllerContext)\r\n   
at System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)\r\n   
at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"
字典中不存在给定的键。“,“ExceptionType”:“System.Collections.Generic.KeyNotFoundException”,“StackTrace”:“at System.Collections.Generic.dictionary`2.get\u项(TKey key)\r\n
位于System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.FindActionMatchRequiredRouteAndQueryParameters(IEnumerable`1 candidatesFound)\r\n
位于System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelector或CacheItem.FindMatchingActions(HttpControllerContext controllerContext,布尔型ignoreVerbs)\r\n
位于System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext controllerContext)\r\n
位于System.Web.Http.Controllers.ApiControllerActionSelector.SelectAction(HttpControllerContext controllerContext)\r\n
位于System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext,CancellationToken CancellationToken)\r\n
位于System.Web.Http.Dispatcher.HttpControllerDispatcher.d_u1.MoveNext()
这是我的控制器选择器:

public class Namespace_HTTP_Controller_Selector : IHttpControllerSelector
{
    private readonly HttpConfiguration _configuration;
    private readonly Lazy<Dictionary<string, HttpControllerDescriptor>> _controller;

    public Namespace_HTTP_Controller_Selector(HttpConfiguration Config)
    {
        _configuration = Config;
        _controller = new Lazy<Dictionary<string, HttpControllerDescriptor>>(Initialize_Controller_Dictionary);
    }

    public HttpControllerDescriptor SelectController(HttpRequestMessage Request)
    {
        var Route_Data = Request.GetRouteData();
        if(Route_Data == null)
        {
            throw new HttpResponseException(HttpStatusCode.NotFound);
        }

        var Controller_Name = Get_Controller_Name(Route_Data);
        if(Controller_Name ==  null)
        {
            throw new HttpResponseException(HttpStatusCode.NotFound);
        }

        var Name_Space = Get_Version(Route_Data);
        if (Name_Space == null)
        {
            throw new HttpResponseException(HttpStatusCode.NotFound);
        }

        var Controller_Key = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", Name_Space, Controller_Name);

        HttpControllerDescriptor Descriptor;
        if(_controller.Value.TryGetValue(Controller_Key, out Descriptor))
        {
            return Descriptor;
        }

        throw new HttpResponseException(HttpStatusCode.NotFound);
    }

    public IDictionary<string, HttpControllerDescriptor> GetControllerMapping()
    {
        return _controller.Value;
    }


    private Dictionary<string, HttpControllerDescriptor> Initialize_Controller_Dictionary()
    {
        var Dictionary = new Dictionary<string, HttpControllerDescriptor>(StringComparer.OrdinalIgnoreCase);

        var Assemblies_Resolver = _configuration.Services.GetAssembliesResolver();
        var Controller_Resolver = _configuration.Services.GetHttpControllerTypeResolver();

        var Controller_Types = Controller_Resolver.GetControllerTypes(Assemblies_Resolver);

        foreach(var ct in Controller_Types)
        {
            var Segments = ct.Namespace.Split(Type.Delimiter);

            var Controller_Name = ct.Name.Remove(ct.Name.Length - DefaultHttpControllerSelector.ControllerSuffix.Length);

            var Controller_Key = string.Format(CultureInfo.InvariantCulture, "{0}.{1}", Segments[Segments.Length - 1], Controller_Name);


            if(Dictionary.Keys.Contains(Controller_Key) == false)
            {
                Dictionary[Controller_Key] = new HttpControllerDescriptor(_configuration, ct.Name, ct);
            }
        }

        return Dictionary;
    }

    private T Get_Route_Variable<T>(IHttpRouteData Route_Data, string Name)
    {
        object Result;

        if(Route_Data.Values.TryGetValue(Name, out Result))
        {
            return (T)Result;
        }

        return default(T);
    }


    private string Get_Controller_Name(IHttpRouteData Route_Data)
    {

        var SubRoute = Route_Data.GetSubRoutes().FirstOrDefault();

        if( SubRoute == null )
        {
            return null;
        }

        var Data_Token_Value = SubRoute.Route.DataTokens.First().Value;
        if(Data_Token_Value == null)
        {
            return null;
        }


        var Controller_Name = ((HttpActionDescriptor[])Data_Token_Value).First().ControllerDescriptor.ControllerName.Replace("Controller", string.Empty);


        return Controller_Name;
    }

    private string Get_Version(IHttpRouteData Route_Data)
    {
        var Sub_Route_Data = Route_Data.GetSubRoutes().FirstOrDefault();
        if(Sub_Route_Data== null)
        {
            return null;
        }

        return Get_Route_Variable<string>(Sub_Route_Data, "apiVersion");
    }
}
公共类名称空间\u HTTP\u控制器\u选择器:IHttpControllerSelector
{
私有只读HttpConfiguration\u配置;
专用只读懒控制器;
公共名称空间\u HTTP\u控制器\u选择器(HttpConfiguration配置)
{
_配置=配置;
_控制器=新延迟(初始化\u控制器\u字典);
}
公共HttpControllerDescriptor SelectController(HttpRequestMessage请求)
{
var Route_Data=Request.GetRouteData();
如果(路由_数据==null)
{
抛出新的HttpResponseException(HttpStatusCode.NotFound);
}
var控制器名称=获取控制器名称(路由数据);
如果(控制器名称==null)
{
抛出新的HttpResponseException(HttpStatusCode.NotFound);
}
var Name_Space=获取_版本(路由_数据);
if(Name_Space==null)
{
抛出新的HttpResponseException(HttpStatusCode.NotFound);
}
var Controller_Key=String.Format(CultureInfo.InvariantCulture,“{0}.{1}”,名称空间,控制器名称);
HttpControllerDescriptor描述符;
if(_controller.Value.TryGetValue(controller_键,out描述符))
{
返回描述符;
}
抛出新的HttpResponseException(HttpStatusCode.NotFound);
}
公共IDictionary GetControllerMapping()
{
返回_controller.Value;
}
专用字典初始化\u控制器\u字典()
{
var字典=新字典(StringComparer.OrdinalIgnoreCase);
var Assemblies_Resolver=_configuration.Services.GetAssembliesResolver();
var Controller_Resolver=_configuration.Services.GetHttpControllerTypeResolver();
var Controller\u Types=Controller\u Resolver.GetControllerTypes(assemblems\u Resolver);
foreach(控制器类型中的变量ct)
{
var Segments=ct.Namespace.Split(Type.Delimiter);
var Controller_Name=ct.Name.Remove(ct.Name.Length-DefaultHttpControllerSelector.ControllerSuffix.Length);
var Controller_Key=string.Format(CultureInfo.InvariantCulture,“{0}.{1}”、Segments[Segments.Length-1],Controller_Name);
if(Dictionary.Keys.Contains(Controller_Key)==false)
{
字典[Controller\u Key]=新的HttpControllerDescriptor(\u配置,ct.Name,ct);
}
}
返回字典;
}
private T Get_Route_变量(IHttpRouteData Route_数据,字符串名称)
{
客观结果;
if(路由_数据.Values.TryGetValue(名称,输出结果))
{
返回(T)结果;
}
返回默认值(T);
}
私有字符串获取\u控制器\u名称(IHttpRouteData路由\u数据)
{
var subcute=Route_Data.getsubcutes().FirstOrDefault();
if(子例程==null)
{
返回null;
}
var Data_Token_Value=subcure.Route.DataTokens.First().Value;
if(数据\u标记\u值==null)
{
返回null;
}
var Controller_Name=((HttpActionDescriptor[])Data_Token_Value.First().ControllerDescriptor.ControllerName.Replace(“Controller”,string.Empty);
返回控制器名称;
}
私有字符串获取版本(IHttpRouteData路由数据)
{
var Sub_Route_Data=Route_Data.GetSubRoutes().FirstOrDefault();
if(子路由数据==null)
{
返回null;
}
返回Get_Route_变量(Sub_Route_数据,“apiVersion”);
}
}

这是因为在返回描述符之前,您没有在请求中设置子例程数据

HttpControllerDescriptor Descriptor;
if(_controller.Value.TryGetValue(Controller_Key, out Descriptor))
{
    var subRoutes = Route_Data.GetSubRoutes();
    IEnumerable<IHttpRouteData> filteredSubRoutes = subRoutes.Where(attrRouteData =>
    {
        HttpControllerDescriptor currentDescriptor = ((HttpActionDescriptor[])Route_Data.Route.DataTokens["actions"]).First().ControllerDescriptor;
        return currentDescriptor != null && currentDescriptor.ControllerName.Equals(Descriptor.ControllerName, StringComparison.OrdinalIgnoreCase);
    });
    Route_Data.Values["MS_SubRoutes"] = filteredSubRoutes.ToArray();
    return Descriptor;
}
HttpControllerDescriptor描述符;
if(_controller.Value.TryGetValue(controller_键,out描述符))
{
var subRoutes=Route_Data.GetSubRoutes();
IEnumerable filteredSubRoutes=子例程。其中(AttrRoutedData=>
{
HttpControllerDescriptor currentDescriptor=((HttpActionDescriptor[])Route_Data.Route.DataTokens[“actions”]).First().ControllerDescriptor;
返回currentDescriptor!=null&¤tDescriptor.ControllerName.Equals(Descriptor.ControllerName,StringComparison.OrdinalIgnoreCase);
});
Route_Data.Values[“MS_子例程”]=filteredSubRoutes.ToArray();
返回描述符;
}
看看:

公共类CustomSelector控制器:默认HttpControllerSelector
{
HttpConfiguration\u config;
public class CustomSelectorController : DefaultHttpControllerSelector
    {
        HttpConfiguration _config;

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

        public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
        {
            IHttpRouteData routeData = request.GetRouteData();
            IEnumerable<IHttpRouteData> attributeSubRoutes = routeData.GetSubRoutes();

            var actions = attributeSubRoutes.LastOrDefault()?.Route?.DataTokens["actions"] as HttpActionDescriptor[];

            var controllerName = "";
            if (actions != null && actions.Length > 0)
            {
                controllerName = actions[0].ControllerDescriptor.ControllerName;
            }

            IEnumerable<string> headerValues = null;
            //Custom Header Name to be check version
            if (request.Headers.TryGetValues("Accept-Version", out headerValues))
            {
                var apiVersion = headerValues.First().ToUpper();
                if (apiVersion == "V2")
                {
                    controllerName = controllerName + apiVersion;
                }
            }

            HttpControllerDescriptor controllerDescriptor = null;

            IEnumerable<IHttpRouteData> filteredSubRoutes = attributeSubRoutes.Where(attrRouteData =>
            {
                HttpControllerDescriptor currentDescriptor = GetControllerDescriptor(attrRouteData);

                bool match = currentDescriptor.ControllerName.Equals(controllerName);

                if (match && (controllerDescriptor == null))
                {
                    controllerDescriptor = currentDescriptor;
                }

                return match;
            });

            routeData.Values["MS_SubRoutes"] = filteredSubRoutes.ToArray();
            return controllerDescriptor;
        }
        private HttpControllerDescriptor GetControllerDescriptor(IHttpRouteData routeData)
        {
            return ((HttpActionDescriptor[])routeData.Route.DataTokens["actions"]).First().ControllerDescriptor;
        }
    }