views:

150

answers:

5

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.

A: 

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.

Dean Harding
I updated the question because I'm trying to resolve to a URL, not to the file system.
John K
A: 

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;
}
John K
A: 
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));
}
Max Toro
+2  A: 

Here's the answer: http://stackoverflow.com/questions/26796/asp-net-using-system-web-ui-control-resolveurl-in-a-shared-static-function

string absoluteUrl = VirtualPathUtility.ToAbsolute("~/SomePage.aspx");
Max Toro
exactly what I was about to post :)
rob_g
A: 

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 "~".

Mike Schall