2012-10-17 27 views
1

我有一个ASP.NET MVC 4应用程序使用错误的实例,我有两个方面:MVC 4 DomainRoute到区从RouteTable

  • 后台
  • 注册

我已经称为类DomainRoute,它使路由整个子域的区域:

using System; 
using System.Collections.Generic; 
using System.Text.RegularExpressions; 
using System.Web.Mvc; 
using System.Web.Routing; 

namespace Admin.Web.PresentationLogic 
{ 
    /// <summary> 
    /// DomainRoute is an extension of the default Route, that makes it possible to route domains and subdomains the specific controllers. 
    /// </summary> 
    public class DomainRoute : Route 
    { 
     private string _subDomain; 

     private string[] _namespaces; 

     /// <summary> 
     /// Initializes a new instance of the <see cref="DomainRoute"/> class. 
     /// </summary> 
     /// <param name="subDomain">The sub domain.</param> 
     /// <param name="url">The URL format.</param> 
     /// <param name="defaults">The defaults.</param> 
     public DomainRoute(string subDomain, string url, RouteValueDictionary defaults) 
      : base(url, defaults, new MvcRouteHandler()) 
     { 
      this._subDomain = subDomain; 
     } 

     /// <summary> 
     /// Initializes a new instance of the <see cref="DomainRoute" /> class. 
     /// </summary> 
     /// <param name="subDomain">The sub domain.</param> 
     /// <param name="url">The URL format.</param> 
     /// <param name="defaults">The defaults.</param> 
     /// <param name="namespaces">The namespaces.</param> 
     public DomainRoute(string subDomain, string url, RouteValueDictionary defaults, string[] namespaces) 
      : base(url, defaults, new MvcRouteHandler()) 
     { 
      this._subDomain = subDomain; 
      this._namespaces = namespaces; 
     } 

     /// <summary> 
     /// Returns information about the requested route. 
     /// </summary> 
     /// <param name="httpContext">An object that encapsulates information about the HTTP request.</param> 
     /// <returns> 
     /// An object that contains the values from the route definition. 
     /// </returns> 
     public override RouteData GetRouteData(System.Web.HttpContextBase httpContext) 
     { 
      // Request information 
      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; 
      } 

      var index = requestDomain.IndexOf("."); 

      if (index < 0) 
      { 
       return RouteTable.Routes["Default"].GetRouteData(httpContext); 
      } 

      var subDomain = requestDomain.Substring(0, index); 

      if (!String.IsNullOrWhiteSpace(subDomain)) 
      { 
       if (this._subDomain.Equals(subDomain, StringComparison.InvariantCultureIgnoreCase)) 
       { 
        RouteData data = new RouteData(this, this.RouteHandler); 

        // Add defaults first 
        if (Defaults != null) 
        { 
         foreach (KeyValuePair<string, object> item in Defaults) 
         { 
          data.Values[item.Key] = item.Value; 
         } 
        } 

        var pathRegex = this.CreateRegex(Url); 
        var requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo; 

        // Match domain and route 
        Match pathMatch = pathRegex.Match(requestPath); 

        // Iterate matching path groups 
        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; 
           } 
          } 
         } 
        } 

        if (!data.Values.ContainsKey("action")) 
        { 
         data.Values.Add("action", "Index"); 
        } 

        data.DataTokens["Namespaces"] = this._namespaces; 
        data.DataTokens["area"] = data.Values["area"] ?? this._subDomain; 

        return data; 
       } 
      } 

      return RouteTable.Routes["Default"].GetRouteData(httpContext); 
     } 

     /// <summary> 
     /// Creates the regex. 
     /// </summary> 
     /// <param name="source">The source.</param> 
     /// <returns>Returns the Regex for the source.</returns> 
     private Regex CreateRegex(string source) 
     { 
      // Perform replacements 
      source = source.Replace("/", @"\/?"); 
      source = source.Replace(".", @"\.?"); 
      source = source.Replace("-", @"\-?"); 
      source = source.Replace("{", @"(?<"); 
      source = source.Replace("}", @">([a-zA-Z0-9_]*))"); 

      return new Regex("^" + source + "$"); 
     } 
    } 
} 

当我章ister领域,我这样做:

context.Routes.Add("Signup_default", 
    new DomainRoute("signup", "{controller}/{action}/{id}", 
    new RouteValueDictionary(new { area = "Signup", controller = "Home", action = "Index", id = UrlParameter.Optional }), 
    new string[] { "Admin.Web.Areas.Signup.Controllers" })); 

那么,问题与执行DomainRouteGetRouteData法的方式做。

每当我尝试访问signup.localhost时,DomainRoute类的实例是我在注册Backstage区域时使用的实例。

我试着禁用后台区域,然后注册区域工作。

它使用在RouteTable中首先出现的DomainRoute的实例。

我错过了什么?

回答

1

我错过了RouteCollection的概念。

经过步骤调试到.Net源代码后,我意识到在我的DomainRoute中,如果子域不匹配,而不是返回默认路由数据,我应该返回null

这就是ASP.NET路由决定使用哪一个的方式 - 通过拨打调用GetRouteData,并让具体路由判断“我是否与HttpContext匹配?”。