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 中文 api (43) —— Chronometer
    SVN客户端清除密码
    Android 中文 API (35) —— ImageSwitcher
    Android 中文API (46) —— SimpleAdapter
    Android 中文 API (28) —— CheckedTextView
    Android 中文 API (36) —— Toast
    Android 中文 API (29) —— CompoundButton
    android 中文 API (41) —— RatingBar.OnRatingBarChangeListener
    Android 中文 API (30) —— CompoundButton.OnCheckedChangeListener
    Android 中文 API (24) —— MultiAutoCompleteTextView.CommaTokenizer
  • 原文地址:https://www.cnblogs.com/frozenzhang/p/5446194.html
Copyright © 2011-2022 走看看