zoukankan      html  css  js  c++  java
  • ASP.NET MVC 实现二级域名 [转]

    ASP.NET MVC 实现二级域名 [转]

    [转]

    自从微软发布 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控制域名:


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

    打算用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方法,需要更多的功能可以自己研究扩展。

    附代码:附件
    (如果要在使用Visual Studio开发Web服务器,务必添加把二级域名添加到hosts文件)(貌似本地测试不用)
    原文地址:http://blog.maartenballiauw.be/post/2009/05/20/ASPNET-MVC-Domain-Routing.aspx
    其实有的人为什么要这么麻烦用这种方式,URL重写或者二级域名直接绑定都可以。但是既然微软给url rouring,就应该能做到。

  • 相关阅读:
    tsm 存放磁带到带库
    tsm 切记
    添加路由时啥时候是dev啥时候是gw
    网卡上绑定多个IP地址
    更改本地环回地址引发的血案
    自学网络 arp_ignore/arp_announce
    do_try_to_free_pages
    如何用ssh实现端口的映射
    显示系统中所有的socket信息
    ifstat查看网络流量的原理
  • 原文地址:https://www.cnblogs.com/zbw911/p/2330926.html
Copyright © 2011-2022 走看看