Getting Absolute URL from an ASP.NET MVC Action

This probably is a dummy question but I cannot find a clear indication. I have a POCO class in a MVC3 web application whose only purpose is managing the backup of some files in the server. Typically it creates a backup and returns the filename to the controller, which sends an email with the URL for downloading it. This works fine, but I cannot build the absolute URL to be sent. No matter which function I use, I always get a relative URL, like /Backup/TheFile.zip, rather than e.g. http://www.somesite.com/Backup/TheFile.zip. I tried:

VirtualPathUtility.ToAbsolute("~/Backup/SomeFile.zip");
HttpRuntime.AppDomainAppVirtualPath + "/Backup/SomeFile.zip";
Url.Content("~/Backup/SomeFile.zip");

but they all return something like /Backup/SomeFile.zip. Any idea?


You can do it by the following:

var urlBuilder =
    new System.UriBuilder(Request.Url.AbsoluteUri)
        {
            Path = Url.Action("Action", "Controller"),
            Query = null,
        };

Uri uri = urlBuilder.Uri;
string url = urlBuilder.ToString();
// or urlBuilder.Uri.ToString()

Instead of Url.Action() in this sample, you can also use Url.Content(), or any routing method, or really just pass a path.

But if the URL does go to a Controller Action, there is a more compact way:

var contactUsUriString =
    Url.Action("Contact-Us", "About",
               routeValues: null /* specify if needed */,
               protocol: Request.Url.Scheme /* This is the trick */);

The trick here is that once you specify the protocol/scheme when calling any routing method, you get an absolute URL. I recommend this one when possible, but you also have the more generic way in the first example in case you need it.

I have blogged about it in details here:
http://gurustop.net/blog/2012/03/23/writing-absolute-urls-to-other-actions-in-asp-net-mvc/

Extracted from Meligy’s AngularJS & Web Dev Goodies Newsletter


From within the controller:

var path = VirtualPathUtility.ToAbsolute(pathFromPoco);
var url = new Uri(Request.Url, path).AbsoluteUri

This works for me:

using System;
using System.Web;
using System.Web.Mvc;

public static class UrlExtensions
{
    public static string Content(this UrlHelper urlHelper, string contentPath, bool toAbsolute = false)
    {
        var path = urlHelper.Content(contentPath);
        var url = new Uri(HttpContext.Current.Request.Url, path);

        return toAbsolute ? url.AbsoluteUri : path;
    }
}

Usage in cshtml:

@Url.Content("~/Scripts/flot/jquery.flot.menuBar.js", true)