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

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. 获取bing图片并自动设置为电脑桌面背景(C++完整开源程序)

    众所周知,bing搜索网站首页每日会更新一张图片,张张漂亮(额,也有一些不合我口味的),特别适合用来做电脑壁纸. 我们想要将bing网站背景图片设置为电脑桌面背景的通常做法是: 上网,搜索bing 找 ...

  2. 《Django By Example》第九章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者@ucag 注:哈哈哈,第九章终于来啦 ...

  3. Qt下实现简单的UDP通信

    本人呢还是小实习生一枚,刚一脚踏进社会大母亲的怀抱,不想找工作的时候碰到的全是培训机构... 不过还是幸运的进了一家...咳咳,国企?!好吧,其实是国企下面的一个分出来的小公司(正在起步中,算是创业公 ...

  4. UNIX 网络编程知识,函数积累

    1: fprintf()#include <stdio.h> int fprintf( FILE *stream, const char *format, ... );fprintf()函 ...

  5. 使用 @Qualifier 注释和 @Autowired 注释通过指定哪一个真正的 bean 将会被装配来消除混乱

    1.当你创建多个具有相同类型的 bean 时,并且想要用一个属性只为它们其中的某一个进行装配,在这种情况下,你可以使用 @Qualifier 注释和 @Autowired 注释来精确配置. 2.示例 ...

  6. mysql数据库开启慢查询日志

    修改配置文件 在配置文件my.ini中加上下面两句话 log-slow-queries = C:\xampp\mysql_slow_query.log long_query_time=3 第一句使用来 ...

  7. android 关于表格布局的认识

    表格布局(TableLayout) 使用的知识点有: 控件 TableRow:为这个表格添加一行 table的特殊属性 android:layout_column:确定此表格的列数 android:s ...

  8. 菜鸟Scrum敏捷实践系列(一)用户故事概念

    菜鸟Scrum敏捷实践系列索引 菜鸟Scrum敏捷实践系列(一)用户故事概念 菜鸟Scrum敏捷实践系列(二)用户故事验收 菜鸟Scrum敏捷实践系列(三)用户故事的组织---功能架构的规划 敏捷开发 ...

  9. 获取 metadata 的完整例子 - 每天5分钟玩转 OpenStack(166)

    我们将通过实验详细分析 instance 从 nova-api-metadata 获取信息的完整过程. 环境介绍 1. 一个 all-in-one 环境(多节点类似). 2. 已创建 neutron ...

  10. 这是对position讲解最通俗易懂的版本了。

    position 为了制作更多复杂的布局,我们需要讨论下 position 属性.它有一大堆的值,名字还都特抽象,别提有多难记了.让我们先一个个的过一遍,不过你最好还是把这页放到书签里. static ...