diff --git a/snippets/csharp/System/Uri/HostComparison/Project.csproj b/snippets/csharp/System/Uri/HostComparison/Project.csproj
new file mode 100644
index 00000000000..8493fb5b09d
--- /dev/null
+++ b/snippets/csharp/System/Uri/HostComparison/Project.csproj
@@ -0,0 +1,8 @@
+
+
+
+ Exe
+ net6.0
+
+
+
diff --git a/snippets/csharp/System/Uri/HostComparison/source.cs b/snippets/csharp/System/Uri/HostComparison/source.cs
new file mode 100644
index 00000000000..7a2531aba07
--- /dev/null
+++ b/snippets/csharp/System/Uri/HostComparison/source.cs
@@ -0,0 +1,58 @@
+using System;
+
+public class UriHostComparison
+{
+ public static void Main()
+ {
+ //
+ // Demonstrate differences between Host, IdnHost, and DnsSafeHost.
+
+ // Example 1: Regular hostname (ASCII).
+ Console.WriteLine("Example 1: Regular ASCII hostname");
+ Uri uri1 = new Uri("http://www.contoso.com:8080/path");
+ Console.WriteLine($" Host: {uri1.Host}"); // www.contoso.com
+ Console.WriteLine($" IdnHost: {uri1.IdnHost}"); // www.contoso.com
+ Console.WriteLine($" DnsSafeHost: {uri1.DnsSafeHost}"); // www.contoso.com
+ Console.WriteLine();
+
+ // Example 2: International domain name (non-ASCII).
+ Console.WriteLine("Example 2: International domain name");
+ Uri uri2 = new Uri("http://münchen.de/path");
+ Console.WriteLine($" Host: {uri2.Host}"); // münchen.de (original)
+ Console.WriteLine($" IdnHost: {uri2.IdnHost}"); // xn--mnchen-3ya.de (punycode)
+ Console.WriteLine($" DnsSafeHost: {uri2.DnsSafeHost}"); // münchen.de
+ Console.WriteLine();
+
+ // Example 3: International domain name already in punycode (encoded) form.
+ Console.WriteLine("Example 3: Already-encoded international domain name");
+ Uri uri2Encoded = new Uri("http://xn--mnchen-3ya.de/path");
+ Console.WriteLine($" Host: {uri2Encoded.Host}"); // xn--mnchen-3ya.de (as provided)
+ Console.WriteLine($" IdnHost: {uri2Encoded.IdnHost}"); // xn--mnchen-3ya.de (already punycode)
+ Console.WriteLine($" DnsSafeHost: {uri2Encoded.DnsSafeHost}"); // xn--mnchen-3ya.de
+ Console.WriteLine();
+
+ // Example 4: IPv6 address without zone ID.
+ Console.WriteLine("Example 4: IPv6 address without zone ID");
+ Uri uri3 = new Uri("http://[::1]:8080/path");
+ Console.WriteLine($" Host: {uri3.Host}"); // [::1] (with brackets)
+ Console.WriteLine($" IdnHost: {uri3.IdnHost}"); // ::1 (without brackets)
+ Console.WriteLine($" DnsSafeHost: {uri3.DnsSafeHost}"); // ::1 (without brackets)
+ Console.WriteLine();
+
+ // Example 5: IPv6 link-local address with zone ID.
+ Console.WriteLine("Example 5: IPv6 link-local address with zone ID");
+ Uri uri4 = new Uri("http://[fe80::1%10]:8080/path");
+ Console.WriteLine($" Host: {uri4.Host}"); // [fe80::1] (with brackets, no zone ID)
+ Console.WriteLine($" IdnHost: {uri4.IdnHost}"); // fe80::1%10 (without brackets, with zone ID)
+ Console.WriteLine($" DnsSafeHost: {uri4.DnsSafeHost}"); // fe80::1%10 (without brackets, with zone ID)
+ Console.WriteLine();
+
+ // Example 6: IPv4 address.
+ Console.WriteLine("Example 6: IPv4 address");
+ Uri uri5 = new Uri("http://192.168.1.1:8080/path");
+ Console.WriteLine($" Host: {uri5.Host}"); // 192.168.1.1
+ Console.WriteLine($" IdnHost: {uri5.IdnHost}"); // 192.168.1.1
+ Console.WriteLine($" DnsSafeHost: {uri5.DnsSafeHost}"); // 192.168.1.1
+ //
+ }
+}
diff --git a/xml/System/Uri.xml b/xml/System/Uri.xml
index 3bcf5e86f49..634d3bb5bb7 100644
--- a/xml/System/Uri.xml
+++ b/xml/System/Uri.xml
@@ -1648,6 +1648,8 @@ For `uriString`, an IPv6 address in string form must be enclosed within brackets
## Remarks
For IPv6 addresses, the brackets ([]) are removed and the property is set, if one was specified when this instance was constructed.
+ is a legacy property whose behavior depends on configuration settings in .NET Framework apps. For new code, prefer , which is configuration-independent and produces a value suitable for DNS resolution. See and for guidance on choosing a host property.
+
If you used an escaped string to construct this instance (for example, `"http://[fe80::200:39ff:fe36:1a2d%254]/temp/example.htm"`), then DnsSafeHost returns an escaped string. Unescape any escaped string returned from `DnsSafeHost` before using that string for DNS resolution (see the Example). If you used an invalid unescaped string to construct this instance (for example, "http://[fe80::200:39ff:fe36:1a2d%4]/temp/example.htm"), then DnsSafeHost returns an unescaped string.
## Examples
@@ -2638,6 +2640,14 @@ The following examples show a URI and the results of calling property, this property value does not include the port number.
+ The value returned by this property depends on the host type:
+
+ - For **DNS host names** (including international domain names): Returns the escaped input. Non-ASCII characters are returned as-is and aren't punycode encoded.
+ - For **IPv6 addresses**: Returns the address enclosed in square brackets (for example, `[::1]`), but doesn't include the zone ID (scope) even if one was specified in the original URI.
+ - For **IPv4 addresses**: Returns the dotted-decimal notation (for example, `192.168.1.1`).
+
+ For DNS resolution or other lower-level networking scenarios, use instead, which returns a punycode-encoded form for valid international domain names and includes the zone ID (without brackets) for IPv6 addresses. Use when you want the host as it appears in the URI (for example, for display or comparison).
+
## Examples
The following example writes the host name (`www.contoso.com`) of the server to the console.
@@ -2645,6 +2655,10 @@ The following examples show a URI and the results of calling and differ across DNS, IDN, IPv4, and IPv6 inputs:
+
+ :::code language="csharp" source="~/snippets/csharp/System/Uri/HostComparison/source.cs" id="SnippetHostComparison":::
+
]]>
This instance represents a relative URI, and this property is valid only for absolute URIs.
@@ -2749,10 +2763,21 @@ The following examples show a URI and the results of calling for the hostname.
-IdnHost is provided as the preferred alternative to using the deprecated property, because is guaranteed to always be DNS safe.
+ The value returned by this property depends on the host type:
+
+ - For **DNS host names**: For valid international domain names, non-ASCII characters are punycode encoded (for example, `münchen.de` becomes `xn--mnchen-3ya.de`). Hostnames that aren't valid IDNs might be returned as-is and include non-ASCII characters.
+ - For **IPv6 addresses**: Returns the address without the surrounding brackets, and includes the zone ID (scope) if one was specified (for example, `::1` or `fe80::1%18`).
+ - For **IPv4 addresses**: Returns the dotted-decimal notation (for example, `192.168.1.1`).
+
+ is the preferred alternative to the legacy property, because its behavior doesn't depend on *app.config* settings and it's designed to produce a value suitable for DNS resolution. Note that for IPv6 results that include a zone ID, callers may still need to strip the zone ID before passing the value to APIs that don't accept it.
If you used an escaped string to construct this instance (for example, `"http://[fe80::200:39ff:fe36:1a2d%254]/temp/example.htm"`), then IdnHost returns an escaped string. You should unescape any escaped string returned from IdnHost before using that string for DNS resolution. Be aware that if you used an invalid unescaped string to construct this instance (for example, "http://[fe80::200:39ff:fe36:1a2d%4]/temp/example.htm"), then IdnHost returns an unescaped string.
+## Examples
+ The following example shows how and differ across DNS, IDN, IPv4, and IPv6 inputs:
+
+ :::code language="csharp" source="~/snippets/csharp/System/Uri/HostComparison/source.cs" id="SnippetHostComparison":::
+
]]>
This instance represents a relative URI, and this property is valid only for absolute URIs.