好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

ASP.NET MVC动态二级域名及ASP.NET管道机制

ASP.NET MVC动态二级域名及ASP.NET管道机制

ASP.NET MVC动态二级域名及ASP.NET管道机制 动态二级域名的实现:

应用场景:目前产品要实现SaaS功能,因为工作需要实现二级域名: www.{CompanyUrl}.xxx.com

假设产品主域名入口为: www.xxx.com

当a公司租户登录时: www.a.xxx.com

当b公司租户登录时:  www.b.xxx.com

首先想到的是对Url的重写:(网上有关于UrlRewrite的实现。在ASP.NET中这也是常用的手法。)

Route简介:ASP.NET路由可以不用映射到网站特定文件的URL.由于该 URL 不必映射到文件,因此可以使用对用户操作进行描述因而更易于被用户理解的 URL。.NET Framework 3.5 SP1已经包含了ASP.NET Routing引擎。现在微软已经在ASP.NET WebForms 4.0中增加了对Routing引擎更好的支持,它使用表达式构造器进行双向Routing。

MVC 应用程序中的典型 URL 模式——来自MSDN

MVC 应用程序中用于路由的 URL 模式通常包括 {controller} 和 {action} 占位符。

当收到请求时,会将其路由到  UrlRoutingModule  对象,然后路由到  MvcHandler  HTTP 处理程序。  MvcHandler  HTTP 处理程序通过向 URL 中的控制器值添加后缀“Controller”以确定将处理请求的控制器的类型名称,来确定要调用的控制器。URL 中的操作值确定要调用的操作方法。

MVC项目中添加路由,Global.asax 文件默认的MVC 路由的代码。

默认配置:

View Code

 1           public   static   void   RegisterRoutes(RouteCollection routes)
   2           {
   3              routes.IgnoreRoute( "  {resource}.axd/{*pathInfo}  "  );
   4  
  5               routes.MapRoute(
   6                   "  Default  " ,  //   Route name 
  7                   "  {controller}/{action}/{id}  " ,  //   URL with parameters 
  8                   new  { controller =  "  Home  " , action =  "  Index  " , id = UrlParameter.Optional }  //   Parameter defaults 
  9               );
  10  
 11           }
  12           protected   void   Application_Start()
  13           {
  14               AreaRegistration.RegisterAllAreas();
  15  
 16               RegisterGlobalFilters(GlobalFilters.Filters);
  17               RegisterRoutes(RouteTable.Routes);
  18          }

涉及类参考

类 说明 Route 表示 Web 窗体或 MVC 应用程序中的路由。 RouteBase 用作表示 ASP.NET 路由的所有类的基类。 RouteTable 存储应用程序的路由。 RouteData 包含所请求路由的值。 RequestContext 包含有关对应于路由的 HTTP 请求的信息。 RouteValueDictionary 提供用于存储路由  Constraints 、 Defaults  和  DataTokens  对象的方法。 VirtualPathData 提供用于从路由信息生成 URL 的方法。

因为目前采用的是ASP.NET MVC 3进而可以利用扩展Route的方式实现。

首先定义DomainData、DomainRoute类

代码如下:

DomainRoute类:

