How can I correctly include a (non-fragment) # in a URL? I need to build an external URL that looks like this:

https://searchapp.foo.gov/search-org/#/collection-name?q=search%20terms%20here


First thought is that /#/ is entirely invalid according to RFC 3986, unless I'm reading it incorrectly, but that's what I've been given. So I'm building it like so:

$base_url = 'https://searchapp.foo.gov/search-org/#/collection-name';
$options = [
  'absolute' =&gt; TRUE,
  'https' =&gt; TRUE,
  'query' =&gt; [
    'q' =&gt; $form_state-&gt;getValue('search'),
  ],
];
$url = Url::fromUri($base_url, $options)-&gt;toString();


Instead of the expected output, I find that my querystring is appearing before the #:

https://searchapp.foo.gov/search-org/?q=search%20terms%20here#/collection-name


I've tried using /%23/ instead of /#/, and that fixes the problem with the querystring being out of place, but creates a new problem by url encoding the %, so that I wind up with /%2523/.

I'm guessing this is a problem with hash segment handling. Is there a right way to handle a URL like this?
You are correct ... it is invalid to use the "#" for anything other than a fragment. That does not mean that someone doesn't have their web servers setup in such a way that "#" can be used in the URL itself.  


  I'm guessing this is a problem with hash segment handling. Is there a right way to handle a URL like this?


To be clear, there is no problem with how Drupal is handling URLs ... Drupal is following the spec. I think your best bet in this case (short of yelling at whoever is giving you this URL for doing so) is to extend the Url class and replace the formUri method to handle your weird case. 

Your other option is to do something really hacky like putting an easily replaced string in the URL and then doing a string replace at the last minute before displaying it.