49

I tried

Uri uri = HttpContext.Current.Request.Url;
String host = uri.Scheme + Uri.SchemeDelimiter + uri.Host + ":" + uri.Port;

and it worked well on my local machine, but when being published to IIS7, there is an exception saying

System.Web.HttpException: Request is not available in this context

Anyone know how to achieve this?

Leo
  • 2,173
  • 6
  • 28
  • 37
  • See also http://stackoverflow.com/a/578083/12484 for a cleaner way to get the scheme + host + port from a URL (once you have one). – Jon Schneider Sep 18 '14 at 19:12
  • Sounds like you're running in integrated mode, not classic (which I think you're running on your local). The problem is that Request isn't available in Application_Start in IIS7. Have a look at: http://mvolo.com/blogs/serverside/archive/2007/11/10/Integrated-mode-Request-is-not-available-in-this-context-in-Application_5F00_Start.aspx Which explains it nicely. – Michael Shimmins Nov 22 '10 at 07:44

3 Answers3

60

When your web application starts, there is no HTTP request being handled.

You may want to handle define the Application_BeginRequest(Object Sender, EventArgs e) method in which the the Request context is available.

Edit: Here is a code sample inspired by the Mike Volodarsky's blog that Michael Shimmins linked to:

    void Application_BeginRequest(Object source, EventArgs e)
    {
        HttpApplication app = (HttpApplication)source;
        var host = FirstRequestInitialisation.Initialise(app.Context);
    }

    static class FirstRequestInitialisation
    {
        private static string host = null;
        private static Object s_lock = new Object();

        // Initialise only on the first request
        public static string Initialise(HttpContext context)
        {
            if (string.IsNullOrEmpty(host))
            {
                lock (s_lock)
                {
                    if (string.IsNullOrEmpty(host))
                    {
                        var uri = context.Request.Url;
                        host = uri.GetLeftPart(UriPartial.Authority);
                    }
                }
            }

            return host;
        }
    }
Chris Marisic
  • 32,487
  • 24
  • 164
  • 258
cspolton
  • 4,495
  • 4
  • 26
  • 34
  • 3
    Shouldn't that be `Uri uri = context.Request.Url;` also couldn't the next line be simplified to merely `uri.GetLeftPart(UriPartial.Authority);` – Chris Marisic Jun 06 '12 at 02:40
  • this should also be a static class and you don't need to initialize host. – Steve Dec 04 '13 at 01:47
  • So there really is no way to get the port number until the very first HTTP request arrives? – PaulK Oct 30 '14 at 22:55
  • 1
    Actually no. An ASP.NET website can have multiple bindings, it could run under multiple hosts and multiple port numbers (for example a secure and non-secure version of the website). You only have one instance of the web application running, the incoming request has information on what host initiated the request. The web application just knows it is an application, it has no real context of what host it is running under. If you app has two bindings, one for port 80 and one for port 8080, which one do you want? You don't know, that is why you want it on a per-request basis. – revlayle May 06 '15 at 00:08
  • It's a pretty elegant solution. I found the need to get the 'base' domain in the app start and use it when JIT'ing the application. I ended up moving my logic into Begin_Request. The Application_Start is now empty and the Begin_Request contains the logic and a simple check on whether the domain is not null or empty. – Dan Atkinson Apr 13 '17 at 14:50
  • I'm curious, why two checks on the value of `host`? My guess is a concurrency issue in case the value is set in that small gap of time, but just double checking to see if this was a mistake. – trnelson Apr 21 '17 at 15:03
9

The accepted answer is good, but in most cases (if the first request is a HTTP Request) you should better use the Session_Start event, which is called once per user every 20 minutes or so (not sure how long the session is valid). Application_BeginRequest will be fired at every Request.

public void Session_Start(Object source, EventArgs e)
{
   //Request / Request.Url is available here :)
}
VladL
  • 12,769
  • 10
  • 63
  • 83
2

Just answering this so if someone ever decides to actually search on this topic...

This works on application start in any mode...

typeof(HttpContext).GetField("_request", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(HttpContext.Current)
Gh61
  • 9,222
  • 4
  • 28
  • 39
  • 3
    please note that field is non-public (i.e. private). You should be very careful to use non-documented features and fields as they can change without further information. – Stephen Reindl Mar 19 '15 at 20:53
  • And how is it different from `HttpContext.Current.Request`??? I see the same result – Andrii Dec 23 '17 at 13:23