zoukankan      html  css  js  c++  java
  • MVC项目不同域之间的UrlRouting

     一、DomainAction,方便生成不同域下的url

    1、新建3个MVC项目,一个公用类库WebCore

    Demo.WebApplication0

      绑定域名 www.demo.com demo.com t0.demo.com

    Demo.WebApplication1(可不用建)

      绑定域名 t1.demo.com

    Demo.WebApplication2(可不用建)

      绑定域名 t2.demo.com

    Demo.WebCore

    2、项目Demo.WebApplication0新增一个学生的Controller

     1     public class StudentController : Controller
     2     {
     3         public ActionResult Search(int gender, int degree, int pageSize, int page)
     4         {
     5             return Content(string.Format("查找学生,筛选条件。性别:{0},学历:{1},每页学生数量:{2},页码:{3}"
     6                 , (gender == 1 ? "" : (gender == 2 ? "" : "不限"))
     7                 ,degree, pageSize, page
     8                 ));
     9             //return View();
    10         }
    11 
    12 
    13     }

     

    3、域名枚举

     1     public enum DemoDomain
     2     {
     3         /// <summary>
     4         /// www.demo.com
     5         /// demo.com
     6         /// t0.demo.com
     7         /// </summary>
     8         T0,
     9 
    10         /// <summary>
    11         /// t1.demo.com
    12         /// </summary>
    13         T1,
    14 
    15         /// <summary>
    16         /// t2.demo.com
    17         /// </summary>
    18         T2,
    19 
    20         /// <summary>
    21         /// demo.com
    22         /// </summary>
    23         Default,
    24 
    25     }

    4、System.Web.Mvc.UrlHelper的静态扩展类DemoUrlExtensions

     1     public static class DemoUrlExtensions
     2     {
     3         public static string DomainAction(this UrlHelper urlHelper, string actionName, string controllerName)
     4         {
     5             return urlHelper.DomainAction(actionName, controllerName, DemoDomain.Default);
     6         }
     7 
     8         public static string DomainAction(this UrlHelper urlHelper, string actionName, string controllerName, object routeValues)
     9         {
    10             return urlHelper.DomainAction(actionName, controllerName, routeValues, DemoDomain.Default);
    11         }
    12 
    13         public static string DomainAction(this UrlHelper urlHelper, string actionName, string controllerName, DemoDomain Domain)
    14         {
    15             return urlHelper.DomainAction(actionName, controllerName, new { }, Domain);
    16         }
    17 
    18         public static string DomainAction(this UrlHelper urlHelper, string actionName, string controllerName, object routeValues, DemoDomain Domain)
    19         {
    20             return DomainAction(urlHelper, actionName, controllerName, new RouteValueDictionary(routeValues), Domain);
    21         }
    22 
    23         public static string DomainAction(this UrlHelper urlHelper, string actionName, string controllerName, RouteValueDictionary routeValues, DemoDomain Domain)
    24         {
    25             string subDomain = string.Empty;
    26             string HostName = string.Empty;
    27             switch (Domain)
    28             {
    29                 case DemoDomain.Default:
    30                     subDomain = string.Empty;
    31                     break;
    32                 case DemoDomain.T0:
    33                     subDomain = "t0";
    34                     break;
    35                 case DemoDomain.T1:
    36                     subDomain = "t1";
    37                     break;
    38                 case DemoDomain.T2:
    39                     subDomain = "t2";
    40                     break;
    41                 default:
    42                     subDomain = string.Empty;
    43                     break;
    44             }
    45 
    46             if (!string.IsNullOrEmpty(subDomain))
    47             {
    48                 HostName = subDomain + ".demo.com";
    49             }
    50             else
    51             {
    52                 HostName = "www.demo.com";
    53             }
    54             //核心的一行
    55             string url = urlHelper.Action(actionName, controllerName, routeValues, "http", HostName);
    56             if (url.Contains('?'))
    57             {
    58                 url = url.TrimEnd('/');
    59             }
    60             else
    61             {
    62                 if (url.EndsWith(".html/"))
    63                 {
    64                     url = url.TrimEnd('/');
    65                 }
    66             }
    67             return url;
    68         }
    69 
    70     }

    5、修改Home/Index内容

    1 <div>
    2     <a href="@Url.DomainAction("Index","Home", DemoDomain.T1)">我要去t1.demo.com</a>
    3     <a href="@Url.DomainAction("Index","Home", DemoDomain.T2)">我要去t2.demo.com</a>
    4     <a href="@Url.DomainAction("Index", "Home", new { from = "www" }, DemoDomain.T2)">我要去t2.demo.com,我要带参数,表示我是从www过来的</a>
    5 
    6     <a href="@Url.DomainAction("Search", "Student", new { gender = 1, degree = 0, pageSize = 20, page = 1 }, DemoDomain.T0)">查找性别男的学生</a>
    7 
    8 </div>

    对应的html源码

    1 <div>
    2     <a href="http://t1.demo.com/">我要去t1.demo.com</a>
    3     <a href="http://t2.demo.com/">我要去t2.demo.com</a>
    4     <a href="http://t2.demo.com/?from=www">我要去t2.demo.com,我要带参数,表示我是从www过来的</a>
    5 
    6     <a href="http://t0.demo.com/Student/Search?gender=1&amp;degree=0&amp;pageSize=20&amp;page=1">查找性别男的学生</a>
    7 
    8 </div>

    二、注册路由,SEO优化

    现在已经能做到

    @Url.DomainAction("Search", "Student", new { gender = 1, degree = 0, pageSize = 20, page = 1 }, DemoDomain.T0)

    对应的Url为

    http://t0.demo.com/Student/Search?gender=1&degree=0&pageSize=20&page=1

    ,但这个链接不利于SEO,理想的情况可能是这样(请把t0当成student)

    http://t0.demo.com/Search/1-0-20-1.html

    定义路由

      1 public class DomainRoute : Route
      2     {
      3         private static 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_]*})*-?.?/?", RegexOptions.Compiled);
      4         private static Dictionary<string, Regex> domainRegDic = new Dictionary<string, Regex>();
      5         private static Dictionary<string, Regex> pathRegDic = new Dictionary<string, Regex>();
      6 
      7         /// <summary>
      8         /// 
      9         /// </summary>
     10         public Regex PathRegex
     11         {
     12             get
     13             {
     14                 if (!pathRegDic.Keys.Contains(Url))
     15                 {
     16                     switch (Url)
     17                     {
     18                         case WebCoreConsts.URL_T0_SearchStudent:
     19                             pathRegDic[Url] = new Regex(ConvertToPattern("search/{gender}-{degree}-{pagesize}-{page}.html"), RegexOptions.Compiled | RegexOptions.IgnoreCase);
     20                             break;
     21                         default:
     22                             pathRegDic[Url] = CreateRegex(Url);
     23                             break;
     24                     }
     25                 }
     26                 return pathRegDic[Url];
     27             }
     28         }
     29 
     30         /// <summary>
     31         /// 
     32         /// </summary>
     33         public Regex DomainRegex
     34         {
     35             get
     36             {
     37                 if (!domainRegDic.Keys.Contains(Domain))
     38                 {
     39 
     40                     domainRegDic[Domain] = CreateRegex(Domain);
     41                 }
     42                 return domainRegDic[Domain];
     43             }
     44 
     45         }
     46 
     47         public string Domain { get; set; }
     48 
     49         public DomainRoute(string domain, string url, RouteValueDictionary defaults)
     50             : base(url, defaults, new MvcRouteHandler())
     51         {
     52             Domain = domain;
     53         }
     54 
     55         public DomainRoute(string domain, string url, RouteValueDictionary defaults, IRouteHandler routeHandler)
     56             : base(url, defaults, routeHandler)
     57         {
     58             Domain = domain;
     59         }
     60 
     61         public DomainRoute(string domain, string url, object defaults)
     62             : base(url, new RouteValueDictionary(defaults), new MvcRouteHandler())
     63         {
     64             Domain = domain;
     65         }
     66 
     67         //new
     68         public DomainRoute(string domain, string url, object defaults, object constraints)
     69             : base(url, new RouteValueDictionary(defaults), new RouteValueDictionary(constraints), new MvcRouteHandler())
     70         {
     71             Domain = domain;
     72         }
     73 
     74         public DomainRoute(string domain, string url, object defaults, IRouteHandler routeHandler)
     75             : base(url, new RouteValueDictionary(defaults), routeHandler)
     76         {
     77             Domain = domain;
     78         }
     79 
     80         public override RouteData GetRouteData(HttpContextBase httpContext)
     81         {
     82             // 请求信息
     83             string requestDomain = httpContext.Request.Headers["host"];
     84             if (!string.IsNullOrEmpty(requestDomain))
     85             {
     86                 if (requestDomain.IndexOf(":") > 0)
     87                 {
     88                     requestDomain = requestDomain.Substring(0, requestDomain.IndexOf(":"));
     89                 }
     90             }
     91             else
     92             {
     93                 requestDomain = httpContext.Request.Url.Host;
     94             }
     95             string requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;
     96 
     97             // 匹配域名和路由
     98             Match domainMatch = DomainRegex.Match(requestDomain);
     99             Match pathMatch = PathRegex.Match(requestPath);
    100 
    101             // 路由数据
    102             RouteData data = null;
    103             if (domainMatch.Success && pathMatch.Success)
    104             {
    105                 data = new RouteData(this, RouteHandler);
    106 
    107                 // 添加默认选项
    108                 if (Defaults != null)
    109                 {
    110                     foreach (KeyValuePair<string, object> item in Defaults)
    111                     {
    112                         data.Values[item.Key] = item.Value;
    113                     }
    114                 }
    115 
    116                 // 匹配域名路由
    117                 for (int i = 1; i < domainMatch.Groups.Count; i++)
    118                 {
    119                     Group group = domainMatch.Groups[i];
    120                     if (group.Success)
    121                     {
    122                         string key = DomainRegex.GroupNameFromNumber(i);
    123 
    124                         if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, 0))
    125                         {
    126                             if (!string.IsNullOrEmpty(group.Value))
    127                             {
    128                                 data.Values[key] = group.Value;
    129                             }
    130                         }
    131                     }
    132                 }
    133 
    134                 // 匹配域名路径
    135                 for (int i = 1; i < pathMatch.Groups.Count; i++)
    136                 {
    137                     Group group = pathMatch.Groups[i];
    138                     if (group.Success)
    139                     {
    140                         string key = PathRegex.GroupNameFromNumber(i);
    141 
    142                         if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, 0))
    143                         {
    144                             if (!string.IsNullOrEmpty(group.Value))
    145                             {
    146                                 data.Values[key] = group.Value;
    147                             }
    148                         }
    149                     }
    150                 }
    151             }
    152 
    153             return data;
    154         }
    155 
    156         public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    157         {
    158 
    159             VirtualPathData pathData = base.GetVirtualPath(requestContext, RemoveDomainTokens(values));
    160             if (pathData != null && !string.IsNullOrEmpty(pathData.VirtualPath))
    161             {
    162                 if (pathData.VirtualPath.EndsWith(".html/"))
    163                 {
    164                     pathData.VirtualPath = pathData.VirtualPath.TrimEnd('/');
    165                 }
    166                 else if (!pathData.VirtualPath.EndsWith("/") && !pathData.VirtualPath.EndsWith(".html"))
    167                 {
    168                     pathData.VirtualPath = pathData.VirtualPath + "/";
    169                 }
    170             }
    171             return pathData;
    172         }
    173 
    174         private Regex CreateRegex(string source)
    175         {
    176             try
    177             {
    178                 string src = source;
    179                 // 替换
    180                 source = source.Replace("/", @"/?");
    181                 source = source.Replace(".", @".?");
    182                 source = source.Replace("-", @"-?");
    183                 source = source.Replace("{", @"(?<");
    184                 source = source.Replace("}", @">([a-zA-Z0-9_]*))");
    185                 return new Regex("^" + source + "$", RegexOptions.Compiled);
    186             }
    187             catch (Exception ex)
    188             {
    189                 //AppLogger.Error("创建正则出错:" + source + " 详情:" + ex.Message);
    190             }
    191             return new Regex("^" + source + "$", RegexOptions.Compiled);
    192         }
    193 
    194         private RouteValueDictionary RemoveDomainTokens(RouteValueDictionary values)
    195         {
    196 
    197             Match tokenMatch = tokenRegex.Match(Domain);
    198             for (int i = 0; i < tokenMatch.Groups.Count; i++)
    199             {
    200                 Group group = tokenMatch.Groups[i];
    201                 if (group.Success)
    202                 {
    203                     string key = group.Value.Replace("{", "").Replace("}", "");
    204                     if (values.ContainsKey(key))
    205                         values.Remove(key);
    206                 }
    207             }
    208 
    209             return values;
    210         }
    211 
    212         private static string ConvertToPattern(string source)
    213         {
    214             try
    215             {
    216                 string src = source;
    217                 // 替换
    218                 source = source.Replace("/", @"/?");
    219                 source = source.Replace(".", @".?");
    220                 source = source.Replace("-", @"-?");
    221                 source = source.Replace("{", @"(?<");
    222                 source = source.Replace("}", @">([a-zA-Z0-9_]*))");
    223                 return "^" + source + "$";
    224             }
    225             catch (Exception ex)
    226             {
    227             }
    228             return source;
    229         }
    230 
    231     }
    View Code

    注册路由

    1             routes.LowercaseUrls = true;
    2 
    3             routes.Add("T0StudentSearchDomainRoute", new DomainRoute(
    4                 "t0.demo.com",  // Domain with parameters
    5                 WebCoreConsts.URL_T0_SearchStudent, // URL with parameters
    6                 new { controller = "Student", action = "Search" }
    7                         //, new { }
    8             ));

    可能还需要在web.config的system.webServer项中增加一行配置,否则.html不会进入路由,会直接映射成本地路径

        <modules runAllManagedModulesForAllRequests="true" />

    这时候

        <a href="@Url.DomainAction("Search", "Student", new { gender = 1, degree = 0, pageSize = 20, page = 1 }, DemoDomain.T0)" target="_blank">查找性别男的学生</a>

    就会对应成

        <a href="http://t0.demo.com/search/1-0-20-1.html" target="_blank">查找性别男的学生</a>

      附:源码下载

  • 相关阅读:
    Android真机测试、乐视手机启用开发者模式
    HTML5 Geolocation API地理定位整理(二)
    HTML5 Geolocation API地理定位整理(一)
    HTML5 Geolocation API工作原理[转载]
    HTML5 filesystem: 网址
    RequireJS API
    Grunt 之 watch 和 livereload
    Grunt 之通配符
    前端开发 Grunt 之 Connect
    创建 Web 前端开发环境
  • 原文地址:https://www.cnblogs.com/frozenzhang/p/5446194.html
Copyright © 2011-2022 走看看