View Code

 1       public   class   DomainRoute : Route
    2       {
    3           private   Regex domainRegex;
    4           private   Regex pathRegex;
    5  
   6           public   string  Domain {  get ;  set  ; }
    7  
   8           public  DomainRoute( string  domain,  string   url, RouteValueDictionary defaults)
    9              :  base (url, defaults,  new   MvcRouteHandler())
   10           {
   11              Domain =  domain;
   12           }
   13  
  14           public  DomainRoute( string  domain,  string   url, RouteValueDictionary defaults, IRouteHandler routeHandler)
   15              :  base  (url, defaults, routeHandler)
   16           {
   17              Domain =  domain;
   18           }
   19  
  20           public  DomainRoute( string  domain,  string  url,  object   defaults)
   21              :  base (url,  new  RouteValueDictionary(defaults),  new   MvcRouteHandler())
   22           {
   23              Domain =  domain;
   24           }
   25  
  26           public  DomainRoute( string  domain,  string  url,  object   defaults, IRouteHandler routeHandler)
   27              :  base (url,  new   RouteValueDictionary(defaults), routeHandler)
   28           {
   29              Domain =  domain;
   30           }
   31  
  32           public   override   RouteData GetRouteData(HttpContextBase httpContext)
   33           {
   34               //   构造 regex 
  35              domainRegex =  CreateRegex(Domain);
   36              pathRegex =  CreateRegex(Url);
   37  
  38               //   请求信息 
  39               string  requestDomain = httpContext.Request.Headers[ "  host  "  ];
   40               if  (! string  .IsNullOrEmpty(requestDomain))
   41               {
   42                   if  (requestDomain.IndexOf( "  :  " ) >  0  )
   43                   {
   44                      requestDomain = requestDomain.Substring( 0 , requestDomain.IndexOf( "  :  "  ));
   45                   }
   46               }
   47               else 
  48               {
   49                  requestDomain =  httpContext.Request.Url.Host;
   50               }
   51               string  requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring( 2 ) +  httpContext.Request.PathInfo;
   52  
  53               //   匹配域名和路由 
  54              Match domainMatch =  domainRegex.Match(requestDomain);
   55              Match pathMatch =  pathRegex.Match(requestPath);
   56  
  57               //   路由数据 
  58              RouteData data =  null  ;
   59               if  (domainMatch.Success &&  pathMatch.Success)
   60               {
   61                  data =  new  RouteData( this  , RouteHandler);
   62  
  63                   //   添加默认选项 
  64                   if  (Defaults !=  null  )
   65                   {
   66                       foreach  (KeyValuePair< string ,  object > item  in   Defaults)
   67                       {
   68                          data.Values[item.Key] =  item.Value;
   69                       }
   70                   }
   71  
  72                   //   匹配域名路由 
  73                   for  ( int  i =  1 ; i < domainMatch.Groups.Count; i++ )
   74                   {
   75                      Group group =  domainMatch.Groups[i];
   76                       if   (group.Success)
   77                       {
   78                           string  key =  domainRegex.GroupNameFromNumber(i);
   79  
  80                           if  (! string .IsNullOrEmpty(key) && ! char .IsNumber(key,  0  ))
   81                           {
   82                               if  (! string  .IsNullOrEmpty(group.Value))
   83                               {
   84                                  data.Values[key] =  group.Value;
   85                               }
   86                           }
   87                       }
   88                   }
   89  
  90                   //   匹配域名路径 
  91                   for  ( int  i =  1 ; i < pathMatch.Groups.Count; i++ )
   92                   {
   93                      Group group =  pathMatch.Groups[i];
   94                       if   (group.Success)
   95                       {
   96                           string  key =  pathRegex.GroupNameFromNumber(i);
   97  
  98                           if  (! string .IsNullOrEmpty(key) && ! char .IsNumber(key,  0  ))
   99                           {
  100                               if  (! string  .IsNullOrEmpty(group.Value))
  101                               {
  102                                  data.Values[key] =  group.Value;
  103                               }
  104                           }
  105                       }
  106                   }
  107               }
  108  
 109               return   data;
  110           }
  111  
 112           public   override   VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
  113           {
  114               return   base  .GetVirtualPath(requestContext, RemoveDomainTokens(values));
  115           }
  116  
 117           public   DomainData GetDomainData(RequestContext requestContext, RouteValueDictionary values)
  118           {
  119               //   获得主机名 
 120               string  hostname =  Domain;
  121               foreach  (KeyValuePair< string ,  object > pair  in   values)
  122               {
  123                  hostname = hostname.Replace( "  {  "  + pair.Key +  "  }  "  , pair.Value.ToString());
  124               }
  125  
 126               //   Return 域名数据 
 127               return   new   DomainData
  128               {
  129                  Protocol =  "  http  "  ,
  130                  HostName =  hostname,
  131                  Fragment =  "" 
 132               };
  133           }
  134  
 135           private  Regex CreateRegex( string   source)
  136           {
  137               //   替换 
 138              source = source.Replace( "  /  " ,  @"  \/?  "  );
  139              source = source.Replace( "  .  " ,  @"  \.?  "  );
  140              source = source.Replace( "  -  " ,  @"  \-?  "  );
  141              source = source.Replace( "  {  " ,  @"  (?<  "  );
  142              source = source.Replace( "  }  " ,  @"  >([a-zA-Z0-9_]*))  "  );
  143  
 144               return   new  Regex( "  ^  "  + source +  "  $  "  );
  145           }
  146  
 147           private   RouteValueDictionary RemoveDomainTokens(RouteValueDictionary values)
  148           {
  149              Regex tokenRegex =  new  Regex( @"  ({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?  "  );
  150              Match tokenMatch =  tokenRegex.Match(Domain);
  151               for  ( int  i =  0 ; i < tokenMatch.Groups.Count; i++ )
  152               {
  153                  Group group =  tokenMatch.Groups[i];
  154                   if   (group.Success)
  155                   {
  156                       string  key = group.Value.Replace( "  {  " ,  "" ).Replace( "  }  " ,  ""  );
  157                       if   (values.ContainsKey(key))
  158                           values.Remove(key);
  159                   }
  160               }
  161  
 162               return   values;
  163           }
  164       }
  165       public   class   DomainData
  166       {
  167           public   string  Protocol {  get ;  set  ; }
  168           public   string  HostName {  get ;  set  ; }
  169           public   string  Fragment {  get ;  set  ; }
  170      }

