4

I have a situation where I need to obtain a link to the item at my site to use it in an e-mail notification. I currently do it like this: var baseUrl = new Uri(Sitecore.Globals.ServerUrl);.
This method works for my local site instance, which has the following bindings:

Type | Host name | port
http |    foo    | 80 
https|    foo    | 443

I go to https://foo/, trigger my e-mail notification and the link I get in the e-mail is "https://foo/", so all is well. When debugging, Sitecore.Globals.ServerUrl contains "https://foo:443".

However, our shared sandbox site is configured to be used as https://foo.bar:44305. The bindings there are as follows:

Type | Host name | port
http |    foo    | 80 
https|    foo    | 443
https|           | 8082
http |           | 8081
https|           | 44301
https|           | 44305

and while I use https://foo.bar:44305 to trigger e-mail to be sent, I receive "https://foo.bar:8081" in my e-mails.

If I add an extra binding

<... >
https|    foo    | 40443
to my local instance, I start getting "https://foo:40443" in the e-mails while triggering them from plain https://foo.

The alternative we tried is hard-coding the link to be used in Web.config. which obviously works, but the link is not resolved dynamically, so we have to always keep this in mind to change it before deploying to production, etc.

Is there actually a way to do this properly without hard-coding or messing up the bindings? I'm also very curious why Sitecore.Globals.ServerUrl contains a seemingly random binding port.

Update: per @RichardSeal's advice I also tried to get this link via Sitecore.Links.LinkManager:

var options = LinkManager.GetDefaultUrlOptions();
options.AlwaysIncludeServerUrl = true;
var url = Sitecore.Links.LinkManager.GetItemUrl(item);

In this case I obtain a relative url, not a full url, i.e: /en/sitecore/shell/foo/home/lookbook/sales/list

9
  • Are you trying to get a link to your home page or another page on the site. Trying to work out why you are using Sitecore.Globals.ServerUrl to build the link instead of the LinkManager
    – Richard Seal
    Commented Nov 14, 2016 at 14:47
  • @RichardSeal There are several cases, but it's mostly about links to various Angular pages at the site, something like "foo:44305/sales/list".
    – Elena P
    Commented Nov 14, 2016 at 15:33
  • is sales/list a Sitecore item? Also - do the urls need to be full? can they be created as relative urls? Then you don't have to worry about the host
    – Richard Seal
    Commented Nov 14, 2016 at 15:35
  • The link is to go into an email which is why they want them to be absolute.
    – Kasaku
    Commented Nov 14, 2016 at 15:42
  • 2
    @elellle - When faced with an issue like this in the past, we have had something akin to a PublishedHost setting, so we had absolute control over the host in the URL. This was set as a deployment variable so we never had to worry about editing it for production etc., much like a connection string.
    – Kasaku
    Commented Nov 14, 2016 at 15:44

2 Answers 2

5

Sitecore.Globals.ServerUrl is set in the Globals.Load function by calling WebUtil.GetServerUrl(HttpContext.Current.Request.Url, false).

The code for that is:

public static string GetServerUrl(Uri url, bool forcePort)
{
    if (url == (Uri) null)
        return string.Empty;
    string scheme = url.Scheme;
    string host = url.Host;
    string @string = url.Port.ToString();
    string str = string.Format("{0}://{1}", (object) scheme, (object) host);
    if (forcePort || @string != "80")
        str += string.Format(":{0}", (object) @string);
    return str;
}

So the ports are getting added because GetServerUrl adds the port any time the Uri.Port value is not 80.

To make the LinkManager work, you need to make sure that in your site definition you have both the targetHostName and scheme set correctly. These can be setup in your standard deployment process:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
    <sitecore>
        <sites>
            <site name="foo" patch:before="site[@name='website']"
                  host="foo.com|other.foo.com"
                  ... other settings ...
                  targetHostName="foo.com"
                  scheme="https"
                  />
        </sites>
    </sitecore>
</configuration>

With those set, calling the LinkManager with AlwaysIncludeServerUrl set to true in the options should give you:

https://foo.com/en/path/to/your/page

2
  • Thank you! Do you have an idea on why the Uri.Port that is added not the same that the one I actually use? My problem with Sitecore.Globals.ServerUrl is that I go to https://foo.bar:44305/whatever/page, change it, and the users get an e-mail notification that contains a wrong port, i.e.: "Hey, https://foo.bar:8081/whatever/page was changed, check it out."
    – Elena P
    Commented Nov 15, 2016 at 8:44
  • 1
    My guess would be that there is some internal redirection happening, possibly behind a load balancer. If the external port is 44305 to the LB, but the LB then hits the origin server at port 8081, the code will only see the 8081 port.
    – Richard Seal
    Commented Nov 15, 2016 at 13:10
2

I ended up using config transformation, having different site urls for local build, qa build and production in my Sitecore.config, Sitecore.QA.config, etc.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.