写了个扩展,分享给需要的朋友。

0x01 使用方法

在mvc区域中的{xxxx}AreaRegistration.cs文件中,如ProjectsAreaRegistration.cs

<pre>

<code>

using Dsvisual.Extensions;

namespace Dsvisual.WebApp.Areas.Projects
{
    public class ProjectsAreaRegistration : AreaRegistration
    {
        public override string AreaName
        {
            get
            {
                return "Projects";
            }
        }

public override void RegisterArea(AreaRegistrationContext context)
        {
            context.MapSubdomain("projects", true);
        }
    }
}

</code>

</pre>

0x02 扩展功能源码

<pre><code>

/// <summary>
    /// an extension for map subdomain request to a mvc area
    /// </summary>
    public static class RouteExtension
    {
        /// <summary>
        /// 创建该区域(Area)的路由并将子域名(subdomain)的请求映射到该区域
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="subdomain">子域名</param>
        /// <param name="allowShortUrl">是否启用短地址(当请求地址位于默认控制器时支持控制器路径省略)</param>
        public static void MapSubdomain(this AreaRegistrationContext ctx, string subdomain, bool allowShortUrl)
        {
            ctx.Routes.MapSubdomain(subdomain, ctx.AreaName, ctx.Namespaces.ToArray(), allowShortUrl);
        }

/// <summary>
        /// 映射子域名到对应的区域
        /// map the subdomain requests to the specific mvc Area
        /// </summary>
        /// <param name="routes"></param>
        /// <param name="subdomain">子域名,支持多级 如admin.info.domain.com 则子域名为admin.info</param>
        /// <param name="areaName">MVC Area名称</param>
        /// <param name="namespaces">MVC Area所在的命名空间</param>
        /// <param name="allowShortUrl">是否启用短地址(当请求地址位于默认控制器时支持控制器路径省略)</param>
        private static void MapSubdomain(this RouteCollection routes, string subdomain, string areaName, string[] namespaces, bool allowShortUrl)
        {
            var prefix = areaName + "_";
            var defaults = new { controller = "home", action = "index", id = UrlParameter.Optional };

bool flag = namespaces == null || namespaces.Length == 0;
            var dataTokens = new { area = areaName, Namespaces = namespaces, UseNamespaceFallback = flag };

object constraints = null;

//通过配置两个路由来映射短路由和标准路由
            //这里URL不带路由前缀目的是避免映射为二级域名后Html.ActionLink等输出路由前缀
            //因为MVC区域默认是Projects/{controller}/{action}/{id}这样的格式,
            //这样会导致Html.ActionLink等生成project.domain.com/project/home/index这样的路径
            //而我们需要的是project.domain.com/home/index这样的格式
            if (allowShortUrl)
            {

//短路径输出支持路由默认控制器设置和当前调用的控制器相同的情况
                //比如默认值设置为{controller="home",action="index"}
                //当请求地址为projects.domain.com/details?id=5这样的地址时
                //短路径可以将该请求解析到projects区域下HomeController的Details动作上
                var shortUrl = new Route("{action}/{id}", new RouteValueDictionary(defaults), new RouteValueDictionary(constraints), new RouteValueDictionary(dataTokens), new MvcRouteHandler());
                var shortUrlLocal = new Route(areaName + "/{action}/{id}", new RouteValueDictionary(defaults), new RouteValueDictionary(constraints), new RouteValueDictionary(dataTokens), new MvcRouteHandler());
                var shortUrlRoute = new SubdomainRoute(subdomain, areaName, shortUrl, shortUrlLocal);
                routes.Add(prefix + "shortUrl", shortUrlRoute);
            }

var standard = new Route("{controller}/{action}/{id}", new RouteValueDictionary(defaults), new RouteValueDictionary(constraints), new RouteValueDictionary(dataTokens), new MvcRouteHandler());
            var standardLocal = new Route(areaName + "/{controller}/{action}/{id}", new RouteValueDictionary(defaults), new RouteValueDictionary(constraints), new RouteValueDictionary(dataTokens), new MvcRouteHandler());
            var standardRoute = new SubdomainRoute(subdomain, areaName, standard, standardLocal);
            routes.Add(prefix + "standard", standardRoute);
        }

/// <summary>
        /// 子域名路由到Area
        /// </summary>
        internal class SubdomainRoute : Route
        {
            public Route LocalRoute { get; private set; }
            public string LowercasedSubdomain { get; private set; }
            public string LowercasedAreaName { get; set; }
            public SubdomainRoute(string subdomain, string areaName, Route targetRoute, Route localRoute)
                : base(targetRoute.Url, targetRoute.Defaults, targetRoute.Constraints, targetRoute.DataTokens, targetRoute.RouteHandler)
            {
                this.LocalRoute = localRoute;
                this.LowercasedSubdomain = subdomain.ToLowerInvariant();
                this.LowercasedAreaName = areaName.ToLowerInvariant();
                //在缺失controller的默认值设定中补充一个controller默认值,否则MvcStandardRoute获取不到路由数据
                if (!this.Defaults.ContainsKey("controller"))
                {
                    this.Defaults["controller"] = "home";
                }
            }

public override RouteData GetRouteData(HttpContextBase httpContext)
            {
                //对于通过localhost或127.0.0.1访问的,SubdomainRoute相当于无效状态
                if (httpContext.Request.IsLocal && httpContext.Request.Url.IsLoopback)
                {
                    return LocalRoute == null ? null : LocalRoute.GetRouteData(httpContext);
                }
                var host = httpContext.Request.Url.Host.ToLowerInvariant();
                if (host.StartsWith(LowercasedSubdomain))
                {
                    var rest = host.Substring(LowercasedSubdomain.Length, host.Length - LowercasedSubdomain.Length);
                    if (rest.Count(x => x == '.') == 2)
                    {
                        var data = base.GetRouteData(httpContext);
                        //if (data == null)
                        //{
                        //    data = new RouteData(this, this.RouteHandler);
                        //    if (Defaults != null)
                        //    {
                        //        foreach (KeyValuePair<string, object> item in Defaults) //controller action index
                        //        {
                        //            if (!data.Values.ContainsKey(item.Key))
                        //                data.Values[item.Key] = item.Value;
                        //        }
                        //    }
                        //    if (DataTokens != null)
                        //    {
                        //        foreach (var item in DataTokens) //Namespaces,area,UseNamespaceFallback
                        //        {
                        //            if (!data.DataTokens.ContainsKey(item.Key))
                        //                data.DataTokens[item.Key] = item.Value;
                        //        }
                        //    }
                        //}
                        //data.DataTokens["area"] = this.LowercasedAreaName;
                        return data;
                    }
                }
                return null;
            }

public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
            {
                if (requestContext.HttpContext.Request.IsLocal && requestContext.HttpContext.Request.Url.IsLoopback)
                {
                    return LocalRoute == null ? null : LocalRoute.GetVirtualPath(requestContext, values);
                }
                var virturalPathData = base.GetVirtualPath(requestContext, values);
                return virturalPathData;
            }
        }
    }

