ChatGPT解决这个技术问题 Extra ChatGPT

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?

The answer here 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.

M
Meligy

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


Edited: if your request Uri had a query segment, You might also need to overwrite the Query property on the Uri builder!
Here's a quick summary post with all the options: benjii.me/2015/05/…
M
Max Toro

From within the controller:

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

VirtualPathUtility still returns a relative Uri in MVC4 controller
And combined with the Uri class, that's all you need. Kind of a pointless comment.
I would first pass your path through the Url.Content() method. This answer will fail for paths that are not absolute (start with '/').
J
Jeff Tian

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)

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!
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.
C
Community

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.


b
brady321

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);

B
Brian MacKay

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;
    }
}

K
Keith

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.