9

I'm aware that there are easier ways to do this and believe me, I've tried them. I'm of course open to any suggestions =). You don't need to read the whole code, just the part that says where the problem lies. Also, I'm debbugging perl style so you guys can see. Oh and did I mention that on my development environment everything works as intended?

Here's the code:

string GetPortalAlias()
{
    String myURL2 = Request.Url.ToString();
    URLLabel.Text = "Original Request.Url.ToString() returned: \"" + myURL2 + "\"";
    string myURL = string.Copy(myURL2);
    URLLabel.Text = "Copying it to myURL, it's now: \"" + myURL + "\"";
    myURL = myURL.ToLower().Trim();
    URLLabel.Text += "<br>Trimming and ToLower myURL.<br>The new url is \"" + myURL + "\"" + "<br>";
    myURL = myURL.Replace(":80", "");
    URLLabel.Text += "Replacing the \":80\".<br> The new url is\"" + myURL + "\"<br>";


    //***HERE LIES THE PROBLEM***
    myURL = myURL.Replace("http://", "");
    URLLabel.Text += "Replacing the \"http://\".<br> The new url is\"" + myURL + "\"<br>";
    //***PROBLEM ENDS***


    myURL = myURL.Remove(myURL.IndexOf("/"));
    URLLabel.Text += "Removing everything after the \"/\"." + "<br> The new url is \"" + myURL + "\"<br>";
    URLLabel.Text += "<br>GetPortalAlias Returning \"" + myURL + "\"";
    return myURL;
}

Believe it or not, the output produced in the webpage is this:

output

Copying it to myURL, it's now: "http://sar.smg.com.ar/Default.aspx?TabID=912"
Trimming and ToLower myURL.
The new url is "http://sar.smg.com.ar/default.aspx?tabid=912"
Replacing the ":80".
The new url is"http://sar.smg.com.ar/default.aspx?tabid=912"
Replacing the "http://".
The new url is"intranetqa/default.aspx?tabid=912"
Removing everything after the "/".
The new url is "intranetqa"

GetPortalAlias Returning "intranetqa" 

So... for some reason whenever it reaches the replace section it mysteriously mutates to start with "intranetqa" instead of "sar.smg.com.ar". "intranetqa" is our default hostname. CHANGING OR TAKING AWAY ANY CHARACTER OF HTTP:// IN ANY WAY MUTATES THE STRING.

I do a string.copy because I'm aware that if two strings are equal the compiler stores them in the same place therefore I wanted to prevent errors. Taking those lines away and use Request.Url.ToString() tomyURL directly does nothing at all. They were just a test to see if that worked.

Here's a list of the things I've tried:

  • All combinations of string / String, none worked.
  • I've tried Request.Host.Url and it just gave me "intranetqa".
  • I've used Request.Url.AbsoluteUri and that's why I have the replace :80 line.
  • USING THE .tochararray FUNCTION GIVES ME BACK THE INTRANETQA THING
  • myURL = myURL.Substring(6) gives back the intranetqa thing.
  • string.Contains("sar.smg.com.ar") gives back false.

I believe the trick lies around here:

  • Uri uriAddress1 = Request.Url; and "The parts are <br>" + "Part 1: " + uriAddress1.Segments[0] + "<br>Part 2: " + uriAddress1.Segments[1]; Gives Part1 : "/" and Part 2: "Default.aspx". Trying to access part 3 (index 2) gives an exception. The request.url does not have the first part, but when I call the ToString() method, it does have like a "fake" first part
