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

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. js动态加载的蒙板弹框

    我们访问一些网站时总会遇到这种点击后,背景像被打上一层模板一样,这个是怎么做到的呢? 它是将这个弹框div独立于页面容器wrap,设置position为absolute,将其水平垂直之后都居中,设置弹 ...

  2. jump堡垒机配置使用

    一.用户管理 1)添加用户 点击用户管理 —> 查看用户 —> 添加用户 输入要添加的用户名,姓名,权限,Mail,并且发送邮件 —> 保存 查看添加的用户 查看用户邮件 邮件中包含 ...

  3. 一个web应用的诞生(8)--博文发布

    这个系统一直号称轻博客,但貌似博客的功能还没有实现,这一章将简单的实现一个博客功能,首先,当然是为数据库创建一个博文表(models\post.py): from .. import db from ...

  4. C#全局鼠标键盘Hook

    原文出自:http://www.cnblogs.com/iEgrhn/archive/2008/02/17/1071392.html using System; using System.Collec ...

  5. spring-mvc-两个个小例子

    1.用Eclipse创建一个工程,命名为spring2.0 并添加相应的jar包(我用的是4.0.5的版本)到 lib 包下: spring-webmvc-4.0.5.RELEASE.jar spri ...

  6. Android中的Drawable和动画

    Android中Drawable是一种可以在Canvas上进行绘制抽象的概念,种类很多,常见的颜色和图片都可以是一个Drawable.Drawable有很多种,它们表示一种图像的概念,但是它们又不全是 ...

  7. 读书笔记 effective c++ Item 37 永远不要重新定义继承而来的函数默认参数值

    从一开始就让我们简化这次的讨论.你有两类你能够继承的函数:虚函数和非虚函数.然而,重新定义一个非虚函数总是错误的(Item 36),所以我们可以安全的把这个条款的讨论限定在继承带默认参数值的虚函数上. ...

  8. 在docker container中运行docker-compose

    为了保持宿主主机的环境干净,因此将docker-compose安装到一个基于centos7.3的容器之中,因为tianchao屏蔽了amazonaws,最后选择了通过pip方式来安装,这也是官方推荐的 ...

  9. 苹果App删除 AppStore应用删除指南

    最近做IOS应用上传时,想改一下SUK或者Bundle ID ,发现改不了,只能删除. 但是删除却没有找到删除按钮,百度半天不给力,不过后来多亏一位群里的兄弟给找个链接,终于解决 今天就给他记录下来, ...

  10. 反射实现 Data To Model

    调用 : public ActionResult Index() { DataTable dt = new DataTable(); dt.Columns.Add("Name"); ...