在说二级域名绑定之前,先说一下.net core中的区域,关于区域这一块儿在很久之前的博客中,已经提过,详见《03-dotnet core创建区域[Areas]及后台搭建》,在这篇博客中,创建区域的时候,都是手动创建的,手动创建区域Areas文件夹,手动添加M-V-C等文件目录,由于在最早的VS2017版本中,直接右键添加区域的选项居然没了,然而在后来的VS版本更新中,这一功能又恢复了,也不知微软是出于什么考虑。区域的功能,就不用多说了,至于如何创建如何使用,也不多说,这些都是在MVC4的功能了。今天主要说一下关于二级域名如何绑定到指定的控制器。

二级域名也无需多说了吧,比如我们进入百度,我们直接输入www.baidu.com或者输入baidu.com(重定向到www.baidu.com),会直接进入百度的首页,而如果我们输入的是,news.baidu.com,则直接进入百度新闻,我们称news.baidu.com为二级域名,那输入不同的二级域名会进入不同的主页面,那这是如何实现的呢。关于二级域名绑定其实使用一些代理服务器如nginx等,都可以实现域名绑定,这些我们都不讨论,这里我们只讨论在.net core 项目中如何配置。

这里借助于一篇博客,园子中早已经有人对路由作了扩展,使其可以自定义域名绑定控制器,原文地址:《asp.net core mvc中如何把二级域名绑定到特定的控制器上》 。下面附上代码:二级域名逻辑判断,基于RouteBase扩展

  1. <span style="font-size:14px;">public class SubDomainRouter : RouteBase
  2. {
  3. private readonly IRouter _target;
  4. private readonly string _subDomain;
  5. public SubDomainRouter(
  6. IRouter target,
  7. string subDomain,//当前路由规则绑定的二级域名
  8. string routeTemplate,
  9. RouteValueDictionary defaults,
  10. RouteValueDictionary constrains,
  11. IInlineConstraintResolver inlineConstraintResolver)
  12. : base(routeTemplate,
  13. subDomain,
  14. inlineConstraintResolver,
  15. defaults,
  16. constrains,
  17. new RouteValueDictionary(null))
  18. {
  19. if (target == null)
  20. {
  21. throw new ArgumentNullException(nameof(target));
  22. }
  23. if (subDomain == null)
  24. {
  25. throw new ArgumentNullException(nameof(subDomain));
  26. }
  27. _subDomain = subDomain;
  28. _target = target;
  29. }
  30. public override Task RouteAsync(RouteContext context)
  31. {
  32. string domain = context.HttpContext.Request.Host.Host;//获取当前请求域名,然后跟_subDomain比较,如果不想等,直接忽略
  33. if (string.IsNullOrEmpty(domain) || string.Compare(_subDomain, domain) != 0)
  34. {
  35. return Task.CompletedTask;
  36. }
  37.       
  38.      //如果域名匹配,再去验证访问路径是否匹配
  39. return base.RouteAsync(context);
  40. }
  41. protected override Task OnRouteMatched(RouteContext context)
  42. {
  43. context.RouteData.Routers.Add(_target);
  44. return _target.RouteAsync(context);
  45. }
  46. protected override VirtualPathData OnVirtualPathGenerated(VirtualPathContext context)
  47. {
  48. return _target.GetVirtualPath(context);
  49. }
  50. }</span>

如何把域名绑定到指定的控制器上,代码如下:

  1. <span style="font-size:14px;">public static class RouteBuilderExtensions
  2. {
  3. public static IRouteBuilder MapDomainRoute(
  4. this IRouteBuilder routeBuilder,string domain,string area,string controller)
  5. {
  6. if(string.IsNullOrEmpty(area)||string.IsNullOrEmpty(controller))
  7. {
  8. throw new ArgumentNullException("area or controller can not be null");
  9. }
  10. var inlineConstraintResolver = routeBuilder
  11. .ServiceProvider
  12. .GetRequiredService<IInlineConstraintResolver>();
  13. string template = "";
  14. RouteValueDictionary defaults = new RouteValueDictionary();
  15. RouteValueDictionary constrains = new RouteValueDictionary();
  16. constrains.Add("area", area);
  17. defaults.Add("area", area);
  18. constrains.Add("controller", controller);
  19. defaults.Add("controller", string.IsNullOrEmpty(controller) ? "home" : controller);
  20. defaults.Add("action", "index");
  21. template += "{action}/{id?}";//路径规则中不再包含控制器信息,但是上面通过constrains限定了查找时所要求的控制器名称
  22. routeBuilder.Routes.Add(new SubDomainRouter(routeBuilder.DefaultHandler, domain, template, defaults, constrains, inlineConstraintResolver));
  23. return routeBuilder;
  24. }
  25. }</span>

使用方法:

  1. <span style="font-size:14px;">routes.MapDomainRoute("xxx.domain.com","areaname","controllername");</span>

