Friday, February 4, 2011

Asp.net path compaction

I have an asp.net url path which is being generated in a web form, and is coming out something like "/foo/bar/../bar/path.aspx", and is coming out in the generated html like this too. It should be shortened to "/foo/bar/path.aspx".

Path.Combine didn't fix it. Is there a function to clean this path up?

  • You could create a helper class which wrapped the UriBuilder class in System.Net

    public static class UriHelper
    {       
        public static string NormalizeRelativePath(string path)
        {
      UriBuilder _builder = new UriBuilder("http://localhost");
         builder.Path = path;
         return builder.Uri.AbsolutePath;
        }
    }
    

    which could then be used like this:

    string url = "foo/bar/../bar/path.aspx";
    Console.WriteLine(UriHelper.NormalizeRelativePath(url));
    

    It is a bit hacky but it would work for the specific example you gave.

    EDIT: Updated to reflect Andrew's comments.

    From Sarcastic
  • Sarcastic's reply is so much better than mine, but if you were working with filesystem paths, my ugly hack below could turn out to be useful too. (Translation: I typed it, so I'll be damned if I don't post it :)

    Path.Combine just slaps two strings together, paying attention to leading or trailing slashes. As far as I know, the only Path method that does normalization is Path.GetFullPath. The following will give you the "cleaned up" version.

    myPath = System.IO.Path.GetFullPath(myPath);
    

    Of course, there is the small issue that the resulting path will be rooted and the forward slashes will be converted to back slashes (like "C:\foo\bar\path.aspx"). But if you know the parent root of the original path, stripping out the root should not be a big problem.

    From Ishmaeel
  • Whatever you do, don't use a static UriBuilder. This introduces all sorts of potential race conditions that you might not detect until you are under heavy load.

    If two different threads called UriHelper.NormalizeRelativePath at the same time, the return value for one could be passed back to the other caller arbitrarily.

    If you want to use UriBuilder to do this, just create a new one when you need it (it's not expensive to create).

    Sarcastic : @Andrew Very good point about the static UrlBuilder instance. I shall pray for forgiveness to the gods of multi-threading.

0 comments:

Post a Comment