Uri modification
host replacement
URL manipulation
programming tutorial
web development

Replace host in Uri

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

If you need to send the same request to another server, changing only the host is a common task. In .NET, the safe way to do that is to parse the address as a Uri and rebuild it with UriBuilder, instead of trying to patch the string by hand.

Why String Replacement Fails

A URI is not just a hostname followed by a path. It can include a scheme, port, username, password, query string, and fragment. A plain text replacement often works for the happy path, then breaks as soon as one of those extra parts appears.

For example, this approach is fragile:

csharp
var original = "https://api.old.example:8443/v1/users?id=42";
var updated = original.Replace("api.old.example", "api.new.example");
Console.WriteLine(updated);

The code above changes the visible host, but it assumes the old host appears exactly once and only inside the authority section. If the same text appears in the query string or path, you can silently corrupt the URI.

Another problem is encoding. A URI may contain escaped characters in the path or query. Treating the entire address as raw text makes it easy to produce a value that looks correct but no longer parses the same way.

Use UriBuilder to Replace the Host

UriBuilder exists for this exact job. It lets you parse the original Uri, change one component, and keep everything else intact.

csharp
1using System;
2
3var original = new Uri("https://api.old.example:8443/v1/users?id=42#details");
4
5var builder = new UriBuilder(original)
6{
7    Host = "api.new.example"
8};
9
10Uri updated = builder.Uri;
11
12Console.WriteLine($"Original: {original}");
13Console.WriteLine($"Updated:  {updated}");
14Console.WriteLine($"Scheme:   {updated.Scheme}");
15Console.WriteLine($"Port:     {updated.Port}");
16Console.WriteLine($"Path:     {updated.AbsolutePath}");
17Console.WriteLine($"Query:    {updated.Query}");
18Console.WriteLine($"Fragment: {updated.Fragment}");

That produces a new URI with the new host while preserving the scheme, port, path, query string, and fragment. This is usually what you want when moving traffic between environments such as staging, production, or an internal proxy.

If you also need to swap the scheme or port, change those explicitly:

csharp
1using System;
2
3var original = new Uri("http://old.example:8080/report/daily");
4
5var builder = new UriBuilder(original)
6{
7    Host = "new.example",
8    Scheme = Uri.UriSchemeHttps,
9    Port = 443
10};
11
12Console.WriteLine(builder.Uri);

Setting each field directly makes the intent obvious and avoids hidden assumptions.

Encapsulate the Logic in a Helper

If the same transformation happens in several places, wrap it in a helper method. That keeps URI parsing rules in one place and makes the call site easier to read.

csharp
1using System;
2
3static Uri ReplaceHost(Uri original, string newHost, int? newPort = null)
4{
5    var builder = new UriBuilder(original)
6    {
7        Host = newHost
8    };
9
10    if (newPort.HasValue)
11    {
12        builder.Port = newPort.Value;
13    }
14
15    return builder.Uri;
16}
17
18var source = new Uri("https://service.internal.example/api/orders?page=2");
19var target = ReplaceHost(source, "service.public.example");
20
21Console.WriteLine(target);

This pattern also gives you a clean place to validate input. For example, you may want to reject an empty host name or enforce HTTPS when switching to a public endpoint.

Relative URIs Need Different Handling

UriBuilder only works with absolute URIs. If you are dealing with a relative path such as /api/orders?page=2, there is no host to replace yet. In that case, combine the relative URI with a base address first.

csharp
1using System;
2
3var baseUri = new Uri("https://api.example.com");
4var relative = new Uri("/api/orders?page=2", UriKind.Relative);
5
6var combined = new Uri(baseUri, relative);
7Console.WriteLine(combined);

Once you have an absolute URI, you can use the same UriBuilder pattern shown earlier.

Common Pitfalls

Replacing the host with string.Replace is the most common mistake. It looks shorter, but it ignores URI structure and can modify the wrong part of the address.

Forgetting the port is another frequent issue. If the old URI uses a non-default port, that port will stay in place unless you change it. Moving from http on 8080 to https on 443 often requires updating both fields.

Relative URIs also trip people up. A path by itself does not have a host, so there is nothing to replace until you resolve it against a base URI.

Finally, watch for user info in legacy addresses. If the original URI contains embedded credentials, UriBuilder preserves them. That may be correct for an internal migration, but it may also copy secrets into a context where they no longer belong.

Summary

  • Use Uri and UriBuilder instead of raw string replacement.
  • Changing the host does not automatically change the scheme or port.
  • Wrap repeated URI transformations in a helper method.
  • Resolve relative paths against a base URI before trying to modify the host.
  • Preserve intent explicitly so the rewritten URI is predictable and safe.

Course illustration
Course illustration

All Rights Reserved.