1

ASP.NET MVC 4 アプリがあり、次の 2 つの領域があります。

  • バックステージ
  • サインアップ

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 + "$");
        }
    }
}

エリアを登録するときは、次のようにします。

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 領域を登録するときに使用したものです。

Backstage エリアを無効にしようとしたところ、Signup エリアが機能しました。

DomainRouteで最初に発生するのインスタンスを使用しますRouteTable

私は何が欠けていますか?

4

1 に答える 1

1

の概念が欠けていましたRouteCollection

DomainRoute.Net ソースへのステップ デバッグの後、サブドメインが一致しない場合、既定のルート データを返す代わりに、 を返す必要があることに気付きましたnull

GetRouteDataこれが、ASP.NET ルーティングがどちらを使用するかを決定する方法HttpContextですHttpContext

于 2012-10-19T11:55:20.517 に答える