ASP.NET MVC Subdomains

后端 未结 3 1434
渐次进展
渐次进展 2020-12-28 09:18

I have hosting and domain like that:

www.EXAMPLE.com

I\'ve created few subdomains like that:

www.PAGE1.EXAMPLE.com
www.PAGE         


        
相关标签:
3条回答
  • 2020-12-28 09:52

    I tried Paul Taylor answer above is pretty good but that didn't work entirely for me. I use this implementation of Route class.

    Add your custom domain into C:/Windows/System32/drivers/etc/hosts file

    • 127.0.0.1 subdomain.localhost.com

    DomainData.cs

    public class DomainData
    {
      public string Protocol { get; set; }
      public string HostName { get; set; }
      public string Fragment { get; set; }
    }
    

    DomainRoute.cs

    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)
    {
        // Build regex
        domainRegex = CreateRegex(Domain);
        pathRegex = CreateRegex(Url);
    
        // 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;
        }
        string requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) +
                             httpContext.Request.PathInfo;
    
        // Match domain and route
        Match domainMatch = domainRegex.Match(requestDomain);
        Match pathMatch = pathRegex.Match(requestPath);
    
        // Route data
        RouteData data = null;
        if (domainMatch.Success && pathMatch.Success && requestDomain.ToLower() != "tg.local" &&
            requestDomain.ToLower() != "tg.terrasynq.net" && requestDomain.ToLower() != "www.townsgossip.com" &&
            requestDomain.ToLower() != "townsgossip.com")
        {
            data = new RouteData(this, RouteHandler);
    
            // Add defaults first
            if (Defaults != null)
            {
                foreach (KeyValuePair<string, object> item in Defaults)
                {
                    data.Values[item.Key] = item.Value;
                }
            }
    
            // Iterate matching domain groups
            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;
                        }
                    }
                }
            }
    
            // 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;
                        }
                    }
                }
            }
        }
    
        return data;
    }
    
    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        return base.GetVirtualPath(requestContext, RemoveDomainTokens(values));
    }
    
    public DomainData GetDomainData(RequestContext requestContext, RouteValueDictionary values)
    {
        // Build hostname
        string hostname = Domain;
        foreach (KeyValuePair<string, object> pair in values)
        {
            hostname = hostname.Replace("{" + pair.Key + "}", pair.Value.ToString());
        }
    
        // Return domain data
        return new DomainData
        {
            Protocol = "http",
            HostName = hostname,
            Fragment = ""
        };
    }
    
    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 + "$");
    }
    
    private RouteValueDictionary RemoveDomainTokens(RouteValueDictionary values)
    {
        var 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;
      }
    }
    

    Reference: http://www.howtobuildsoftware.com/index.php/how-do/UaR/aspnet-mvc-5-domain-routing-in-mvc5

    0 讨论(0)
  • 2020-12-28 10:05

    You can do this by writing a custom Route. Here's how (adapted from Is it possible to make an ASP.NET MVC route based on a subdomain?)

    public class SubdomainRoute : RouteBase
    {
    
        public override RouteData GetRouteData(HttpContextBase httpContext)
        {
            var host = httpContext.Request.Url.Host;
            var index = host.IndexOf(".");
            string[] segments = httpContext.Request.Url.PathAndQuery.Split('/');
    
            if (index < 0)
                return null;
    
            var subdomain = host.Substring(0, index);
            string controller = (segments.Length > 0) ? segments[0] : "Home";
            string action = (segments.Length > 1) ? segments[1] : "Index";
    
            var routeData = new RouteData(this, new MvcRouteHandler());
            routeData.Values.Add("controller", controller); //Goes to the relevant Controller  class
            routeData.Values.Add("action", action); //Goes to the relevant action method on the specified Controller
            routeData.Values.Add("subdomain", subdomain); //pass subdomain as argument to action method
            return routeData;
        }
    
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            //Implement your formating Url formating here
            return null;
        }
    }
    

    Add to the route table in Global.asax.cs like this:

    routes.Add(new SubdomainRoute());
    

    And your controller method:

    public ActionResult Index(string subdomain)
    {
        //Query your database for the relevant articles based on subdomain
        var viewmodel = MyRepository.GetArticles(subdomain);
        Return View(viewmodel);
    }
    
    0 讨论(0)
  • 2020-12-28 10:05

    This is something I have wanted to do with ASP.NET MVC for a long time, but... This is not a concern that ASP.NET MVC is responsible for. This is a server concern (IIS). What you need to do is allow for wildcard subdomains on your IIS server and point them to your one application.

    Then you can do something like this with the HttpContext:

    HttpContext.Current.Request.Url.Host // user1.yourwebsite.com
    

    Then you just need to parse that and push it into your ASP.NET MVC app anyway you see fit:

    • Push it into Session
    • Update the current route data and push a value in
    • Etc....

    The choice is really up to you.

    Note: The downside here is that this makes local development increasingly difficult, so you might want to mock up a way to fake a subdomain in your application.

    0 讨论(0)
提交回复
热议问题