How can I use Domain-based routing? - asp.net-mvc

I have a simple web server running Windows 2012 with IIS. I have half a dozen domains linked to this server that are basically not in use yet. I have a few more domains which are used but they could all have various subdomains that aren't supported by any site yet. So I have a default site in IIS set to catch all incoming requests that aren't handled by any other site on the server or any other server. And it's main purpose is to show a "Page not in use yet" message.
That's easy to set up but I want these pages to be a bit more fancy. So I want to have some kind of routing based on the domain name so example.com and sub.example.com and sub.sub.example.com would all be handled by the same view, but anotherexample.com would be handled by a different view and thirdexample.com by yet another view. And any domain that is not caught by this routing system would go to the default view.
And I wonder if there's a simple way to do this. Something like [route("example.com")] as a controller attribute which the system would recognize as the controller for a specific domain and it's subdomains. (And the URL path can be ignored.) I don't know if something like this already exists and have used Google but found nothing yet.
I can create a custom route, of course. But this tends to result in an if-then-else situation for all potential domain names. I need to know if there's a better method.

Use the URL rewrite module for IIS:
https://learn.microsoft.com/en-us/iis/extensions/url-rewrite-module/using-the-url-rewrite-module

Related

Working with dynamic sub-domains with struts2

How do I create a sub-domain on my application server/container using Struts2.
For example, if I have a user called john15 I would like to dynamically create the sub-domain: john15.abc.com, after the user has signed in to my application at abc.com.
In general you can't. There are ways to achieve this but sub-domains are controlled by the application server and so any programmatic control over them are limited by what the container/application server offers and would probably not be portable.
Another solution (which acheives the desired effect but without trying to use struts2/application server interaction) is to use struts2 to develop a custom url tag which builds your desired urls. Then using something that re-writes urls (software such as squid, and like: http://en.wikipedia.org/wiki/Proxy_server#Web_proxy_servers). You can rewrite the URL into a format which is more acceptable to struts, possibly as a url parameter, or make it appear as part of the path which can then be parsed.
If you must do this I would advise the proxy server solution. Implement urls to reach your actions following the template:
abc.com/user/additional_path_and_parameters
then use the web proxy to rewrite user.abc.com/additional_path_and_parameters into the above.
Finally in creating that magical stuts2 url tag and possibly a reimplementation of the action tag too: You'll probably want to reuse the existing tag(s) and have it implement urls for "production" and "development" modes. In development the tag would behave exactly as the existing struts2 url tag does, but during deployment mode it will write your urls as you need them. This is important because you don't want to waste time setting up a proxy on your development machines, that would be a pain.

Angular dart bookmarking views

It is my experience that Angular Dart is agnostic to your backend server implementation. it doesn't care if your server is in java, ruby or whatever. Angular dart has the concept of views and has a module that deals with routing between them. these routes also modify the address bar of the browser when it changes views.
I have come across this issue. Though the angular router module will change the address bar, because said route doesn't actually exist as far as the backend server is concerned, and as such will always issue a 404 response.
If such is the case, then I find the ability to route to different pages via angular to be pointless. Might as well I code in a more traditional server oriented fashion to transition between pages, than to sue angular.
Is it that there is something that is missing? Is there a way you can can get your server to resolve to the correct angular page?
You can use usePushState: false then only the (client) local part of the URL is changed.
see https://github.com/angular/angular.dart.tutorial/blob/master/Chapter_06/web/main.dart#L27
This part after the hash is never sent to the server.
This might cause some additional work for SEO.
http://example.com/index.html#someRoutePath/anotherRoutePath
or you can configure your server in a way that each request is handled independent of the path in the request and use the route package server side too.
see also https://stackoverflow.com/a/17909743/217408
You can configure your backend server to point all routes to the same file (using some kind of wildcard route which all decent servers should support). So app/some/page and app/another/page would both be served app.html. Then on your app startup you could have Angular parse the URL of the page, and manually route to that page.
I have used this approach with a Polymer app (with the Route library) and it works great. It should work similarly for Angular.

Asp.net MVC Domain Routing or Setting domain on optional MVC URL

How to set payed domains on optional URLs in one Asp.net MVC project like this:
http://domain.com/Controller/Action?id -----> www.example.com
domain.com/Controller/Action?id2 -----> www.sample.net
In another words we want to map each URL to separate domain name in 1 MVC project.
It's necessary to say, that a question near this have been asked before in Stackoverflow with some changes. And also asked before in official asp.net site by me. To clarifying the Problem, I reproduced question to achieve great answer. This question also asked from Mr. k.Scott Allen before, so he suggest me to read IRouteConstrain topic in MVC.
Any way, the required configuration in Mapping routes at the Global.asax file are not bright for me.
The information that I have gathered until now are:
First of all, Consider we have configured required DNS options to handle requests connect to related Authoritative DNS server.
And now, We need to do some changes in Global.asax file by configuring MapRoutes.
Please Answer this question by implementing above samples.Thanks a lot.
One easy and external way is to use dns Redirects like bellow:
www.example.com ----redirect to----> www.domain.com/Controller/Action/id
can be performed at the authoritative(local) dns Server. Note that we must use possible characters in url to store in a dns RR. this can be solved changing identifiers in action or using Url Rewrite methods in IIS.
Url Rewrite allow us to have some mappings due to optimizing Urls for SEO and shortening theme like a sub domain. But, because of not using sub domains in reality, we can't have Url aliases in dns like below:
www.domain.com/Controller/Action?id=optional ----map to --> www.domain.com/optional
www.domain.com/optional is not equal to optional.domain.com
so we can't use this aliasing:
www.domain.com/optional ---domain aliasing ---> www.example.com
Finally, The mapping techniques available in global.asax or C# or VB files such as Route, IRoute, etc... can be used for internal mappings and setting up MVC Routing Engine to represent different Url information but not aliasing for a domain.

IIS 7 URL Rewrite config issue or MVC Route?

I have an account with Gearhost.com and when it comes to setting up sub-domains you are currently required to go in and configure an URL Rewrite entry using IIS Remote Admin.
The directory folder structure follows the pattern:
\mastersite
\mastersite\subdomain1
The Gearhost KB Article on how to do it can be found here:
https://support.gearhost.com/KB/a851/setting-a-subdomains-content-location-using-url-rewrite.aspx?KBSearchID=0
This works just fine, but I ran into a scenario that revealed the ability to access the sub-domain by using the master.com/sub-domain path.
subdomain1.site.com (works)
www.site.com/subdomain1 (displays site also --which I don't want)
I don't know if the KB article is the correct way to configure sub-domains in IIS or if I need to manage the routing in my Microsoft MVC 3 Application.
Let's say it is the correct way to setup/configure a sub-domain. Is there a way to restrict the path for the 2nd option, so it returns as page not found or access forbidden or something to this effect?
I'm developing a Microsoft MVC Application and if I use a "Request.Url" call, it actually returns the full path of the 2nd option even when I'm sitting on what looks like a perfect path to the sub-domain home page.
So I don't know if this needs to be handled a different way, if the URL Rewrite entry needs to be changed, or what the solution may be.
Looking for feedback from any engineers who may have more knowledge on the topics.
Thanks.
I ran across an article which solved my original request for help.
It involved creating Outgoing rules in IIS, to rename the path. The rule looks for the path in question and then rewrites it.
Per the article I used Outgoing rule # 2.
Pre-Condition: None
Matching Scope: Server Variable
Variable Name: RESPONSE_LOCATION
Variable Value: Matches the Pattern
Using: Regular Expressions
Pattern: ^(?:MyMasterSiteSubFolder/MySubDomain|(.*//[_a-zA-Z0-9-\.]*)?/MyMasterSiteSubFolder/MySubDomain)(.*)
[x] Ignore case
Action: Rewrite
Action Properties Value: {R:1}{R:2}
[x] Replace existing server variable value
[ ] Stop processing of subsequent rules

Account based lookup in ASP.NET

I'm looking at using ASP.NET for a new SaaS service, but for the love of me I can't seem to figure out how to do account lookups based on subdomains like most SaaS applications (e.g. 37Signals) do.
For example, if I offer yourname.mysite.com, then how would I use ASP.NET (MVC specifically) to extract the subdomain so I can load the right template (displaying your company's name and the like)? Can it be done with regular routing?
This seems to be a common thing in SaaS so there has to be an easy way to do it in ASP.NET; I know there are plugins that do it for other frameworks like Ruby on Rails.
This works for me:
//--------------------------------------------------------------------------------------------------------------------------
public string GetSubDomain()
{
string SubDomain = "";
if (Request.Url.HostNameType == UriHostNameType.Dns)
SubDomain = Regex.Replace(Request.Url.Host, "((.*)(\\..*){2})|(.*)", "$2");
if (SubDomain.Length == 0)
SubDomain = "www";
return SubDomain;
}
I'm assuming that you would like to handle multiple accounts within the same web application rather than building separate sites using the tools in IIS. In our work, we started out creating a new web site for each subdomain but have found that this approach doesn't scale well - especially when you release an update and then have to modify dozens of sites! Thus, I do recommend this approach rather than the server-oriented techniques suggested above based on several years worth of experience doing exactly what you propose.
The code above just makes sure that this is a fully formed URL (rather, say, than an IP address) and returns the subdomain. It has worked well for us in a fairly high-volume environment.
You should be able to pick this up from the ServerVariables collection, but first you need to configure IIS and DNS to work correctly. So you know 37Signals probably use Apache or another open source, unix web server. On Apache this is referred to as VirtualHosting.
To do this with IIS you would need to create a new DNS entry (create a CNAME yourname.mysite.com to application.mysite.com) for each domain that points to your application in IIS (application.mysite.com).
You then create a host header entry in the IIS application (application.mysite.com) that will accept the header yourname.mysite.com. Users will actually hit application.mysite,com but the address is the custom subdomain. You then access the ServerVariables collection to get the value to decide on how to customize the site.
Note: there are several alternative implementations you could follow depending on requirements.
Handle the host header processing at a hardware load balancer (more likely 37Signals do this, than rely on the web server), and create a custom HTTP header to pass to the web application.
Create a new web application and host header for each individual application. This is probably an inefficient implementation for a large number of users, but could offer better isolation and security for some people.
You need to configure your DNS to support wildcard subdomains. It can be done by adding an A record pointing to your IP address, like this:
* A 1.2.3.4
Once its done, whatever you type before your domain will be sent to your root domain, where you can get by splitting the HTTP_HOST server variable, like the user buggs said above:
string user = HttpContext.Request.ServerVariables["HTTP_HOST"].Split(".")
//use the user variable to query the database for specific data
PS. If you are using a shared hosting you're probably going to have to by a Unique IP addon from them, since it's mandatory for the wildcard domains to work. If you're using a dedicated hosting you already have your own IP.
The way I have done it is with HttpContext.Request.ServerVariables["HTTP_HOST"].Split(".").
Let me know if you need more help.

Resources