DomainData 类:

View Code

 1   public   class   DomainData
  2       {
  3           public   string  Protocol {  get ;  set  ; }
  4           public   string  HostName {  get ;  set  ; }
  5           public   string  Fragment {  get ;  set  ; }
  6      }

然后在Global中配置路由

    1:   routes.Add( "DomainRoute" ,  new  DomainRoute( 
    2:     "www.{companyUrl}.wenthink.com" ,       // Domain with parameters  
    3:    "{controller}/{action}/{id}" ,     // URL with parameters  
    4:    new  {  companyUrl=  "" ,  controller =  "Home" , action =  "Login" , id =  ""  }   // Parameter defaults  
    5:   ));

效果图:

a 公司用户登录时:

 

b公司用户登录时:

 

当用户尝试错误时:可自定义提示页面

基础支持:域名支持泛解析

然后要做的是:配置DNS服务,也就是让你的域名支持泛解析   (Windows Server 才会有,其他的Windows系统可以尝试修改Host文件,便于测试)

Step By Step

创建反向区域 绑定指针  

完成上面的操作,基本可以实现DNS的泛解析了.当然如果没有绑定域名的话,只能修改Host文件来进行操作;

本机测试的情况下需要把Host文件中添加当前IP地址 所映射的域名,如本文中的wenthink.com

备注:以上解决了域名访问的问题,但是会存在Session跨域访问的丢失的现象.本例中采用了CrossDomainCookie的方式解决.当然不是唯一的解决方案. 方法很简单,这里就不多说明了,需要的可以自己Google一下 :-)

参考资料: http://blog.maartenballiauw.be/post/2009/05/20/ASPNET-MVC-Domain-Routing.aspx

             http://www.cnblogs.com/cyq1162/archive/2010/10/15/1851773.html

以上为个人学习摘要,如有错误,欢迎指正!!

下期:ASP.NET管道机制及IIS的工作原理浅析.

上个草图先 :-P

我们每个人都是梦想家,当离开家了,就只剩梦想了。。。 道路,或许坎坷,但你终会到达!!!

 

分类:  ASP.NET ,  个人随笔

标签:  MVC ,  二级域名 ,  DNS 泛解析

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于ASP.NET MVC动态二级域名及ASP.NET管道机制的详细内容...

  阅读:48次