以上代码为原博客中的代码,使用起来也很方便,只需要传值域名,区域名,控制器名,就可以实现我们想要的结果。下面我对以上代码稍作了修改,通过配置文件配置域名和控制器的绑定。新建一个关于域名、区域、控制器名的Model:

  1. <span style="font-size:14px;">/// 域名信息实体类
  2. /// <summary>
  3. /// 域名信息实体类
  4. /// </summary>
  5. public class SubDomain
  6. {
  7. /// 域名
  8. /// <summary>
  9. /// 域名
  10. /// </summary>
  11. public string Domain { get; set; }
  12. /// 区域名
  13. /// <summary>
  14. /// 区域名
  15. /// </summary>
  16. public string AreaName { get; set; }
  17. /// 控制器名
  18. /// <summary>
  19. /// 控制器名
  20. /// </summary>
  21. public string Controller { get; set; }
  22. }</span>

另外在MapDomainRoute扩展方法中,去掉了对区域的判断, 这样也可以配置非区域的控制器了,代码如下:

  1. <span style="font-size:14px;">public static IRouteBuilder MapDomainRoute(
  2. this IRouteBuilder routeBuilder, string domain, string area, string controller)
  3. {
  4. try
  5. {
  6. <span style="background-color:rgb(255,204,0);">if (string.IsNullOrEmpty(domain))
  7. {
  8. throw new ArgumentNullException("domain can not be null");
  9. }
  10. //string.IsNullOrEmpty(area) || //去掉该判断,不限制仅限区域使用配置
  11. if (string.IsNullOrEmpty(controller))
  12. {
  13. throw new ArgumentNullException("controller can not be null");
  14. }</span>
  15. var inlineConstraintResolver = routeBuilder
  16. .ServiceProvider
  17. .GetRequiredService<IInlineConstraintResolver>();
  18. string template = "";
  19. RouteValueDictionary defaults = new RouteValueDictionary();
  20. RouteValueDictionary constrains = new RouteValueDictionary();
  21. constrains.Add("area", area);
  22. defaults.Add("area", area);
  23. constrains.Add("controller", controller);
  24. defaults.Add("controller", string.IsNullOrEmpty(controller) ? "Home" : controller);
  25. defaults.Add("action", "index");
  26. template += "{action}/{id?}";//路径规则中不再包含控制器信息,但是上面通过constrains限定了查找时所要求的控制器名称
  27. routeBuilder.Routes.Add(new SubDomainRouter(routeBuilder.DefaultHandler, domain, template, defaults, constrains, inlineConstraintResolver));
  28. return routeBuilder;
  29. }
  30. catch (Exception ex)
  31. {
  32. throw ex;
  33. }
  34. }</span>

同时也添加了一个对该方法的重载:

  1. <span style="font-size:14px;">public static void MapDomainRoute(this IRouteBuilder routeBuilder, List<SubDomain> listDomains)
  2. {
  3. try
  4. {
  5. if (listDomains == null || listDomains.Count <= 0)
  6. {
  7. return;
  8. }
  9. foreach (SubDomain domain in listDomains)
  10. {
  11. MapDomainRoute(routeBuilder, domain.Domain, domain.AreaName, domain.Controller);
  12. }
  13. }
  14. catch (Exception ex)
  15. {
  16. throw ex;
  17. }
  18. }</span>

将域名路由信息配置到appsetting.json文件中,例如:

当然在.net core中可以直接从IConfiguration对象中可以直接获取到配置文件下的信息,但我也没找到可以直接序列化我为要的标准的Json格式,就使用了直接读取文件的方式,借助Json.Net,又反序列化成我要的实体信息List<SubDomain>,代码如下:

  1. <span style="font-size:14px;">//获取域名路由配置规则信息
  2. var jsonDomain = JObject.Parse(File.ReadAllText("appsettings.json"))["SubDomains"];
  3. if (jsonDomain != null)
  4. {
  5. var infos = JsonConvert.DeserializeObject<List<SubDomain>>(jsonDomain.ToString());
  6. routes.MapDomainRoute(infos);
  7. }</span>

这样也就可以直接通过配置文件去修改配置了,效果展示:

https://www.allenchoi.net

https://blog.allenchoi.net

https://admin.allenchoi.net

以上就实现了我们想要的结果。后面内容应该会涉及微服务内容了,我会结合微软的示例项目eShop,应用到自己的项目中。另外,微软官方出了一本电子书《.NET微服务:容器化.NET应用架构指南》,大家可以免费下载,下载地址:https://aka.ms/microservicesebook

原文中涉及到的博客地址(尊重原创):http://www.cnblogs.com/dxp909/p/6994354.html

扫描二维码关注我的公众号,共同学习,共同进步!

