Odd string.Replace Chaining Behavior
I ran into a bit of a head scratcher today with a routine that does some string manipulation. It's an old routine that I use to help me do the equivalent of ResolveUrl() outside of the context of the ASP.NET Page framework - typically in static code somewhere or as part of a handler or other component.
The process is easy enough but I ran into a snag with the special case of resolving a root web path (ie. /wwbanner.ashx for example) and the routine has some admittedly hacky code that checks for the possibility of duplicated slashes in the front. So basically there's some code that looks like this:
newUrl = HttpContext.Current.Request.ApplicationPath +originalUrl.Substring(1).Replace("//","/");
Now that seems reasonable to me and I could swear that this code should work.
However it doesn't. If I pass in ~/wwbanner.ashx with a root web the URL gets generated as:
//wwbanner.ashx
which oddly enough goes out and downloads a whole HTML page from some PHP server off the Web (which is really quite a bizarre matter all on its own).
Honestly I can't figure out though why the above code DOESN'T work. The last Replace() at the end of the string expression should handle the double forward slashes. If I explicitly put the Replace() portion onto a separate line of code the code starts working properly:
newUrl = HttpContext.Current.Request.ApplicationPath +originalUrl.Substring(1);
newUrl = newUrl.Replace("//", "/");
this properly produces:
/wwbanner.ashx
which works as expected and properly fires my local banner manager in the site.
Anybody see which part of the forest I'm missing here and why the first fails and the latter works? It seems to me I SHOULD be able to chain string commands together and get expectable results - in fact I'm pretty sure I do this in other places and it works just fine. But somehow in this scenario it seems that .Replace() in particular is not behaving properly. <shrug>
Other Posts you might also like
- Adding minimal OWIN Identity Authentication to an Existing ASP.NET MVC Application
- Getting the Client IP Address in ASP.NET Core
- Map Physical Paths with an HttpContext.MapPath() Extension Method in ASP.NET
- Getting the ASP.NET Core Server Hosting Urls at Startup and in Requests
- Creating Dual Use Windows GUI and Console Applications
The Voices of Reason
# re: Odd string.Replace Chaining Behavior
newUrl = (HttpContext.Current.Request.ApplicationPath +
originalUrl.Substring(1)).Replace("//","/");
Otherwise you are only doing the replace on the substring(1), which isnt going to match?
# re: Odd string.Replace Chaining Behavior
# re: Odd string.Replace Chaining Behavior
# re: Odd string.Replace Chaining Behavior
A nice day to you all from Germany!
# re: Odd string.Replace Chaining Behavior
http://msdn2.microsoft.com/en-us/library/system.web.virtualpathutility.aspx
newUrl = VirtualPathUtility.ToAbsolute(originalUrl);
# re: Odd string.Replace Chaining Behavior
newUrl = (HttpContext.Current.Request.ApplicationPath +
originalUrl).Substring(1).Replace("//","/");
the other slash is coming from the applicationPath
# re: Odd string.Replace Chaining Behavior
newUrl = (HttpContext.Current.Request.ApplicationPath +
originalUrl.Substring(1)).Replace("//","/");
but you are not actually using HttpContext.Current.Request.ApplicationPath, are you?
# re: Odd string.Replace Chaining Behavior
http://www.west-wind.com/WebLog/posts/154812.aspx
which (if you look through the comments) goes through a whole bunch of the issues. The end result was the above function (or part of it anyway).
# re: Odd string.Replace Chaining Behavior
# re: Odd string.Replace Chaining Behavior
# re: Odd string.Replace Chaining Behavior
Are you using openDNS? If so, it will auto-redirect your DNS query to a likely match, and your program will be none the wiser.
# re: Odd string.Replace Chaining Behavior
# re: Odd string.Replace Chaining Behavior
When moving code like this that worked fine on localhost to another hosting environment, for example, Request.ApplicationPath may or may not return a trailing forward slash.
So if Requestion.Application Path returns /YourWebSite, concatenating the strings will work fine. But if it returns "/", you will concat this to the string replace function that has been computed to begin with a forward slash.
Here is what I do: Some new things here:
public static string ResolveUrl(string originalUrl)
{
if (String.IsNullOrEmpty(originalUrl))
return String.Empty;
if (Regex.IsMatch(originalUrl, "http(s?):|www."))
return originalUrl;
if (Regex.IsMatch(originalUrl, "~/[^/]"))
{
string newUrl = "";
if (HttpContext.Current != null)
{
newUrl = String.Concat(MyApplicationPath, originalUrl.Replace("~/", ""));
}
else
throw new ArgumentException("Invalid URL: Relative URL not allowed.");
return newUrl;
}
return originalUrl;
}
private static string m_appPath = String.Empty;
public static string MyApplicationPath
{
get
{
if (String.IsNullOrEmpty(m_appPath))
{
m_appPath = HttpContext.Current.Request.ApplicationPath;
m_appPath = m_appPath.EndsWith("/") ? m_appPath : String.Concat(m_appPath, "/");
}
return m_appPath;
}
}
# re: Odd string.Replace Chaining Behavior
everything works as expected:
In the first snippet, the Replace function is applied to the Substring(1) of the originalUrl, which means it is applied to "/wwbanner.ashx". Here it can't find any double slashes and does nothing. This results in "/" + "/wwbanner.ashx" = "//wwbanner.ashx".
In the second snippet, the two strings are FIRST put together, thus producing "//wwbanner.ashx" first. Replace applied on this string, is now able to do its work as it finds the double slash at the beginning. Thus it produces "/wwbanner.ashx".
Don't start downloading the .net symbols, everything's fine ;-)
HTH, Dennis