zoukankan      html  css  js  c++  java
  • 解决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() }
                );
    
            }
        }
  • 相关阅读:
    搞破坏(手动滑稽),如何写出让同事无法维护的代码?
    我们公司是如何把项目中的2100个if-else彻底干掉的
    为什么阿里规定需在事务注解@Transactional中指定rollbackFor?
    算法导论 10.2-7
    算法导论 10.2-3
    算法导论 10.2-2
    算法导论 10.1-7
    算法导论 10.1-6
    算法导论 2.3-7
    算法导论 2.3-5 二分查找
  • 原文地址:https://www.cnblogs.com/youguess/p/13155071.html
Copyright © 2011-2022 走看看