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

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. MySQL基准测试(benchmark)

    基准测试是唯一方便有效的.可以学习系统在给定的工作负载下会发生什么的方法.基准测试可以观察系统在不同压力下的行为,评估系统的容量,掌握哪些是重要的变化,或者观察系统如何处理不同的数据. 验证基于系统的 ...

  2. 【Troubleshooting Case】Unable to delete Exchange database?

    在我们日常邮件系统运维管理或实施部署变更中,经常会遇到,删除Exchange 数据库DB时,提示无法删除. ------------------– Microsoft Exchange Error - ...

  3. 关于Tarjan(1)

    众所周知, 求有向图的强连通分量的Tarjan算法是以其发明者Robert Tarjan命名的.Robert Tarjan还发明了求双连通分量的Tarjan算法,以及求最近公共祖先(LCA)的离线Ta ...

  4. Windows Phone下页面跳转动画的实现

    写在前面的一些废话: 前段时间一直忙于其他的事情,好长时间没有更新博客,很多东西虽然看过.学过,但是没有仔细去思考,去总结,长时间不用或者用的少难免会遗忘.最近由于家里以及感情方面的事,人也变得有点怨 ...

  5. java学习笔记----运算符

    一.算数运算符 特别说明: 加 ,减 ,乘 ,除 与数学运算一致 取余符号看被除数 自加(减)运算:++a,--a;先做自加(自减)运算在做其他运算 a++,a--;先做其他运算在做自加(自减)运算 ...

  6. spring(一) IOC讲解

    spring基本就两个核心内容,IOC和AOP.把这两个学会了基本上就会用了. --WH 一.什么是IOC? IOC:控制反转,通俗点讲,将对象的创建权交给spring,我们需要new对象,则由spr ...

  7. CoreCLR源码探索(五) GC内存收集器的内部实现 调试篇

    在上一篇中我分析了CoreCLR中GC的内部处理, 在这一篇我将使用LLDB实际跟踪CoreCLR中GC,关于如何使用LLDB调试CoreCLR的介绍可以看: 微软官方的文档,地址 我在第3篇中的介绍 ...

  8. ajax 原理----初级篇

    一.贴dome,ajax三大步 <!DOCTYPE html> <html lang="en"> <head> <meta charset ...

  9. jenkins+SVN配置

    开发项目,版本控制必不可少,我用的版本控制软件为SVN,那么如何把jenkins和SVN结合,使得SVN源码一有上传更新,jenkins就马上构建项目呢?下面说一下配置过程   1)         ...

  10. 关于oracle后导数据的一些小TIPS

    今天下午需要把一些数据导入到正式环境中,但是通过Excel拷贝进去行会错位,把excel的每一列的双击让其变为最宽即可解决该问题