• 解决Web API路由配置支持Area及命名空间参数


    解决Web API路由配置支持Area及命名空间参数 

    首先创建一个新的HttpControllerSelector类

    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Web;
    using System.Web.Http;
    using System.Web.Http.Controllers;
    using System.Web.Http.Dispatcher;
    
    namespace _1_解决MVC的Controller和Web_API的Controller类名不能相同的问题.App_Start.webExt
    {
        public class NamespaceHttpControllerSelector : DefaultHttpControllerSelector
        {
            private const string NamespaceRouteVariableName = "namespaceName";
            private readonly HttpConfiguration _configuration;
            private readonly Lazy<ConcurrentDictionary<string, Type>> _apiControllerCache;
    
            public NamespaceHttpControllerSelector(HttpConfiguration configuration)
                : base(configuration)
            {
                _configuration = configuration;
                _apiControllerCache = new Lazy<ConcurrentDictionary<string, Type>>(new Func<ConcurrentDictionary<string, Type>>(InitializeApiControllerCache));
            }
    
            private ConcurrentDictionary<string, Type> InitializeApiControllerCache()
            {
                IAssembliesResolver assembliesResolver = this._configuration.Services.GetAssembliesResolver();
                var types = this._configuration.Services.GetHttpControllerTypeResolver().GetControllerTypes(assembliesResolver).ToDictionary(t => t.FullName, t => t);
    
                return new ConcurrentDictionary<string, Type>(types);
            }
    
            public IEnumerable<string> GetControllerFullName(HttpRequestMessage request, string controllerName)
            {
                object namespaceName;
                var data = request.GetRouteData();
                IEnumerable<string> keys = _apiControllerCache.Value.ToDictionary<KeyValuePair<string, Type>, string, Type>(t => t.Key,
                        t => t.Value, StringComparer.CurrentCultureIgnoreCase).Keys.ToList();
    
                if (!data.Values.TryGetValue(NamespaceRouteVariableName, out namespaceName))
                {
                    return from k in keys
                           where k.EndsWith(string.Format(".{0}{1}", controllerName, DefaultHttpControllerSelector.ControllerSuffix), StringComparison.CurrentCultureIgnoreCase)
                           select k;
                }
    
                //get the defined namespace
                string[] namespaces = (string[])namespaceName;
                return from n in namespaces
                       join k in keys on string.Format("{0}.{1}{2}", n, controllerName, DefaultHttpControllerSelector.ControllerSuffix).ToLower() equals k.ToLower()
                       select k;
            }
    
            public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
            {
                Type type;
                if (request == null)
                {
                    throw new ArgumentNullException("request");
                }
                string controllerName = this.GetControllerName(request);
                if (string.IsNullOrEmpty(controllerName))
                {
                    throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound,
                        string.Format("No route providing a controller name was found to match request URI '{0}'", new object[] { request.RequestUri })));
                }
                IEnumerable<string> fullNames = GetControllerFullName(request, controllerName);
                if (fullNames.Count() == 0)
                {
                    throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound,
                            string.Format("No route providing a controller name was found to match request URI '{0}'", new object[] { request.RequestUri })));
                }
    
                if (this._apiControllerCache.Value.TryGetValue(fullNames.First(), out type))
                {
                    return new HttpControllerDescriptor(_configuration, controllerName, type);
                }
                throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound,
                    string.Format("No route providing a controller name was found to match request URI '{0}'", new object[] { request.RequestUri })));
            }
        }
    
    }

    其次,在全局webApi配置文件中添加

     //为了让WebApi也支持NameSpace
                config.Services.Replace(typeof(IHttpControllerSelector), new NamespaceHttpControllerSelector(config));
    public static class WebApiConfig
        {
            public static void Register(HttpConfiguration config)
            {
                //是为了让WebApi的控制器自动匹配ApiController
                var suffix = typeof(DefaultHttpControllerSelector).GetField("ControllerSuffix", BindingFlags.Static | BindingFlags.Public);
                if (suffix != null) suffix.SetValue(null, "ApiController");
    
                //为了让WebApi也支持NameSpace
                config.Services.Replace(typeof(IHttpControllerSelector), new NamespaceHttpControllerSelector(config));
    
                // Web API 路由
                config.MapHttpAttributeRoutes();
    
                config.Routes.MapHttpRoute(
                    name: "DefaultApi",
                    routeTemplate: "api/{controller}/{id}",
                    defaults: new { id = RouteParameter.Optional }
                );
            }
        }

    最后,在区域在配置webApi路径

     GlobalConfiguration.Configuration.Routes.MapHttpRoute(
                    this.AreaName + "Api",
                    "api/" + this.AreaName + "/{controller}/{action}/{id}",
                    new
                    {
                        action = RouteParameter.Optional,
                        id = RouteParameter.Optional,
                        namespaceName = new string[] { string.Format("_1_解决MVC的Controller和Web_API的Controller类名不能相同的问题.Areas.{0}.Controllers", this.AreaName) }
                    },
                    null
                    //new { action = new StartWithConstraint() }
                );
    public class shopAreaRegistration : AreaRegistration 
        {
            public override string AreaName 
            {
                get 
                {
                    return "shop";
                }
            }
    
            public override void RegisterArea(AreaRegistrationContext context) 
            {
                context.MapRoute(
                    "shop_default",
                    "shop/{controller}/{action}/{id}",
                    new { action = "Index", id = UrlParameter.Optional },
                    new string [] { "_1_解决MVC的Controller和Web_API的Controller类名不能相同的问题.Areas.shop.Controllers" }
                );
    
                GlobalConfiguration.Configuration.Routes.MapHttpRoute(
                    this.AreaName + "Api",
                    "api/" + this.AreaName + "/{controller}/{action}/{id}",
                    new
                    {
                        action = RouteParameter.Optional,
                        id = RouteParameter.Optional,
                        namespaceName = new string[] { string.Format("_1_解决MVC的Controller和Web_API的Controller类名不能相同的问题.Areas.{0}.Controllers", this.AreaName) }
                    },
                    null
                    //new { action = new StartWithConstraint() }
                );
    
            }
        }
  • 相关阅读:
    Core Foundation 框架
    iOS下微信语音播放之切换听筒和扬声器的方法解决方案
    http://blog.sina.com.cn/s/blog_6f40a0e70100p98l.html
    web移动开发最佳实践之js篇
    iOS框架介绍(五)Core Services 层
    针式PKM V9.36 最新版(2012_03_29)
    通过10000个小时的个人知识管理,将自己的智慧潜力挖掘出来
    下载 针式PKM V9.08 版
    如何避免重复造轮子问题?
    和evernote比 针式PKM有什么特色?
  • 原文地址:https://www.cnblogs.com/youguess/p/13155071.html
Copyright © 2020-2023  润新知