7

I need to create an absolute URL to specific files in my ASP.NET MVC 4 application. I am currently doing this by generating a relative path via Url.Content and then using the following extension method to create the absolute path.

public static string Absolute(this UrlHelper url, string relativeUrl)
{
    var request = url.RequestContext.HttpContext.Request;
    return string.Format("{0}://{1}{2}{3}", 
        (request.IsSecureConnection) ? "https" : "http", 
        request.Url.Host, 
        (request.Url.Port == 80) ? "" : ":" + request.Url.Port, 
        VirtualPathUtility.ToAbsolute(relativeUrl));
}

When running under the Azure Emulator, the proper URL that I need to create is http://127.0.0.1/myfile.jpg but when this code executes, the port number comes back as 81 so the URL that is generated is http://127:0.0.1:81/myfile.jpg. However, if I go to http://127:0.0.1:81/myfile.jpg it of course doesn't work as the Azure Emulator is listening on port 80, not 81.

I assume this has to do with the built in Azure Emulator/IIS Express load balancer, but I am not sure what change I need to make to my Url.Absolute method to return an accurate URL.

user2719100
  • 1,704
  • 3
  • 20
  • 25

3 Answers3

7

You can rely on the Host header that is being sent by the client:

public static string Absolute(this UrlHelper url, string relativeUrl)
{
    var request = url.RequestContext.HttpContext.Request;

    return string.Format("{0}://{1}{2}",
        (request.IsSecureConnection) ? "https" : "http",
        request.Headers["Host"],
        VirtualPathUtility.ToAbsolute(relativeUrl));
}
haim770
  • 48,394
  • 7
  • 105
  • 133
  • Will the host header also include the port number if it exists? eg. if the application is legitimately deployed at, say, http://www.contoso.com:999/ will the header be "www.contoso.com:999"? – user2719100 Aug 26 '13 at 21:06
3

Why not just use @Url.Content("~/myfile.jpg");? This converts a virtual (relative) path to an application absolute path and works finle in IIS,the emulator and when deployed. See UrlHelper.Content Method

viperguynaz
  • 12,044
  • 4
  • 30
  • 41
  • 2
    Application-absolute-path is not absolute-path. `/Content/Img/myfile.jpg` != `http://127.0.0.1/Content/Img/myfile.jpg` – haim770 Aug 26 '13 at 20:44
  • @haim770 is correct. I need the full absolute path, including the protocol, domain and port. – user2719100 Aug 26 '13 at 20:46
1

I've written a summary post that shows all the options here: http://benjii.me/2015/05/get-the-absolute-uri-from-asp-net-mvc-content-or-action/

The quick and simple answer is this:

var urlBuilder =
    new System.UriBuilder(Request.Url.AbsoluteUri)
        {
            Path = Url.Content("~/path/to/anything"),
            Query = null,
        };

string url = urlBuilder.ToString();
Ben Cull
  • 9,434
  • 7
  • 43
  • 38