zoukankan      html  css  js  c++  java
  • MVC Api 的跨项目路由

    现有Momoda.Api项目,由于团队所有人在此项目下开发,导致耦合度太高,现从此接口项目中拆分出多个子项目从而避免对Momda.Api的改动导致“爆炸”
    MVCApi的跨项目路由和MVC有解决方式有点不同
    第一步:
    首先在Momoda下创建域创建好之后把生成的YZCAreaRegistration文件移动到Areas目录下YZC目录外,然后排除YZC文件夹,像这样:
    第二步:
    创建一个新的MVCApi叫 YZC.WebAi,在资源管理器中用 YZC.WebAi文件夹下的内容替换掉Areas下的YZC域文件夹中的内容,并且只留下Controllers,Views和Models三个文件夹,其他的config和Global等都删除
    第三步:
    右键LYL解决方案添加现有项目在YZC域下找到工程文件 ( LYLMomoda.ApiAreas)
    这样就把Momoda.Api下的YZC域给拆分出来,开发过程中只关注YZC.WebApi即可,目录结构如下图:
    第四步:
    更改YZCAreaRegistration域路由文件。
    Api路由文件的更改是否和MVC跨域路由一样添加context.MapRoute方法的最后一个命名空间参数就能解决呢?答案当然没有那么简单。。。。。哈哈哈哈
    我们现验证以下是否按照MVC跨项目路由的解决方案也同样适用于Api。
    更改父API项目的域路由文件:
    1 public override void RegisterArea(AreaRegistrationContext context)
    2         {
    3             context.MapRoute(
    4                 "YZC_default",
    5                 "YZC/{controller}/{action}/{id}",
    6                 new { action = "Index", id = UrlParameter.Optional },
    7                 new string[] { "YZC.Controllers" }//添加域项目的控制层命名空间
    8             );
    9         }
    在子api项目中添加controller:
     1 {
     2     public class ChildrenController : ApiController
     3     {  
     4 #region 跨项目路由测试
     5         [HttpGet]
     6         public string Test()
     7         {
     8             return "小良哥";
     9         }
    10         #endregion
    11     }
    12 }
    浏览器中测试结果:
    没有路由到,表明MVC域的处理和Api域的处理是不同的
    解决方案:
    在父ApiMomoda.Api下的App_Start中新增叫CustomHttpControllerSelector的类并且继承DefaultHttpControllerSelector
    代码如下:
     1 /// <summary>
     2     /// 自定义区域类
     3     /// </summary>
     4     public class CustomHttpControllerSelector: DefaultHttpControllerSelector
     5     {
     6         private const string NamespaceRouteVariableName = namespaceName";
     7 //namespaceName之后要用到
     8         //private const string AreaRouteVariableName = "area";
     9         private readonly HttpConfiguration _configuration;
    10         private readonly Lazy<ConcurrentDictionary<string, Type>> _apiControllerCache;
    11 
    12         public CustomHttpControllerSelector(HttpConfiguration configuration)
    13             : base(configuration)
    14         {
    15             _configuration = configuration;
    16 
    17             _apiControllerCache = new Lazy<ConcurrentDictionary<string, Type>>(
    18                 new Func<ConcurrentDictionary<string, Type>>(InitializeApiControllerCache));
    19         }
    20 
    21 
    22         private ConcurrentDictionary<string, Type> InitializeApiControllerCache()
    23         {
    24             IAssembliesResolver assembliesResolver = this._configuration.Services.GetAssembliesResolver();
    25             var types = this._configuration.Services.GetHttpControllerTypeResolver()
    26                 .GetControllerTypes(assembliesResolver).ToDictionary(t => t.FullName, t => t);
    27 
    28             return new ConcurrentDictionary<string, Type>(types);
    29         }
    30 
    31         public IEnumerable<string> GetControllerFullName(HttpRequestMessage request, string controllerName)
    32         {
    33             object namespaceName;
    34             var data = request.GetRouteData();
    35             IEnumerable<string> keys = _apiControllerCache.Value.ToDictionary<KeyValuePair<string, Type>, string, Type>(t => t.Key,
    36                     t => t.Value, StringComparer.OrdinalIgnoreCase).Keys.ToList();
    37 
    38             if (!data.Values.TryGetValue(NamespaceRouteVariableName, out namespaceName))
    39             {
    40                 return from k in keys
    41                        where k.EndsWith(string.Format(".{0}{1}", controllerName,
    42                        DefaultHttpControllerSelector.ControllerSuffix), StringComparison.OrdinalIgnoreCase)
    43                        select k;
    44             }
    45 
    46             string[] namespaces = (string[])namespaceName;
    47             return from n in namespaces
    48                    join k in keys on string.Format("{0}.{1}{2}", n, controllerName,
    49                    DefaultHttpControllerSelector.ControllerSuffix).ToLower() equals k.ToLower()
    50                    select k;
    51         }
    52 
    53 
    54         public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
    55         {
    56             Type type;
    57             if (request == null)
    58             {
    59                 throw new ArgumentNullException("request");
    60             }
    61 
    62             string controllerName = this.GetControllerName(request);
    63             if (string.IsNullOrEmpty(controllerName))
    64             {
    65                 throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound,
    66                     string.Format("No route providing a controller name was found to match request URI '{0}'",
    67                     new object[] { request.RequestUri })));
    68             }
    69 
    70             IEnumerable<string> fullNames = GetControllerFullName(request, controllerName);
    71             if (fullNames.Count() == 0)
    72             {
    73                 throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound,
    74                         string.Format("No route providing a controller name was found to match request URI '{0}'",
    75                         new object[] { request.RequestUri })));
    76             }
    77 
    78             if (!this._apiControllerCache.Value.TryGetValue(fullNames.First(), out type))
    79             {
    80                 throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound,
    81                         string.Format("No route providing a controller name was found to match request URI '{0}'",
    82                         new object[] { request.RequestUri })));
    83             }
    84 
    85             return new HttpControllerDescriptor(_configuration, controllerName, type);
    86         }
    87     }
    View Code
    更改父API项目的域路由文件为:
     1 namespace Momoda.Api
     2 {
     3     public class YZCAreaRegistration : AreaRegistration
     4     {
     5         public override string AreaName//域名称
     6         {
     7             get
     8             {
     9                 return "YZC";
    10             }
    11         }
    12         public override void RegisterArea(AreaRegistrationContext context)
    13         {
    14             context.Routes.MapHttpRoute(
    15                   name: this.AreaName + "_default",
    16                   routeTemplate: "api/" + this.AreaName + "/{controller}/{action}/{id}",
    17                   defaults: new
    18            {
    19           id = RouteParameter.Optional,
    20           namespaceName = new string[] { string.Format("{0}.Controllers",this.AreaName) }
    21  //namespaceName名称要CustomHttpControllerSelector中NamespaceRouteVariableName的值一致
    22           }
    23               );  
    24         }
    25     }
    26 }
    这样就完成了吗?没有!!!必须把域YZC.WebApi生成路径设置为Momoda.Api的bin文件下
    测试结果:
    成功!
    域名称可加可不加同样成功
    17:57:11,嘿嘿,下班啦
     
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    Linux虚拟内存(swap)调优篇-“swappiness”,“vm.dirty_background_ratio”和“vm.dirty_ratio”
    《Kafka权威指南》读书笔记-操作系统调优篇
    HTML&CSS基础-表单简介
    《Apache Kafka 实战》读书笔记-认识Apache Kafka
    HTML&CSS基础-完善clearfix
    HTML&CSS基础-使用表格布局
    比Kafka Mangaer更优秀的开源监控工具-Kafka Eagle
    Kafka吞吐量测试案例
    flume常见异常汇总以及解决方案
    运维监控-Open-Falcon单机部署实战篇
  • 原文地址:https://www.cnblogs.com/xiaoliangge/p/6027617.html
Copyright © 2011-2022 走看看