When a web application is sitting behind either a proxy or a load balancer, and you use Request.Url to, for example, generate an absolute url, you would get a the private url used by proxy to connect to the web server.

The reason

Let's see how a typical load balanced environment works:

  • The user types http://example.com;
  • The request goes to the load balancer which is configured to respond to that url;
  • Then the load balancer, randomly or with some logic, forwards the request to the real server that will generate the response, and will do so by using some internal urls, for example server1.mydomain.int or even directly with some internal IP address. Maybe there is a farm with 100s sites on it, and each site might have a port number to identify it.
  • finally the web server responds to the request which has been addressed to http://server1.mydomain.int:8045

By default, the Url property is generated using the information provided by the web server, which is fine in most cases, where the public url is directly mapped to the web server. But in this scenario, it will returnhttp://server1.mydomain.int:8045 instead of http://example.com.

The solution

The solution is pretty simple but not very well documented. All you need it is to add an aspnet specific setting in the appSettings section of the web.config file.

The property is called aspnet:UseHostHeaderForRequestUrl and by default its value is false. When set to true, the Url property will be built using the Host header of the request instead of the domain the server is responding to.

You can read more about this property and all other "secret" configuration keys on the MSDN site.