.Net Core 二级域名绑定到指定的控制器的更多相关文章

  1. asp.net core mvc中如何把二级域名绑定到特定的控制器上

    由于公司的工作安排,一直在研究其他技术,所以一直没时间更新博客,今天终于可以停下手头的事情,写一些新内容了. 应用场景:企业门户网站会根据内容不同,设置不同的板块,如新浪有体育,娱乐频道,等等.有的情 ...

  2. linux下关于Apache设置二级域名绑定二级目录的方法

    背景:对于一些论坛网站,某些目录需要制定二级域名去访问,这时候就要在apache中用二级域名绑定二级目录. 方法: 1.首先你要找到apache安装路径,在apahce安装路径下的conf文件夹中找到 ...

  3. Linux虚拟主机通过程序实现二级域名绑定到子目录

    虚拟主机中CP控制台不支持将二级域名绑定到子目录的功能,用户可以通过程序实现将二级域名绑定到子目录. 有两种方法将二级域名绑定到子目录: 1. 配置.htaccess, 通过伪静态代码实现.具体实现方 ...

  4. 阿里云Centos中二级域名绑定二级目录的方法

    对于一些目录,我们往往需要对其指定二级域名,那么具体如何操作呢?下面,我将用亲身实践来说明一下. 由于第一次接触centos,我不得不借助于网络资源.然后得知要开启mod_rewrite这个模块,具体 ...

  5. 为阿里云ECS服务器二级域名绑定tomcat子目录,实现一个IP多个二级域名

    摘要:前几天租了阿里云ECS服务器,选择的Windows系统,并在服务器上部署了tomcat服务器,随后我又买了一个域名,可一个域名只能指向一个IP地址,包括二级域名也只能指向一个IP地址,并不能指向 ...

  6. 二级域名绑定ECS

    关于阿里云域名的绑定,下面是个人的理解,如有错误请指出. 首先,任何域名都需要在阿里云备案后才可以使用, 如果是二级域名,不能单独备案,需要其顶级域名在阿里云备案. http://help.aliyu ...

  7. thinkphp 二级域名绑定模块,导致设置的路由被多域名共用的问题解决方案

    问题背景: 在router.php路由配置文件设置了二级域名和路由设置 use think\Route; Route::domain('www','index'); Route::domain('ad ...

  8. .htaccess 文件 访问二级域名 对应的 指定文件夹

    <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / # 绑定m.xxx.cc 到子目录m RewriteCond %{HTTP_ ...

  9. aliyun二级域名绑定

    NameVirtualHost *:80 开启监听 <VirtualHost *:80>    DocumentRoot /home/service/    ServerName serv ...

随机推荐

  1. Upsource——对已签入的代码进行分享、讨论和审查代码

    Upsource 一.Upsource简介 Upsource ,这是一个专门为软件开发团队所设计的源代码协作工具.Upsource能够与多种版本控制工具进行集成,包括Git.Mercurial.Sub ...

  2. 怎么解决tomcat占用8080端口问题图文教程

     怎么解决tomcat占用8080端口问题 相信很多朋友都遇到过这样的问题吧,tomcat死机了,重启eclipse之后,发现 Several ports (8080, 8009) required ...

  3. Subime3 快捷键

    实用快捷键 Ctrl+Shift+P:打开命令面板Ctrl+P:搜索项目中的文件Ctrl+G:跳转到第几行Ctrl+W:关闭当前打开文件Ctrl+Shift+W:关闭所有打开文件Ctrl+Shift+ ...

  4. MySQL临时表的简单用法(复制)

      当工作在非常大的表上时,你可能偶尔需要运行很多查询获得一个大量数据的小的子集,不是对整个表运行这些查询,而是让MySQL每次找出所需的少数记录,将记录选择到一个临时表可能更快些,然后在这些表运行查 ...

  5. 150. Evaluate Reverse Polish Notation(逆波兰表达式)

    Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are +, -, ...

  6. 【android】通过leakCanary找出程序内存泄露点

    背景 内存泄露是咱新手比较头痛的问题,因为它不像崩溃,在开发环境可以根据提示的错误信息排查问题. 你都不知道咱的app是否哪个犄角旮旯藏着一个吞噬内存的黑洞. 排查android 内存泄露比较底层高端 ...

  7. java.lang.ClassFormatError: Trjava.lang.ClassFormatError: Truncated class fileuncated class file

    周末过来加班,上传编译好的文件后,部署到服务器没事.但是服务器日志满了,把日志清除后,把服务启动,发现报这个错误,大致网上看了一下,这个错误是编译的文件损坏了.然后大致看了一下文件,还真是.由于日志满 ...

  8. 播放48KHZ有1S的停顿

    两个音频文件: /usr/lib/gstreamer-0.10/libgstflump3dec.so /usr/lib/gstreamer-0.10/libgstflumpegdemux.so

  9. PHP秒杀系统全方位设计分析(二)

    商品页面开发 静态化展示页面[效率要比动态PHP高很多,PHP程序需要解析等步骤,本身就需要很多流程,整个下来PHP的处理花的时间和资源要多] 商品状态的控制 开始前.进行中.库存不足.结束 数据逻辑 ...

  10. 20145211《网络渗透》msf辅助模块的应用

    20145211<网络渗透>msf辅助模块的应用 一.实验准备 启用VB的kali,需要用到桥接,VMware桥接总是罢工…… 二.实验步骤 最好开桥接模式,要不然你就多开几个虚拟机(只要 ...