MVC 4 DomainRoute到区使用从RouteTable错误实例 [英] MVC 4 DomainRoute to Area uses wrong instance from RouteTable

查看:561
本文介绍了MVC 4 DomainRoute到区使用从RouteTable错误实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个ASP.NET MVC应用程序4,我有两个方面:

I have an ASP.NET MVC 4 app where I have two areas:


  • 后台

  • 注册

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

I have a class called DomainRoute that makes it possible to route an entire subdomain to an area:

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

在我注册领域,我这样做:

When I register the areas, I do this:

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

所以,问题的方式做 DomainRoute GetRouteData 执行方法。

每当我尝试访问 signup.localhost DomainRoute 类的实例是,当我用一注册后台区域。

Whenever I try to access signup.localhost the instance of the DomainRoute class is the one that I used when registering the Backstage area.

我尝试禁用后台区域,然后在注册方面的工作。

I tried disabling the Backstage area, and then the Signup area worked.

它使用 DomainRoute 中,首先发生在实例中的 RouteTable

It uses the instance of DomainRoute that occurs first in the RouteTable.

我是什么失踪?

推荐答案

我是缺少概念的 RouteCollection

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

After step debugging into the .Net source, I realized that in my DomainRoute, if the sub-domain doesn't match, instead of returning default route data I should return null.

这是ASP.NET路由决定使用哪一个的方式 - 通过调用 GetRouteData 的HttpContext 和让具体路线弄清楚,如果我的比赛的HttpContext

That's the way ASP.NET Routing determines which one to use -- by calling GetRouteData with the HttpContext and let the specific route figure out if "I'm a match for the HttpContext?"

这篇关于MVC 4 DomainRoute到区使用从RouteTable错误实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