• Asp.Net Mvc Area二级域名


    参考:https://blog.maartenballiauw.be/post/2009/05/20/aspnet-mvc-domain-routing.html

    参考:https://www.cnblogs.com/Showshare/p/multidomain-to-onesite-subdomain-to-area-by-routing.html

    适当使用反编译工具查看 Route 的源码

    主要类

    DomainData.cs

    namespace DomainMvcTest.Core
    {
        public class DomainData
        {
            public string Protocol { get; set; }
            public string HostName { get; set; }
            public string Fragment { get; set; }
        }
    }

    DomainRoute.cs

    using System.Collections.Generic;
    using System.Text.RegularExpressions;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Routing;
    
    namespace DomainMvcTest.Core
    {
        public class DomainRoute : Route
        {
            private Regex domainRegex;
            private Regex pathRegex;
    
            public string Domain { get; set; }
    
            public DomainRoute(string domain, string url, RouteValueDictionary defaults)
                : base(url, defaults, new MvcRouteHandler())
            {
                Domain = domain;
            }
    
            public DomainRoute(string domain, string url, RouteValueDictionary defaults, IRouteHandler routeHandler)
                : base(url, defaults, routeHandler)
            {
                Domain = domain;
            }
    
            public DomainRoute(string domain, string url, object defaults)
                : base(url, new RouteValueDictionary(defaults), new MvcRouteHandler())
            {
                Domain = domain;
            }
    
            public DomainRoute(string domain, string url, object defaults, IRouteHandler routeHandler)
                : base(url, new RouteValueDictionary(defaults), routeHandler)
            {
                Domain = domain;
            }
    
            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);
    
                // 路由数据
                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;
                            if (item.Key.Equals("area") || item.Key.Equals("Namespaces"))
                            {
                                data.DataTokens[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;
                                    if (key.Equals("area"))
                                    {
                                        data.DataTokens[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;
                                    if (key.Equals("area"))
                                    {
                                        data.DataTokens[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)
                {
                    if (pair.Key == "area" && string.IsNullOrEmpty(pair.Value.ToString()))
                    {
                        hostname = hostname.Replace("{" + pair.Key + "}", "www");
                    }
                    else
                    {
                        hostname = hostname.Replace("{" + pair.Key + "}", pair.Value.ToString());
                    }
                }
    
                //如果域名的area还没有被替换,说明路由数据里没有area,恢复为顶级域名
                if (hostname.Contains("{area}"))
                {
                    hostname = hostname.Replace("{area}", "www");
                }
    
                RemoveDomainTokens(values);
    
                // Return 域名数据
                return new DomainData
                {
                    Protocol = "http",
                    HostName = hostname,
                    Fragment = ""
                };
            }
    
            private Regex CreateRegex(string source)
            {
                // 替换
                source = source.Replace("/", @"/?");
                source = source.Replace(".", @".?");
                source = source.Replace("-", @"-?");
                source = source.Replace("{", @"(?<");
                source = source.Replace("}", @">([a-zA-Z0-9_]*))");
    
                return new Regex("^" + source + "$");
            }
    
            private RouteValueDictionary RemoveDomainTokens(RouteValueDictionary values)
            {
                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_]*})*-?.?/?");
                Match tokenMatch = tokenRegex.Match(Domain);
                for (int i = 0; i < tokenMatch.Groups.Count; i++)
                {
                    Group group = tokenMatch.Groups[i];
                    if (group.Success)
                    {
                        string key = group.Value.Replace("{", "").Replace("}", "");
                        if (values.ContainsKey(key))
                            values.Remove(key);
                    }
                }
    
                return values;
            }
        }
    }

    LinkExtensions.cs

    using System.Collections.Generic;
    using System.Linq;
    using System.Web.Routing;
    using DomainMvcTest.Core;
    
    namespace System.Web.Mvc.Html
    {
        public static class LinkExtensions
        {
            public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, bool requireAbsoluteUrl)
            {
                return htmlHelper.ActionLink(linkText, actionName, null, new RouteValueDictionary(), new RouteValueDictionary(), requireAbsoluteUrl);
            }
    
            public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, object routeValues, bool requireAbsoluteUrl)
            {
                return htmlHelper.ActionLink(linkText, actionName, null, new RouteValueDictionary(routeValues), new RouteValueDictionary(), requireAbsoluteUrl);
            }
    
            public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, bool requireAbsoluteUrl)
            {
                return htmlHelper.ActionLink(linkText, actionName, controllerName, new RouteValueDictionary(), new RouteValueDictionary(), requireAbsoluteUrl);
            }
    
            public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, RouteValueDictionary routeValues, bool requireAbsoluteUrl)
            {
                return htmlHelper.ActionLink(linkText, actionName, null, routeValues, new RouteValueDictionary(), requireAbsoluteUrl);
            }
    
            public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, object routeValues, object htmlAttributes, bool requireAbsoluteUrl)
            {
                return htmlHelper.ActionLink(linkText, actionName, null, new RouteValueDictionary(routeValues), new RouteValueDictionary(htmlAttributes), requireAbsoluteUrl);
            }
    
            public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes, bool requireAbsoluteUrl)
            {
                return htmlHelper.ActionLink(linkText, actionName, null, routeValues, htmlAttributes, requireAbsoluteUrl);
            }
    
            public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes, bool requireAbsoluteUrl)
            {
                return htmlHelper.ActionLink(linkText, actionName, controllerName, new RouteValueDictionary(routeValues), new RouteValueDictionary(htmlAttributes), requireAbsoluteUrl);
            }
    
            public static MvcHtmlString 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;
                    //如果不需要变换area,则routeValues不传入area的值
                    if (routeValues.Keys.Contains("area"))
                    {
                        routeData.Values["area"] = routeValues["area"];
                    }
    
                    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);
            }
        }
    }

    在 AreaRegistration 中注册路由

    using System.Web.Mvc;
    using DomainMvcTest.Core;
    
    namespace DomainMvcTest.Areas.Haha
    {
        public class HahaAreaRegistration : AreaRegistration 
        {
            public override string AreaName 
            {
                get 
                {
                    return "Haha";
                }
            }
    
            public override void RegisterArea(AreaRegistrationContext context) 
            {
                context.Routes.Add("hahaDomain", new DomainRoute(
                    "{area}.chenwei.com",                                     // Domain with parameters
                    "{controller}/{action}/{id}",                                        // URL with parameters
                    new { controller = "Home", action = "Index", id = "", Namespaces = new[] { "DomainMvcTest.Areas.Haha.Controllers" }}  // Parameter defaults
                ));
                //context.MapRoute(
                //    "Haha_default",
                //    "Haha/{controller}/{action}/{id}",
                //    new { action = "Index", id = UrlParameter.Optional }
                //);
            }
        }
    }

    View 中生成Url连接

        @Html.ActionLink("前往首页", "Index", "Home",new{area=""},null,true) <br/>
        @Html.ActionLink("前往Hehe", "Index", "Home", new { area = "Hehe" }, null, true)<br />
    @Html.ActionLink("前往Haha", "Index", "Home", new { area = "Haha" }, null, true)
  • 相关阅读:
    单元测试乱弹(一):悲剧的测试工具
    Android 4.2中sqlite操作问题(二):某些情况下显式启用事务能提高操作效率
    some code of debug mode
    asp .NET弹出窗口 汇总
    if (!IsPostBack)
    Asp.Net中清空所有textbox的几种方法
    ASP.NET验证控件详解
    正则表达式限制文本框只能输入数字
    颜色
    gridview 根据条件更改链接的可用和颜色
  • 原文地址:https://www.cnblogs.com/ideacore/p/8026451.html
Copyright © 2020-2023  润新知