81

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?

Andrey
  • 722
  • 2
  • 8
  • 17
Naftis
  • 4,393
  • 7
  • 63
  • 91
  • 1
    The answer [here](http://stackoverflow.com/a/1288383/1658297) helped me in a similar scenario. This answer addresses both the http/https and portnumbers. This is very useful as my local development is on http with a port number but the production solution is on https. – Sujeewa Jul 16 '14 at 19:57

7 Answers7

120

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

Meligy
  • 35,654
  • 11
  • 85
  • 109
  • Edited: if your request Uri had a query segment, You might also need to overwrite the Query property on the Uri builder! – Tim Lovell-Smith Feb 27 '14 at 18:07
  • Here's a quick summary post with all the options: http://benjii.me/2015/05/get-the-absolute-uri-from-asp-net-mvc-content-or-action/ – Ben Cull May 20 '15 at 08:23
35

From within the controller:

var path = VirtualPathUtility.ToAbsolute(pathFromPoco);
var url = new Uri(Request.Url, path).AbsoluteUri
Max Toro
  • 28,282
  • 11
  • 76
  • 114
Chris
  • 27,596
  • 25
  • 124
  • 225
19

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)
Jeff Tian
  • 5,210
  • 3
  • 51
  • 71
  • This is great. I actually wrote almost exactly what you suggested in your answer, but didn't think of adding it as an override to the Content method to make it even more lean. Thanks! – Neil Monroe May 01 '15 at 19:56
  • Thanks a lot for wonderful solution. I am using ng-include directive and I've had a lot of problems because of relative paths. Only thing that I've added in your code are '' around url. – FrenkyB Apr 15 '16 at 08:15
4

The built-in helpers in MVC 4 create absolute URLs if either the host or protocol parameters are non-empty. See this answer here with an example extension method for use in views.

Community
  • 1
  • 1
Carl G
  • 17,394
  • 14
  • 91
  • 115
1

In ASP.Net Core 2.0 (MVC) this works to create an absolute url to an action.

var url = Url.Action("About", "Home", new { /*Route values here*/ }, Request.Scheme);
brady321
  • 1,475
  • 13
  • 14
0

I wrote a helper class for this, for MVC 5... It's pretty flexible, and is particularly useful if you need this functionality when you aren't inside a controller. You should be able to drop it right into a project and go.

As Meligy pointed out, the key is to include the protocol. Here I have it hard coded as http, so if you want to use SSL that might need to become a bit more flexible.

public class AbsoluteUrlHelper
{
    /// <summary>
    /// Creates an absolute "fully qualified" url from an action, and assumes the current controller.
    /// </summary>
    /// <returns></returns>
    public static string GetAbsoluteUrl(string action, object routeValues = null)
    {
        var urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);
        var values = urlHelper.RequestContext.RouteData.Values;
        var controller = values["controller"].ToString();

        return GetAbsoluteUrl(action, controller, urlHelper, routeValues);
    }

    /// <summary>
    /// Creates an absolute "fully qualified" url from an action and controller.
    /// </summary>
    public static string GetAbsoluteUrl(string action, string controller, object routeValues = null)
    {
        var urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);

        return GetAbsoluteUrl(action, controller, urlHelper, routeValues);
    }

    /// <summary>
    /// Creates an absolute "fully qualified" url from an action and controller.
    /// </summary>
    public static string GetAbsoluteUrl(string action, string controller, UrlHelper urlHelper, object routeValues = null)
    {
        var uri = urlHelper.Action(action, controller, routeValues, "http");

        return uri;
    }
}
Brian MacKay
  • 31,133
  • 17
  • 86
  • 125
-5

You have a few options:

  • Save the value of HttpContext.Request.Url in a static or member variable, and use that to pass the Fully-qualified path.
  • Save the app domain in an app setting in the web.config.
  • Hard-code the value.
Keith
  • 5,311
  • 3
  • 34
  • 50