自从微软发布 ASP.NET MVC 和routing engine (System.Web.Routing)以来,就设法让我们明白你完全能控制URL和routing,只要与你的application path相结合进行扩展,任何问题都迎刃而解。如果你需要在所处的域或者子域处理数据标记的话,强制使用Default。

遗憾的是,ASP.NET MVC是基于虚拟目录的,在实际项目却有各种各样的需求方案。

例如:

1:应用程序是多语言的,像cn.example.com应该被匹配到“www.{language}example.com”路由上。

2:应用程序是多用户的,像username.example.com应该被匹配到“www.{clientname}.example.com”路由上。

3:应用程序是多子域的,像mobile.example.com应该被匹配到"www.{controller}.example.com/{action}....” 。

坐下来,深呼吸,开始我们ASP.NET MVC的神奇之旅吧。

定义routes

下面是我们定义简单的route,不带任何controller控制的route:

routes.Add("DomainRoute", new DomainRoute( 
"home.example.com", // Domain with parameters
"{action}/{id}",    // URL with parameters
new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
));

另一个例子是用我们的controller控制域名:

Code

打算用controller 和action完全控制域名?

routes.Add("DomainRoute", new DomainRoute( 
"{controller}-{action}.example.com",     // Domain with parameters
"{id}",    // URL with parameters
new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
));

接下来是多语言route:

routes.Add("DomainRoute", new DomainRoute( 
"{language}.example.com",     // Domain with parameters
"{controller}/{action}/{id}",    // URL with parameters
new { language = "en", controller = "Home", action = "Index", id = "" }  // Parameter defaults
));

HtmlHelper 扩展方法

因为我们不希望所有的URL所产生HtmlHelper ActionLink要使用full URLs,第一件事我们会添加一些新的ActionLink,其中载有boolean flag是否要full URLs或没有。利用这些,现在您可以添加一个链接到一个Action如下:

<%= Html.ActionLink("About", "About", "Home", true)%>

跟你以往的习惯没有什么不同,不是吗?
以下是一小段代码:

public static class LinkExtensions 

public static string ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, bool requireAbsoluteUrl) 
    { 
return htmlHelper.ActionLink(linkText, actionName, controllerName, new RouteValueDictionary(), new RouteValueDictionary(), requireAbsoluteUrl); 
    }  // more of these  public static string ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes, bool requireAbsoluteUrl) 
    { 
if (requireAbsoluteUrl) 
        { 
            HttpContextBase currentContext = new HttpContextWrapper(HttpContext.Current); 
            RouteData routeData = RouteTable.Routes.GetRouteData(currentContext);              routeData.Values["controller"] = controllerName; 
            routeData.Values["action"] = actionName;              DomainRoute domainRoute = routeData.Route as DomainRoute; 
if (domainRoute != null) 
            { 
                DomainData domainData = domainRoute.GetDomainData(new RequestContext(currentContext, routeData), routeData.Values); 
return htmlHelper.ActionLink(linkText, actionName, controllerName, domainData.Protocol, domainData.HostName, domainData.Fragment, routeData.Values, null); 
            } 
        } 
return htmlHelper.ActionLink(linkText, actionName, controllerName, routeValues, htmlAttributes); 
    } 
}

在这没什么特别的:有许多的扩展方法,把扩展的URL加到域名上。这是一个预设ActionLink helpers,我的精神食粮来了DomainRoute class(详见:Dark Magic)

Dark magic

瞥眼之间,您可能已经看到了我的DomainRoute类代码段。这个类实际上是提取子域,并增加了象征性支持域部分的传入的URL,

我们将扩展基类,它已经给了我们一些属性和方法,但是我们得重写他们!

public class DomainRoute : Route 
{  
//   public string Domain { get; set; }  //   public override RouteData GetRouteData(HttpContextBase httpContext) 
    { 
// 构造regex
        domainRegex = CreateRegex(Domain); 
        pathRegex = CreateRegex(Url);  // 请求信息
string requestDomain = httpContext.Request.Headers["host"]; 
if (!string.IsNullOrEmpty(requestDomain)) 
        { 
if (requestDomain.IndexOf(":") > 0) 
            { 
                requestDomain = requestDomain.Substring(0, requestDomain.IndexOf(":")); 
            } 
        } 
else
        { 
            requestDomain = httpContext.Request.Url.Host; 
        } 
string requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;  //匹配域名和路由         Match domainMatch = domainRegex.Match(requestDomain); 
        Match pathMatch = pathRegex.Match(requestPath); // Route 数据         RouteData data = null; 
if (domainMatch.Success && pathMatch.Success) 
        { 
            data = new RouteData(this, RouteHandler); // 添加默认选项
if (Defaults != null) 
            { 
foreach (KeyValuePair<string, object> item in Defaults) 
                { 
                    data.Values[item.Key] = item.Value; 
                } 
            }  // 匹配域名路由
for (int i = 1; i < domainMatch.Groups.Count; i++) 
            { 
                Group group = domainMatch.Groups[i]; 
if (group.Success) 
                { 
string key = domainRegex.GroupNameFromNumber(i); 
if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, 0)) 
                    { 
if (!string.IsNullOrEmpty(group.Value)) 
                        { 
                            data.Values[key] = group.Value; 
                        } 
                    } 
                } 
            }  // 匹配域名路径
for (int i = 1; i < pathMatch.Groups.Count; i++) 
            { 
                Group group = pathMatch.Groups[i]; 
if (group.Success) 
                { 
string key = pathRegex.GroupNameFromNumber(i); 
if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, 0)) 
                    { 
if (!string.IsNullOrEmpty(group.Value)) 
                        { 
                            data.Values[key] = group.Value; 
                        } 
                    } 
                } 
            } 
        }  return data; 
    }  public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) 
    { 
return base.GetVirtualPath(requestContext, RemoveDomainTokens(values)); 
    }  public DomainData GetDomainData(RequestContext requestContext, RouteValueDictionary values) 
    { 
// 获得主机名 string hostname = Domain; 
foreach (KeyValuePair<string, object> pair in values) 
        { 
            hostname = hostname.Replace("{" + pair.Key + "}", pair.Value.ToString()); 
        } // Return 域名数据 return new DomainData 
        { 
            Protocol = "http", 
            HostName = hostname, 
            Fragment = ""
        }; 
    } // 
}

