title: How to change http/https Protocol while using relative URL
body: <p>Protocol-relative URLs <em>aren't</em> what I'm looking for.  I'm looking for a way of absolutely specifying a protocol (http vs https) while keeping the host name of the url relative.</p>
  
  <p>Given a relative URL such as "/SearchForStuff" I want to be able to specify a different protocol "https vs. http" etc. without having to specify a host/domain name.</p>
  
  <p>Our site has a header partial view which we display across the top of every page on our site.  Some pages on the site are http and some are https.  The header contains a textbox and button for site-wide search.  The site search results page is always provided using http, so we want the form action to point to a relative path, "/find".  However, we want the same header to work on our many internal test servers (10.10.10.123 etc.) as well as our public facing server ("www.publicfacingserver.com"), ideally without changing the content of the header partial view. So essentially what I'm looking for is a way of specifying a protocol for the search  action while keeping the server/host name relative.   </p>
  
  <p>Currently, to ensure that it is not possible for a user to link from a secured page to a secured page of site search results, we hard-code the absolute url of the action used for site search, complete with the protocol and host name, such as "http://www.publicsite.com/find".  The problem is that clicking on that action on a <strong>test server</strong> redirects you back to our <strong>public-facing</strong> site.  So for testing, we make manual edits to our hosts file for the test server's IP address to equal our public facing site name.  This puts a bit of cognitive burden on ourselves as developers, and also requires us to visit the computer of any non-coding person who we wish to test our site to configure their hosts file prior to testing, and after testing to de-configure the changes to their hosts file.</p>
  
  <p>The code below is the best solution I have come up with.  Does anyone know of a better way?  If my solution is adequate, does it create any security vulnerabilities?  I don't see how it could, since if a malicious user were to forge a request to our public facing IP address X but with a host name in the host header which did not match that IP address, this would only result in wonky URLs being provided back to the same user.  In other words, I don't see how anyone could use this to create an XSRF exploit by posting a URL in a message board on another site, or anything similar:</p>
  
  <pre><code>public static string CurrentHostName(this UrlHelper helper, HttpProtocol protocol)
  {
      var result = string.Empty;
  
      if (protocol == HttpProtocol.Secure) result += "https://";
      if (protocol == HttpProtocol.UnSecure) result += "http://";
      if (protocol == HttpProtocol.Current) result += HttpContext.Current.Request.Url.Scheme;
  
      result += HttpContext.Current.Request.Url.Host;
  
      if (HttpContext.Current.Request.Url.Port != 80) result += ":" + HttpContext.Current.Request.Url.Port.ToString();
  
      return result;
  }
  </code></pre>
  
  <p>HttpProtocol is an enum that I created myself.</p>
  
  <p>Thanks!</p>