我收到以下错误:
The given key was not present in the dictionary.
它来源于FindActionMatchrequiredRouteAnd@R_502_5962@Parameters()方法中的关键_actionParameternames [descriptor].
foreach (var candIDate in candIDatesFound){ httpActionDescriptor descriptor = candIDate.ActionDescriptor; if (IsSubset(_actionParameternames[descriptor],candIDate.CombinedParameternames)) { matches.Add(candIDate); }}
资料来源:ApiControllerActionSelector.cs
进一步调试后,我意识到如果你有两个控制器
[RoutePrefix("API/people")]public class PeopleController : BaseAPIController{ [Route("")] public httpResponseMessage GetPeople() { } [Route("IDentifIEr/{ID}")] public httpResponseMessage GetPersonByID() { }}[RoutePrefix("API/people")]public class PeopleV2Controller : BaseAPIController{ [Route("")] public httpResponseMessage GetPeople() { } [Route("IDentifIEr/{ID}")] public httpResponseMessage GetPersonByID() { }}
您不能使用您的自定义ApiVersioningSelector : DefaultHttpControllerSelector
,因为它将测试所有键,如上所述,具有相同[RoutePrefix(“API / people”)]的所有控制器,显然会抛出异常.
只是为了确保选择了正确的控制器
我不知道这是否是一个错误,但是使用路由[RoutePrefix(“API / v1 / people”)]到版本API让我很伤心.
注意:没有属性路由,这很有效.
UPDATE
public class APIVersioningSelector : DefaulthttpControllerSelector { private httpConfiguration _httpConfiguration; public APIVersioningSelector(httpConfiguration httpConfiguration) : base(httpConfiguration) { _httpConfiguration = httpConfiguration; } public overrIDe httpControllerDescriptor SelectController(httpRequestMessage request) { IDictionary<string,httpControllerDescriptor> controllers = GetControllerMapPing(); var attributedRoutesData = request.GetRouteData().GetSubroutes(); var subrouteData = attributedRoutesData.LastOrDefault(); //LastOrDefault() will get PeopleController,FirstOrDefault will get People{version}Controller which we don't want var actions = (ReflectedhttpActionDescriptor[])subrouteData.Route.DataTokens["actions"]; var controllername = actions[0].ControllerDescriptor.Controllername; //For controller name without attribute routing //var controllername = (string)routeData.Values["controller"]; httpControllerDescriptor oldControllerDescriptor; if (controllers.TryGetValue(controllername,out oldControllerDescriptor)) { var APIVersion = GetVersionFromMediaType(request); var newControllername = String.Concat(controllername,"V",APIVersion); httpControllerDescriptor newControllerDescriptor; if (controllers.TryGetValue(newControllername,out newControllerDescriptor)) { return newControllerDescriptor; } return oldControllerDescriptor; } return null; } private string GetVersionFromMediaType(httpRequestMessage request) { var acceptheader = request.headers.Accept; var regularExpression = new Regex(@"application\/vnd\.mycompany\.([a-z]+)\.v([0-9]+)\+Json",RegexOptions.IgnoreCase); foreach (var mime in acceptheader) { var match = regularExpression.Match(mime.MediaType); if (match != null) { return match.Groups[2].Value; } } return "1"; } }解决方法 感谢您分享您的代码.我已经修改了您的版本控制器选择器,如下所示,并尝试了一些情况,它似乎工作正常.您可以尝试如下更新您的控制器选择器,看看它是否有效?
public overrIDe httpControllerDescriptor SelectController(httpRequestMessage request) { httpControllerDescriptor controllerDescriptor = null; // get List of all controllers provIDed by the default selector IDictionary<string,httpControllerDescriptor> controllers = GetControllerMapPing(); IhttpRouteData routeData = request.GetRouteData(); if (routeData == null) { throw new httpResponseException(httpStatusCode.NotFound); } //check if this route is actually an attribute route IEnumerable<IhttpRouteData> attributeSubroutes = routeData.GetSubroutes(); var APIVersion = GetVersionFromMediaType(request); if (attributeSubroutes == null) { string controllername = GetRouteVariable<string>(routeData,"controller"); if (controllername == null) { throw new httpResponseException(httpStatusCode.NotFound); } string newControllername = String.Concat(controllername,APIVersion); if (controllers.TryGetValue(newControllername,out controllerDescriptor)) { return controllerDescriptor; } else { throw new httpResponseException(httpStatusCode.NotFound); } } else { // we want to find all controller descriptors whose controller type names end with // the following suffix(ex: CustomersV1) string newControllernameSuffix = String.Concat("V",APIVersion); IEnumerable<IhttpRouteData> filteredSubroutes = attributeSubroutes.Where(attrRouteData => { httpControllerDescriptor currentDescriptor = GetControllerDescriptor(attrRouteData); bool match = currentDescriptor.Controllername.EndsWith(newControllernameSuffix); 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; } // Get a value from the route data,if present. private static T GetRouteVariable<T>(IhttpRouteData routeData,string name) { object result = null; if (routeData.Values.TryGetValue(name,out result)) { return (T)result; } return default(T); }总结
以上是内存溢出为你收集整理的c# – 使用媒体类型版本化ASP.NET Web API 2全部内容,希望文章能够帮你解决c# – 使用媒体类型版本化ASP.NET Web API 2所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)