哇,这是一串按照我们定义的route转换传入请求的URL到tokens的代码,我们这样做是转换{controller}和按照regex然后再尝试匹配route规则,在我们的DomainRoute class里还有其他的helper方法,需要更多的功能可以自己研究扩展。

附代码:附件

ASP.NET MVC 实现二级域名的更多相关文章

  1. Asp.Net Mvc Area二级域名

    参考:https://blog.maartenballiauw.be/post/2009/05/20/aspnet-mvc-domain-routing.html 参考:https://www.cnb ...

  2. 实现asp.net mvc页面二级缓存,提高访问性能

    实现的mvc二级缓存的类 //Asp.Net MVC视图页面二级缓存 public class TwoLevelViewCache : IViewLocationCache { private rea ...

  3. MVC利用Routing实现多域名绑定一个站点、二级域名以及二级域名注册Area

    最近有这么个需求:在一个站点上绑定多个域名,每个域名进去后都要进入不同的页面.实现了这个功能以后,对于有多个域名,且有虚拟空间,但是虚拟空间却只匹配有一个站点的用户来说,可以节省很多小钱钱. 很久以前 ...

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

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

  5. asp.net MVC把Areas区域绑定成二级域名

    先分析需求 在MVC项目中,我们如果有两个Areas.比如Test和DEMO.我们的访问地址应该是 http://localhost:8098/test http://localhost:8098/d ...

  6. MVC实现动态二级域名

    前段时间,一个朋友问我ASP.NET MVC下实现动态二级域名的问题.跟他聊了一些解决方案,这里也总结一下,以供参考. 相信大家都发现类似58同城这样的网站,成都的网址是cd.58.com 上海的是s ...

  7. ASP.NET MVC 3 技术(九) 301永久重定向不带www域名到带www的域名

    在 .net 4 中实现永久重定向非常容易,可以参考ASP.NET MVC3 技术(四) 永久重定向方法.今天主要说明下怎么在 asp.net mvc 3 实现从带www的域名永久重定向到不带www的 ...

  8. ASP.NET二级域名站点共享Session状态

    我的前面一篇文章提到了如何在使用了ASP.NET form authentication的二级站点之间共享登陆状态, http://www.cnblogs.com/jzywh/archive/2007 ...

  9. asp.net 配置二级域名的共享session,并实现sso单点登录

    公司最近做了一个新网站.原先网站的网址是www.xxxx.com.新做的网站要部署到info.xxxx.com.这两个网站要实现单点登录.而新老网站本身机构的原因,对于登录状态的判断,说白了就是对于s ...

随机推荐

  1. Appium下Android keyevent整理

    keycode 3:首页(Home key) keycode 4:返回键(Back key) keycode 5:电话键(Call key) keycode 6:结束通话键(End Call key) ...

  2. POJ 1325

    #include<iostream> #include<stdio.h> #define MAXN 105 using namespace std; int _m[MAXN][ ...

  3. sematext

    https://sematext.atlassian.net/wiki/display/PUBLOGSENE/Syslog

  4. spring mvc 基于注解的使用总结

    本文转自http://blog.csdn.net/lufeng20/article/details/7598801 概述 继 Spring 2.0 对 Spring MVC 进行重大升级后,Sprin ...

  5. HtmlAgilityPack 之 HtmlNode类

    HtmlAgilityPack中的HtmlNode类与XmlNode类差不多,提供的功能也大同小异.下面来看看该类提供功能. 一.静态属性 public static Dictionary<st ...

  6. VS2010中打开VS2013/VS2012项目

    VS2010中打开VS2013/VS2012项目 (2014-04-03 23:47:53) 转载▼   分类: IT VS低版本打开高版本创建的项目时会提示"选择的文件是解决方案文件,但是 ...

  7. lintcode:打劫房屋

    题目 打劫房屋 假设你是一个专业的窃贼,准备沿着一条街打劫房屋.每个房子都存放着特定金额的钱.你面临的唯一约束条件是:相邻的房子装着相互联系的防盗系统,且 当相邻的两个房子同一天被打劫时,该系统会自动 ...

  8. 多页面打印--web print

    背景:项目中要求做在一个页面中通过选择网址来打印多个页面的内容的功能 原理:通过iframe把各网址的页面内容加载进来,通过iframe.contentWindow拿到iframe的window对象, ...

  9. JavaWeb项目开发案例精粹-第4章博客网站系统-002辅助类及配置文件

    1. <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5&qu ...

  10. Spring笔记——Spring+JDBC组合开发

      使用Spring+JDBC集成步骤如下:   1. 配置数据源 2. 配置事务.配置事务时,需要在xml配置文件中引入用于声明事务的tx命名空间,事务的配置方式有两种:注解方式和基于XML配置方式 ...