c# – 使用媒体类型版本化ASP.NET Web API 2

c# – 使用媒体类型版本化ASP.NET Web API 2,第1张

概述我正在使用具有属性路由的ASP.NET Web API 2,但我似乎无法使用媒体类型application / vnd.company [.version] .param [json]获得版本控制. 我收到以下错误: The given key was not present in the dictionary. 它来源于FindActionMatchRequiredRouteAndQueryPa 我正在使用具有属性路由的ASP.NET Web API 2,但我似乎无法使用媒体类型application / vnd.company [.version] .param [Json]获得版本控制.

我收到以下错误:

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所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1235975.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存