Gaspa79
  • 5,488
  • 4
  • 40
  • 63
  • 2
    Did you try turn it off and back on again? – deanvmc Oct 16 '12 at 14:44
  • This is probably not important, but I notice you are using a capitol `S` for the first string, and not the second, replace the `S` with an `s` on the first one and try it? – Serdalis Oct 16 '12 at 14:45
  • Can not reproduce this issue at all, have you restarted visual studio or your computer at all? May be worth trying that and seeing if it persists. – Ryan McDonough Oct 16 '12 at 14:45
  • Haven't you heard, strings are immutable. – Jodrell Oct 16 '12 at 14:46
  • 1
    @Serdalis `String`/`string` are exactly the same. It seems as though your host name is being replaced by the local host name. – James Oct 16 '12 at 14:47
  • 3
    1. The screen shot is very hard to read, copying the text out into a `
    ` in your question would help. 2. If you cannot re-create this in a fresh console app (or similar) then it is something else in the web app (eg. something else is modifying `URLLabel.Text`). Perhaps seeing what a debugger shows before and after the problematic replace?
    – Richard Oct 16 '12 at 14:48
  • @James yes I know, but an error as weird as this might have an equally weird origin. – Serdalis Oct 16 '12 at 14:48
  • I've tried String and string and using just 1 variable and all permutations of String/string. None worked. I've restarted my visual studio, the server's IIS and actual computer. No success. I swear I'm not trolling – Gaspa79 Oct 16 '12 at 14:49
  • @James YES!! That's exactly what is going on. Intranetqa is the default hostname. – Gaspa79 Oct 16 '12 at 14:49
  • Stupid, obvious question, but why is `Request.Url.Host` not the answer to this entire method? – Damien_The_Unbeliever Oct 16 '12 at 14:51
  • @Damieh try getting rid of your call to `string.Copy` at the beginning of the call and just do a straight assignment. – James Oct 16 '12 at 14:51
  • @Damien_The_Unbeliever I tried and Request.Url.Host just gives back intranetqa instead of sar.smg – Gaspa79 Oct 16 '12 at 14:53
  • What happens if you use a different variable name, like `_tempURLString`? Although it's a long shot I wonder if `myURL` is colliding with some default automatic property, and in the page it occasionally gets the scope wrong and so gets some "myURL" property of an enclosing scope rather than the local variable. – Joshua Honig Oct 16 '12 at 14:53
  • @James I got rid of string.copy. I originally didn't have string.copy. That was just a test, as it was string/String, string.tochararray and string.contains. – Gaspa79 Oct 16 '12 at 14:53
  • @jmh_gr I'll try that now, let's see – Gaspa79 Oct 16 '12 at 14:55
  • 1
    What happens _after_ method `GetPortalAlias` was called? Might it be that some other parts of the program work with text of `URLLabel` and alter it anyhow? Try introducing a new label and using it instead of `URLLabel` to make sure nothing happens with its value. – Andrei Oct 16 '12 at 14:58
  • Apart from lots of ugly string manipulation with the request url what are you actually trying to ahceive? – Jodrell Oct 16 '12 at 14:59
  • @jmh_gr Nope, changing the variable name to _tempString790 did nothing. – Gaspa79 Oct 16 '12 at 15:01
  • @Jodrell I'm trying to check server side if the URL that was typed by the user matches a list of urls I have. – Gaspa79 Oct 16 '12 at 15:02
  • @Damieh, so you want to extract the host name from a URL (Reliably)? – Jodrell Oct 16 '12 at 15:05
  • I bet the string doesn't change. Maybe URLLabel displays it differently, when it's not prefixed by "http://". Try adding `URLLabel.Text += "Test http://" + myURL + "
    ";` after the problematic line.
    – Henrik Oct 16 '12 at 15:12
  • @Henrik it just displays http://intranetqa. However, maybe the string is displayed incorrectly. But I've used the debugger on development environment and awkwardly, it shows sar.smg.com.ar till the problematic line. Meaning that if it's a display problem, it also happens in the debbugger. – Gaspa79 Oct 16 '12 at 15:24
  • Can you try once turning off String Interning for the assembly in which code is written by applying CompilationRelaxations assembly level attribute? Not sure but just one more thing to try. – jags Oct 16 '12 at 15:33
  • @jags I'll google this and try. Let's see. Thanks! =) – Gaspa79 Oct 16 '12 at 15:39
  • I had a sudden intuition about an hour ago, but that was just after I left the office and it's taken this long for me to post an answer. I don't believe it's actually anything to do with string manipulation in your code. – Damien_The_Unbeliever Oct 16 '12 at 16:00
  • @Damien_The_Unbeliever I started to believe that too when I used the .toCharArray function. It always gives intranetqa. Also, the request.url doesn't have neither intranetqa nor sar.smg.com.ar on it's parts. Both things are giving hints that it's just the display that is wrong, not the replacing functions. – Gaspa79 Oct 16 '12 at 16:06

5 Answers5

11

Between your browser and the server are a reverse proxy and an output re-writer. These may be the same component, or separate components.

The URL your server actually sees is always of the form http://intranetqa/default.aspx?tabid=912 (after the reverse proxy/URL re-writer has intercepted the request).

