ASP.NET MVC 4 - unique routes for user groups?

I am creating an application in which I want to provide a client company with a unique URL, for example clientcompany .app.com 'or' app.com/ clientcompany .

When a user subscribes, I want to let them choose their subdomain, and they should be able to invite other users to work under this subdomain. The subdomain / route must be the "parent" in which all users are grouped.

How can I achieve something like this using MVC 4 routing?

+4
source share
4 answers

If you want to provide each client company with its own subdomain, for example clientcompany.app.com , you will need to create DNS records for the client company when the first user is signed up. Specify each subdomain in your MVC4 application, but make sure that the IIS settings for your application allow multiple / wildcard hosts (this happens by default).

After that, you can check the host of the domain that the client requested during the Request object of the controller, analyze the domain (for example, select clientcompany from the domain) and use it as your group.

Alternatively, if you want the client company to simply be part of the URL path (i.e. the permanent domain), for example www.app.com/clientcompany/ , you can create a route, for example:

 {company}/{controller}/{action} 

Then, when you take care of the company, you can add a parameter or company member to your model and read it as necessary.

+2
source

This can be achieved by creating a custom domain route:

 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 (System.Diagnostics.Debugger.IsAttached == false) { if (requestDomain.IndexOf(":") > 0) { requestDomain = requestDomain.Substring(0, requestDomain.IndexOf(":")); } } // Strip Multiple Subdomains if (requestDomain.Split('.').Length > 3) { string[] split = requestDomain.Split('.'); requestDomain = String.Join(".", split, split.Length - 3, 3); string url = String.Format("{0}://{1}/", httpContext.Request.Url.Scheme, requestDomain); if (System.Diagnostics.Debugger.IsAttached == true) { httpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache); httpContext.Response.CacheControl = "no-cache"; } httpContext.Response.RedirectPermanent(url, true); } } 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) { 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 = values.Aggregate(Domain, (current, pair) => current.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) { 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; } } public class DomainData { public string Protocol { get; set; } public string HostName { get; set; } public string Fragment { get; set; } } 

Global.asax:

 routes.Add( "DomainRoute", new DomainRoute( "{subdomain}.yoururl.com", // Domain with parameters "{controller}/{action}", // URL with parameters new { controller = "Home", action = "Index", subdomain = UrlParameter.Optional } // Parameter defaults )); 

http://subdomain.app.com will then add the parameter, 'subdomain' to your RouteValueDictionary.

Also, be sure to create a wildcard DNS record.

+3
source

To handle the behavior of the subdomain, you will need a custom IRouteConstraint. There's a post here that covers it exactly the way you want!

Check out MVC 3 Subdomain Routing

Hope this helps you!

+1
source

Honestly, this has nothing to do with routing and everything related to authorization. Regardless of whether you use a subdomain or a directory-style path, you essentially treat the clientcompany part as slug β€” using it to search for a β€œgroup”. Then you check the user / group ownership through the relationships in this "group", and if the user is not allowed access to it, you will return 403 Forbidden answer. Otherwise, you can visualize the view.

+1
source

Source: https://habr.com/ru/post/1487931/


All Articles