HttpControllerSelector

HttpControllerSelector

本文介绍了例外HttpControllerDispatcher的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我WebApiConfig ::寄存器(......)我更换了HttpControllerSelector用我自己的控制器选择。当我火了一个POST请求SelectController成员正确调用和我返回ControllerDescriptor具有正确的类型我的控制器。
但随后HttpControllerDispatcher是抛出一个异常说:给定的是没有在字典present。任何人有一个想法如何调试这样的错误?

完整的例外是消息:

 给定的关键是不是在词典present,ExceptionType:System.Collections.Generic.KeyNotFoundException,堆栈跟踪:System.Collections中时.Generic.Dictionary`2.get_Item(TKEY的键)\\ r \\ n
在System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.FindActionMatchRequiredRouteAndQueryParameters(IEnumerable`1 candidatesFound)\\ r \\ n
在System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.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&下。SendAsync> d__1.MoveNext()

这是我的控制器选择:

 公共类Namespace_HTTP_Controller_Selector:IHttpControllerSelector
{
    私人只读HttpConfiguration _configuration;
    私人只读懒<&字典LT;字符串,HttpControllerDescriptor>> _controller;    公共Namespace_HTTP_Controller_Selector(HttpConfiguration配置)
    {
        _configuration =配置;
        _controller =新懒人<&字典LT;字符串,HttpControllerDescriptor>>(Initialize_Controller_Dictionary);
    }    公共HttpControllerDescriptor SelectController(HTT prequestMessage请求)
    {
        变种Route_Data = Request.GetRouteData();
        如果(Route_Data == NULL)
        {
            抛出新的Htt presponseException(的HTTPStatus code.NotFound);
        }        VAR CONTROLLER_NAME = Get_Controller_Name(Route_Data);
        如果(CONTROLLER_NAME == NULL)
        {
            抛出新的Htt presponseException(的HTTPStatus code.NotFound);
        }        VAR Name_Space = Get_Version(Route_Data);
        如果(Name_Space == NULL)
        {
            抛出新的Htt presponseException(的HTTPStatus code.NotFound);
        }        VAR Controller_Key =的String.Format(CultureInfo.InvariantCulture,{0} {1},Name_Space,CONTROLLER_NAME);        HttpControllerDescriptor描述;
        如果(_controller.Value.TryGetValue(Controller_Key,出描述符))
        {
            返回描述;
        }        抛出新的Htt presponseException(的HTTPStatus code.NotFound);
    }    公众的IDictionary<字符串,HttpControllerDescriptor> GetControllerMapping()
    {
        返回_controller.Value;
    }
    私人字典<字符串,HttpControllerDescriptor> Initialize_Controller_Dictionary()
    {
        VAR字典=新字典<字符串,HttpControllerDescriptor>(StringComparer.OrdinalIgnoreCase);        变种Assemblies_Resolver = _configuration.Services.GetAssembliesResolver();
        变种Controller_Resolver = _configuration.Services.GetHttpControllerTypeResolver();        VAR Controller_Types = Controller_Resolver.GetControllerTypes(Assemblies_Resolver);        的foreach(在Controller_Types VAR克拉)
        {
            VAR分段= 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.Length - 1],CONTROLLER_NAME);
            如果(Dictionary.Keys.Contains(Controller_Key)== FALSE)
            {
                词典[Controller_Key] =新HttpControllerDescriptor(_configuration,ct.Name,CT);
            }
        }        返回字典;
    }    私人ŧGet_Route_Variable< T>(IHttpRouteData Route_Data,字符串名称)
    {
        对象结果;        如果(Route_Data.Values​​.TryGetValue(姓名,出结果))
        {
            回报(T)的结果;
        }        返回默认(T);
    }
    私人字符串Get_Controller_Name(IHttpRouteData Route_Data)
    {        。变种SubRoute = Route_Data.GetSubRoutes()FirstOrDefault();        如果(SubRoute == NULL)
        {
            返回null;
        }        VAR Data_Token_Value = SubRoute.Route.DataTokens.First()值。
        如果(Data_Token_Value == NULL)
        {
            返回null;
        }
        VAR CONTROLLER_NAME = ((HttpActionDescriptor[])Data_Token_Value).First().ControllerDescriptor.ControllerName.Replace(\"Controller\",的String.Empty);
        返回CONTROLLER_NAME;
    }    私人字符串Get_Version(IHttpRouteData Route_Data)
    {
        。变种Sub_Route_Data = Route_Data.GetSubRoutes()FirstOrDefault();
        如果(Sub_Route_Data == NULL)
        {
            返回null;
        }        返回Get_Route_Variable<串GT;(Sub_Route_DataapiVersion);
    }
}


解决方案

这是因为你没有返回描述符前要求设置subroute数据。

  HttpControllerDescriptor描述;
如果(_controller.Value.TryGetValue(Controller_Key,出描述符))
{
    变种子路径= Route_Data.GetSubRoutes();
    IEnumerable的< IHttpRouteData> filteredSubRoutes = subRoutes.Where(attrRouteData =>
    {
        HttpControllerDescriptor currentDescriptor =((HttpActionDescriptor [])Route_Data.Route.DataTokens [行动])(第)ControllerDescriptor。;
        返回currentDescriptor = NULL&放大器;!&安培; currentDescriptor.ControllerName.Equals(Descriptor.ControllerName,StringComparison.OrdinalIgnoreCase);
    });
    Route_Data.Values​​ [MS_SubRoutes] = filteredSubRoutes.ToArray();
    返回描述;
}

看看:
Versioning的ASP.NET Web API 2介质类型

In my WebApiConfig::Register(...) I replaced the HttpControllerSelector with my own controller selector. When I fire off a POST request the SelectController member is correctly called and I return a ControllerDescriptor with the correct type of my controller.But then HttpControllerDispatcher is raising an exception saying "The given was not present in the dictionary." Anyone has an idea how to debug such error?

The complete exception is message is:

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()"

And here is my Controller Selector:

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");
    }
}
解决方案

This is because you are not setting subroute data in request before returning descriptor.

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

Take a look at:Versioning ASP.NET Web API 2 with Media Types

这篇关于例外HttpControllerDispatcher的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 14:54