</code></pre>

将子域名请求路由到MVC区域的更多相关文章

  1. mvc路由,mvc区域

    1.路由在进行匹配时,会默认匹配第一个路由信息 2.路由规则的{control}和{action}时不能改变的 3.路由规则可以中间字符可以随便定义,但是{control}和{action}必须使用一 ...

  2. 浅谈ThinkPHP3.2的子域名部署和路由优化(一)

    前言:建立一个网站系统,往往包含多个子网站,例如PC官网,移动端官网,后台管理,数据源自一个相同的数据库,整个架构上,从ThinkPHP来看,可以大体理解为Model(M)是一样的,Controlle ...

  3. .NET MVC 获取 当前请求的 控制器/视图/区域 的名字

    .NET MVC 在action中或过滤器中或视图中,分别如何获取  当前请求的  控制器/视图/区域  的名字 1)过滤器中的: public class CMSAttribute : Filter ...

  4. Flask02 路由的书写、蓝图、利用蓝图实现url前缀、利用蓝图实现子域名、访问静态文件

    1 书写路由的两种方法 1.1 利用Flask实例对象的 add_url_rule 方法实现 该方法有一个必填参数,两个默认参数 · rule : 请求路径的规则 endpoint : 端点,默认值是 ...

  5. MVC教程:MVC区域路由

    一.区域路由 为了管理网站中大量的文件,在ASP.NET MVC 2.0版本中引入了一个新概念:区域(Area). 有了区域以后,可以让我们的项目不至于太复杂而导致管理混乱.每个模块的页面都放入相应的 ...

  6. Laravel 5 中间件、路由群组、子域名路由、 权限控制的基本使用方法

    创建控制器: php artisan make:controller Admin/IndexController 创建Middleware: php artisan make:middleware T ...

  7. Laravel之路由 Route::get/post/any、路由参数、过滤器、命名、子域名、前缀、与模型绑定、抛出 404 错误、控制器

    基本路由 应用中的大多数路都会定义在 app/routes.php 文件中.最简单的Laravel路由由URI和闭包回调函数组成. 基本 GET 路由 代码如下: Route::get('/', fu ...

  8. MVC区域使用

    新建项目 Main: 添加一个MVC5控制器并添加index视图:(HomeController) Views/Home/Index.cshtml内容: @{ Layout = null; } < ...

  9. MVC区域小结

    MVC区域小结 MVC区域小结 MVC3一直在学习,项目中有的时候也会用到,博客园也一直逛,想写点什么东西,可惜我这个人平时都很懒,理论层面的东西自己写不来,还是来点实际的简单入门的博客,对自己总结能 ...

随机推荐

  1. php基础语法(20161021)

    上午: 数据库总结: 1.创建数据库 create database 数据库名称 删除数据库 drop database 数据库名称 2.创建表 create table 表名 ( 列名 类型(长度) ...

  2. Eclipse使用Maven创建Web项目+整合SSM框架

    一.准备环境: maven:apache-maven-3.2.3 jdk:jdk1.8.0_25 tomcat:tomcat-9.0 二.配置Maven.jdk 1.Window——>Prefe ...

  3. 深入浅出数据结构C语言版(5)——链表的操作

    上一次我们从什么是表一直讲到了链表该怎么实现的想法上:http://www.cnblogs.com/mm93/p/6574912.html 而这一次我们就要实现所说的承诺,即实现链表应有的操作(至于游 ...

  4. sqrt()平方根计算函数的实现2——牛顿迭代法

    牛顿迭代法: 牛顿迭代法又称为牛顿-拉夫逊方法,它是牛顿在17世纪提出的一种在实数域和复数域上近似求解方程的方法.多数方程不存在求根公式,因此求精确根非常困难,甚至不可能,从而寻找方程的近似根就显得特 ...

  5. 【Python系列】Python自动发邮件脚本-html邮件内容

    缘起 这段时间给朋友搞了个群发邮件的脚本,为了防止进入垃圾邮件,做了很多工作,刚搞完,垃圾邮件进入率50%,觉得还不错,如果要将垃圾邮件的进入率再调低,估计就要花钱买主机了,想想也就算了,先发一个月, ...

  6. 解决Highcharts 5.0.7,IE8下bar类型图表无法显示的问题

    引用如上, 当图标类型为bar时,IE8无法直接显示, 官网也一样, 但通过切换图例可以显示, 所以加入以下代码解决此问题 未经允许,严禁转载!!!

  7. jquery-base64.js插件使用

    官方文档地址:https://github.com/yckart/jquery.base64.js var a="123"; var b=$.base64.btoa(a); con ...

  8. Truncated incorrect DOUBLE value错误

    mysql报错:Truncated incorrect DOUBLE value sql的update语法错误eg: update Person set name = 'auhnayuiL' and ...

  9. 树莓派Raspberry实践笔记-简单方法安装minicom

    [原创链接]:http://www.cnblogs.com/atsats/p/6665566.html 本文结合最新的Raspbain jessie,使用图形化的方式安装一款软件:串口调试工具mini ...

  10. QQ第三方登录教程

    教程戳这里