How can I resolve ASP.NET "~" app paths to the website root without a Control being present?
Asked Answered
I

6

16

I want to Resolve "~/whatever" from inside non-Page contexts such as Global.asax (HttpApplication), HttpModule, HttpHandler, etc. but can only find such Resolution methods specific to Controls (and Page).

I think the app should have enough knowledge to be able to map this outside the Page context. No? Or at least it makes sense to me it should be resolvable in other circumstances, wherever the app root is known.

Update: The reason being I'm sticking "~" paths in the web.configuration files, and want to resolve them from the aforementioned non-Control scenarios.

Update 2: I'm trying to resolve them to the website root such as Control.Resolve(..) URL behaviour, not to a file system path.

Isaacson answered 7/4, 2010 at 1:57 Comment(1)
Duplicated: #27296Christelchristen
C
41

Here's the answer: ASP.Net: Using System.Web.UI.Control.ResolveUrl() in a shared/static function

string absoluteUrl = VirtualPathUtility.ToAbsolute("~/SomePage.aspx");
Christelchristen answered 7/4, 2010 at 3:18 Comment(1)
exactly what I was about to post :)Extort
J
1

You can do it by accessing the HttpContext.Current object directly:

var resolved = HttpContext.Current.Server.MapPath("~/whatever")

One point to note is that, HttpContext.Current is only going to be non-null in the context of an actual request. It's not available in the Application_Stop event, for example.

Jewbaiting answered 7/4, 2010 at 2:5 Comment(1)
I updated the question because I'm trying to resolve to a URL, not to the file system.Isaacson
F
1

In Global.asax add the following:

private static string ServerPath { get; set; }

protected void Application_BeginRequest(Object sender, EventArgs e)
{
    ServerPath = BaseSiteUrl;
}

protected static string BaseSiteUrl
{
    get
    {
        var context = HttpContext.Current;
        if (context.Request.ApplicationPath != null)
        {
            var baseUrl = context.Request.Url.Scheme + "://" + context.Request.Url.Authority + context.Request.ApplicationPath.TrimEnd('/') + '/';
            return baseUrl;
        }
        return string.Empty;
    }
}
Fizz answered 18/2, 2013 at 11:7 Comment(0)
I
0

I haven't debugged this sucker but am throwing it our there as a manual solution for lack of finding a Resolve method in the .NET Framework outside of Control.

This did work on a "~/whatever" for me.

/// <summary>
/// Try to resolve a web path to the current website, including the special "~/" app path.
/// This method be used outside the context of a Control (aka Page).
/// </summary>
/// <param name="strWebpath">The path to try to resolve.</param>
/// <param name="strResultUrl">The stringified resolved url (upon success).</param>
/// <returns>true if resolution was successful in which case the out param contains a valid url, otherwise false</returns>
/// <remarks>
/// If a valid URL is given the same will be returned as a successful resolution.
/// </remarks>
/// 
static public bool TryResolveUrl(string strWebpath, out string strResultUrl) {

    Uri uriMade = null;
    Uri baseRequestUri = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority));

    // Resolve "~" to app root;
    // and create http://currentRequest.com/webroot/formerlyTildeStuff
    if (strWebpath.StartsWith("~")) {
        string strWebrootRelativePath = string.Format("{0}{1}", 
            HttpContext.Current.Request.ApplicationPath, 
            strWebpath.Substring(1));

        if (Uri.TryCreate(baseRequestUri, strWebrootRelativePath, out uriMade)) {
            strResultUrl = uriMade.ToString();
            return true;
        }
    }

    // or, maybe turn given "/stuff" into http://currentRequest.com/stuff
    if (Uri.TryCreate(baseRequestUri, strWebpath, out uriMade)) {
        strResultUrl = uriMade.ToString();
        return true;
    }

    // or, maybe leave given valid "http://something.com/whatever" as itself
    if (Uri.TryCreate(strWebpath, UriKind.RelativeOrAbsolute, out uriMade)) {
        strResultUrl = uriMade.ToString();
        return true;
    }

    // otherwise, fail elegantly by returning given path unaltered.    
    strResultUrl = strWebpath;
    return false;
}
Isaacson answered 7/4, 2010 at 2:26 Comment(0)
C
0
public static string ResolveUrl(string url)
{
    if (string.IsNullOrEmpty(url))
    {
        throw new ArgumentException("url", "url can not be null or empty");
    }
    if (url[0] != '~')
    {
        return url;
    }
    string applicationPath = HttpContext.Current.Request.ApplicationPath;
    if (url.Length == 1)
    {
        return applicationPath;
    }
    int startIndex = 1;
    string str2 = (applicationPath.Length > 1) ? "/" : string.Empty;
    if ((url[1] == '/') || (url[1] == '\\'))
    {
        startIndex = 2;
    }
    return (applicationPath + str2 + url.Substring(startIndex));
}
Christelchristen answered 7/4, 2010 at 3:9 Comment(0)
S
0

Instead of using MapPath, try using System.AppDomain.BaseDirectory. For a website, this should be the root of your website. Then do a System.IO.Path.Combine with whatever you were going to pass to MapPath without the "~".

Selfmortification answered 7/4, 2010 at 3:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.