The output your server produces is actually like:

Copying it to myURL, it's now: "http://intranetqa/Default.aspx?TabID=912"
Trimming and ToLower myURL.
The new url is "http://intranetqa/default.aspx?tabid=912"
Replacing the ":80".
The new url is"http://intranetqa/default.aspx?tabid=912"
Replacing the "http://".
The new url is"intranetqa/default.aspx?tabid=912"
Removing everything after the "/".
The new url is "intranetqa"

GetPortalAlias Returning "intranetqa" 

The output re-writer is inspecting the output from your server and doing a replace of http://intranetqa with http://sar.smg.com.ar. Once you strip the http:// off of the front of these strings, it's no longer a match and so replacement no longer occurs.

If you want to know what the original requesting URL/host are, hopefully the reverse proxy either is, or can be configured to, adding an extra header to the request with the original URL.

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
  • This is great!!! But wait... this means that there's no way I can get the original url? Maybe is it stored on a server variable? Also, How can I configure the reverse proxy like that? Ofcourse I'm gonna google it now but if you took this out from a link then please send it to me =). Thanks a lot Damien. – Gaspa79 Oct 16 '12 at 16:03
  • 1
    @Damieh - No, this wasn't from a link. Just a sudden realisation of a completely different situation that matches all of your symptoms. The reverse proxy is almost certainly hosted on the machine that responds at `sar.smg.com.ar` - you need to talk to the people who administer that machine. Alternatively, re-write your current method to instead iterate through the `Request.Headers` property and look at the header names - you may spot one which seems a likely candidate - it may already be there. – Damien_The_Unbeliever Oct 16 '12 at 16:07
  • Wow, just wow. I'll try and see if the original url is there. I'll get back to you and tell you if it worked =). Seriously: I'm really really grateful! – Gaspa79 Oct 16 '12 at 16:12
  • I just got access to that machnine's IIS and there's no binding for "sar.smg.com.ar" just for the internal "intranetqa". Meaning that you're right and the server sees it as "intranetqa" because if not, it wouldn't be able to match the site! – Gaspa79 Oct 16 '12 at 16:21
  • 2
    So, basically, the string has `http://intranetqa` in it all along, but whenever it displays that link it's being converted to `http://sar.smg.com.ar`... up until the "http://" is gone, and it no longer is recognized? Wow. That is a really impressive deduction. – Bobson Oct 16 '12 at 16:49
  • 2
    @Bobson - the weird part was, as soon as I could see it, I assumed it was obvious. I was sure that by the time I finished my commute home, someone else would have posted the equivalent answer. – Damien_The_Unbeliever Oct 16 '12 at 17:22
  • Let me clarify, you are saying the response (containing the debug text) is parsed and embedded urls are substituted for the url the user typed? – Jodrell Oct 17 '12 at 08:24
  • 1
    @Jodrell - it may be the url the user typed, it may be a fixed string. Basically, there's a URL re-writer in there that's inspecting and modifying the output content. See e.g. [Creating Outbound Rules for URL Rewrite Module](http://www.iis.net/learn/extensions/url-rewrite-module/creating-outbound-rules-for-url-rewrite-module) for one way it can be done if IIS is doing it. – Damien_The_Unbeliever Oct 17 '12 at 08:30
  • Inspired deduction +1, so, the observed bug is an incompatability between the debugging technique and the server configuration (i.e. the Rewrite Module.) If the inbound rewriter embeded the substituted value in the request somehow ... – Jodrell Oct 17 '12 at 08:56
  • @Jodrell - that's what my comment about having the reverse proxy adding the original URL as a separate header was about. – Damien_The_Unbeliever Oct 17 '12 at 14:16
  • @Damien_The_Unbeliever So I already solved this, got rid of the rewrite entirely and forwarded the url request without doing an url rewrite and instead binding the address which was being rewrited (sar.smg.com.ar). Everything started working as intended. I even got congratulated because other things that didn't work started working. I told them I owed everything to a guy I met on the internet who is also named Damien =). Thanks again! UPVOTE THIS MAN! – Gaspa79 Oct 17 '12 at 15:13
1

You can try something like this

Uri uriAddress1 = new Uri("http://www.contoso.com/title/index.htm");
Console.WriteLine("The parts are {0}, {1}, {2}", uriAddress1.Segments[0], uriAddress1.Segments[1], uriAddress1.Segments[2]);

Uri.Segments Property

This is better way to handle URIs and their segments.

Amit
  • 21,570
  • 27
  • 74
  • 94
  • Okay this is reaaally strange: Here's what I get out of this. Part 0 is just "/" and Part 1 is Default.aspx. Trying to access part 2 gives an exception. Any ideas? – Gaspa79 Oct 16 '12 at 15:22
1

Don't you want to achieve part of what is done here?

Something like

string host = Request.Url.IsDefaultPort ?
    Request.Url.Host :
    Request.Url.Authority;

If you want to persist with the old method change it like this

string GetPortalAlias()
{
    var rawUrl = Request.Url.ToString();
    var lowerTrimmedUrl = rawUrl.ToLower().Trim();
    var withoutPortUrl = lowerTrimmedUrl.Replace(":80", "");
    var withoutProtocolUrl = withoutPortUrl.Replace("http://", "");
    var justHostUrl = withoutProtocolUrl.Remove(myURL.IndexOf("/"));

    var evolution = new StringBuilder();
    evolution.AppendFormat(
        "{0}<br>", 
        HttpUtility.HtmlEncode(rawUrl));
    evolution.AppendFormat(
        "{0}<br>",
        HttpUtility.HtmlEncode(lowerTrimmedUrl));
    evolution.AppendFormat(
        "{0}<br>",
        HttpUtility.HtmlEncode(withoutPortUrl));
    evolution.AppendFormat(
        "{0}<br>",
        HttpUtility.HtmlEncode(withoutProtocolUrl));
    evolution.AppendFormat(
        "{0}<br>",
        HttpUtility.HtmlEncode(justHostUrl));

    URLLabel.Text = evolution.ToString();
    return justHostUrl;
}

So you can see whats going on.

Community
  • 1
  • 1
Jodrell
  • 34,946
  • 5
  • 87
  • 124
  • Yes and no, I want to served-sided get the host that the user actually typed. Request.Url.Host will give me the default host (intranetqa), which is not necessarily what the user typed (sar.smg.com.ar) – Gaspa79 Oct 16 '12 at 15:20
  • @Damieh I hope the encoding would fix any display issues you have. – Jodrell Oct 16 '12 at 16:30
1

Try to use this property instead:

String myURL2 = Request.Url.AbsoluteUri;
  • I did that and that's why I have the myURL.Replace(":80",""); line. Because that absoluteUri returns a :80 also. – Gaspa79 Oct 16 '12 at 15:03
1

Here is an Extension method that I use to pull the SiteRootPath. You should be able to easily adjust it however you need it. You will need access to the HttpContext for what I currently have below, however, you don't sound like you need that.

using System;
using System.Web;

namespace FlixPicks.Web.Extensions
{
    public static class HttpContextExtensions
    {
        public static string SiteRootPath(this HttpContext context)
        {
            if (context == null || context.Request == null) { return null; }

            return context.Request.Url.SiteRootPath(context.Request.ApplicationPath);
        }

        public static string SiteRootPath(this HttpContextBase context)
        {
            return context.Request.Url.SiteRootPath(context.Request.ApplicationPath);
        }

        private static string SiteRootPath(this Uri url, string applicationPath)
        {
            if (url == null) { return null; }

            // Formatting the fully qualified website url/name.
            string appPath = string.Format(
                        "{0}://{1}{2}{3}",
                        url.Scheme,
                        url.Host,
                        url.Port == 80 ? string.Empty : ":" + url.Port,
                        applicationPath);

            // Remove ending slash(es) if one or more exists to consistently return
            // a path without an ending slash.  Could have just as well choosen to always include an ending slash.
            while (appPath.EndsWith("/") || appPath.EndsWith("\\"))
            {
                appPath = appPath.Substring(0, appPath.Length - 1);
            }

            return appPath;
        }
    }
}

Good luck, Tom

Thomas
  • 3,532
  • 3
  • 20
  • 22
  • Apparently this is for 4.0 because there's no such thing as Request.Url.SiteRootPath in 3.5 Am I right? – Gaspa79 Oct 16 '12 at 15:45
  • 1
    @Damieh SiteRootPath is an Extension method that I included here. You will need to include the namespace for this extension class in the spot you are using it. – Thomas Oct 23 '12 at 18:48