Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions snippets/csharp/System/Uri/HostComparison/Project.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
</Project>
50 changes: 50 additions & 0 deletions snippets/csharp/System/Uri/HostComparison/source.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System;

public class UriHostComparison
{
public static void Main()
{
// <SnippetHostComparison>
// 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: IPv6 address without zone ID.
Console.WriteLine("Example 3: 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 4: IPv6 link-local address with zone ID.
Console.WriteLine("Example 4: 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 5: IPv4 address.
Console.WriteLine("Example 5: 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
// </SnippetHostComparison>
}
}
73 changes: 64 additions & 9 deletions xml/System/Uri.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1553,16 +1553,25 @@ The URI formed by combining <paramref name="baseUri" /> and <paramref name="rela
</ReturnValue>
<Docs>
<summary>Gets a host name that, after being unescaped if necessary, is safe to use for DNS resolution.</summary>
<value>The host part of the URI in a format suitable for DNS resolution; or the original host string, if it is already suitable for resolution.</value>
<value>The host part of the URI in a format suitable for DNS resolution; or the original host string, if it's already suitable for resolution.</value>
<remarks>
<format type="text/markdown"><![CDATA[

## Remarks
For IPv6 addresses, the brackets ([]) are removed and the <xref:System.Net.IPAddress.ScopeId%2A> property is set, if one was specified when this instance was constructed.

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.
If you used an escaped string to construct this instance (for example, `"http://[fe80::200:39ff:fe36:1a2d%254]/temp/example.htm"`), then <xref:System.Uri.DnsSafeHost%2A> 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 <xref:System.Uri.DnsSafeHost%2A> returns an unescaped string.

The <xref:System.Uri.DnsSafeHost%2A> property is dependent on configuration settings in .NET Framework apps, as discussed later in this topic. The <xref:System.Uri.IdnHost%2A> property is provided as the preferred alternative to using <xref:System.Uri.DnsSafeHost%2A>, because <xref:System.Uri.IdnHost%2A> is guaranteed to always be DNS safe.
## Comparison with other Host properties

The <xref:System.Uri> class provides two main host properties:

- <xref:System.Uri.Host%2A>: Returns the host as it appears in the URI. For IPv6, includes brackets but not the zone ID.
- <xref:System.Uri.IdnHost%2A>: Returns a format suitable for DNS resolution. For valid international domain names, applies punycode encoding. For IPv6, doesn't include brackets but does include the zone ID.

The <xref:System.Uri.DnsSafeHost%2A> property is a legacy property that depends on configuration settings. Use <xref:System.Uri.IdnHost%2A> instead for consistent, configuration-independent behavior.

The <xref:System.Uri.DnsSafeHost%2A> property is dependent on configuration settings in .NET Framework apps, as discussed later in this topic. The <xref:System.Uri.IdnHost%2A> property is provided as the preferred alternative to using <xref:System.Uri.DnsSafeHost%2A> because <xref:System.Uri.IdnHost%2A> is guaranteed to always be DNS safe.
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The remarks introduce that IdnHost can return non-ASCII for invalid or malformed hostnames, but later this section still claims IdnHost is "guaranteed to always be DNS safe." That guarantee is inconsistent with the behavior described above and should be softened or removed to avoid overpromising.

Suggested change
The <xref:System.Uri.DnsSafeHost%2A> property is dependent on configuration settings in .NET Framework apps, as discussed later in this topic. The <xref:System.Uri.IdnHost%2A> property is provided as the preferred alternative to using <xref:System.Uri.DnsSafeHost%2A> because <xref:System.Uri.IdnHost%2A> is guaranteed to always be DNS safe.
The <xref:System.Uri.DnsSafeHost%2A> property is dependent on configuration settings in .NET Framework apps, as discussed later in this topic. The <xref:System.Uri.IdnHost%2A> property is provided as the preferred alternative to using <xref:System.Uri.DnsSafeHost%2A>, because <xref:System.Uri.IdnHost%2A> typically returns a value that's suitable for DNS resolution.

Copilot uses AI. Check for mistakes.

The <xref:System.Uri.DnsSafeHost%2A> property was extended in .NET Framework v3.5, 3.0 SP1, and 2.0 SP1 to provide International Resource Identifier (IRI) support based on RFC 3987. However, to ensure application compatibility with prior versions, you must specifically enable it in .NET Framework apps. To enable support for IRI, the following two changes are required:

Expand Down Expand Up @@ -1597,14 +1606,14 @@ If you used an escaped string to construct this instance (for example, `"http://

- idn enabled = None

This value will not convert any Unicode domain names to use Punycode. This is the default value, which is consistent with the .NET Framework 2.0 behavior.
This value won't convert any Unicode domain names to use Punycode. This is the default value, which is consistent with the .NET Framework 2.0 behavior.

Enabling IRI parsing (iriParsing enabled = `true`) normalizes and checks characters according to the IRI rules in RFC 3987. The default value is `false` and normalizes and checks characters according to RFC 2396 and RFC 2732 (for IPv6 literals).

For more information on IRI support, see the Remarks section for the <xref:System.Uri> class.

## Examples
The following example creates a <xref:System.Uri> instance from a string. It illustrates the difference between the value returned from <xref:System.Uri.Host%2A>, which returns the host name or address specified in the URI, and the value returned from <xref:System.Uri.DnsSafeHost%2A>, which returns an address that is safe to use in DNS resolution.
The following example creates a <xref:System.Uri> instance from a string. It illustrates the difference between the value returned from <xref:System.Uri.Host%2A>, which returns the host name or address specified in the URI, and the value returned from <xref:System.Uri.DnsSafeHost%2A>, which returns an address that's safe to use in DNS resolution.

:::code language="csharp" source="~/snippets/csharp/System/Uri/.ctor/nclurienhancements.cs" id="Snippet4":::
:::code language="fsharp" source="~/snippets/fsharp/System/Uri/.ctor/nclurienhancements.fs" id="Snippet4":::
Expand Down Expand Up @@ -2605,7 +2614,24 @@ The following examples show a URI and the results of calling <xref:System.Uri.Ge
<format type="text/markdown"><![CDATA[

## Remarks
Unlike the <xref:System.Uri.Authority%2A> property, this property value does not include the port number.
Unlike the <xref:System.Uri.Authority%2A> property, this property value doesn't include the port number.

The behavior of this property depends on the host type:

- For **regular DNS hostnames**: Returns the escaped input. Non-ASCII characters are returned as-is without punycode encoding.
- For **IPv6 addresses**: Returns the address with square brackets (for example, `[::1]` or `[fe80::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`).

## Comparison with IdnHost

The <xref:System.Uri> class provides two main host properties:

- <xref:System.Uri.Host%2A>: Returns the host as it appears in the URI. For IPv6, includes brackets but not the zone ID.
- <xref:System.Uri.IdnHost%2A>: Returns a format suitable for DNS resolution. For valid international domain names, applies punycode encoding. For IPv6, doesn't include brackets but does include the zone ID.

Which property to use depends on your scenario:
- Use <xref:System.Uri.Host%2A> when you need the original host string as it appears in the URI (for display or comparison).
- Use <xref:System.Uri.IdnHost%2A> when you need a format suitable for DNS resolution or network APIs.

## Examples
The following example writes the host name (`www.contoso.com`) of the server to the console.
Expand All @@ -2614,6 +2640,10 @@ The following examples show a URI and the results of calling <xref:System.Uri.Ge
:::code language="fsharp" source="~/snippets/fsharp/System/Uri/Host/source.fs" id="Snippet1":::
:::code language="vb" source="~/snippets/visualbasic/System/Uri/Host/source.vb" id="Snippet1":::

The following example demonstrates the differences between <xref:System.Uri.Host%2A> and <xref:System.Uri.IdnHost%2A> for various URI types:

:::code language="csharp" source="~/snippets/csharp/System/Uri/HostComparison/source.cs" id="SnippetHostComparison":::

]]></format>
</remarks>
<exception cref="T:System.InvalidOperationException">This instance represents a relative URI, and this property is valid only for absolute URIs.</exception>
Expand Down Expand Up @@ -2718,11 +2748,36 @@ The following examples show a URI and the results of calling <xref:System.Uri.Ge
<format type="text/markdown"><![CDATA[

## Remarks
This property is provided for the use of lower-level networking protocols that require the domain name in Punycode form. If your code does not require that specific format, use <xref:System.Uri.Host%2A> for the hostname.
This property is provided for use with lower-level networking protocols that require the domain name in Punycode form or need DNS-safe formatting.

The behavior of this property depends on the host type:

- For **regular DNS hostnames**: For valid international domain names, non-ASCII characters are punycode encoded (for example, `münchen.de` becomes `xn--mnchen-3ya.de`). Invalid or malformed hostnames might return non-ASCII values.
- For **IPv6 addresses**: Returns the address without square brackets but 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`).

## Comparison with Host

The <xref:System.Uri> class provides two main host properties:

- <xref:System.Uri.Host%2A>: Returns the host as it appears in the URI. For IPv6, includes brackets but not the zone ID.
- <xref:System.Uri.IdnHost%2A>: Returns a format suitable for DNS resolution. For valid international domain names, applies punycode encoding. For IPv6, doesn't include brackets but does include the zone ID.

Which property to use depends on your scenario:
- Use <xref:System.Uri.Host%2A> when you need the original host string as it appears in the URI (for display or comparison).
- Use <xref:System.Uri.IdnHost%2A> when you need a format suitable for DNS resolution or network APIs.

The deprecated <xref:System.Uri.DnsSafeHost%2A> property is dependent on *app.config* settings, which can't be changed by Windows Store applications. <xref:System.Uri.IdnHost%2A> is provided as the preferred alternative to using <xref:System.Uri.DnsSafeHost%2A> because <xref:System.Uri.IdnHost%2A> is guaranteed to always be DNS safe, no matter what the current *app.config* settings might be.
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sentence says IdnHost is "guaranteed to always be DNS safe", but earlier in this section you note that invalid or malformed hostnames might return non-ASCII values, and IPv6 results can include a zone ID. Please remove or qualify the guarantee so it matches the behavior you describe.

Suggested change
The deprecated <xref:System.Uri.DnsSafeHost%2A> property is dependent on *app.config* settings, which can't be changed by Windows Store applications. <xref:System.Uri.IdnHost%2A> is provided as the preferred alternative to using <xref:System.Uri.DnsSafeHost%2A> because <xref:System.Uri.IdnHost%2A> is guaranteed to always be DNS safe, no matter what the current *app.config* settings might be.
The deprecated <xref:System.Uri.DnsSafeHost%2A> property is dependent on *app.config* settings, which can't be changed by Windows Store applications. <xref:System.Uri.IdnHost%2A> is provided as the preferred alternative to using <xref:System.Uri.DnsSafeHost%2A> because it doesn't depend on *app.config* settings, and it's designed to produce a host value that works for typical DNS resolution scenarios. Callers should still validate or normalize the returned value, especially for malformed hostnames or IPv6 addresses that include a zone ID.

Copilot uses AI. Check for mistakes.

## Escaping behavior

If you used an escaped string to construct this instance (for example, `"http://[fe80::200:39ff:fe36:1a2d%254]/temp/example.htm"`), then <xref:System.Uri.IdnHost%2A> returns an escaped string. You should unescape any escaped string returned from <xref:System.Uri.IdnHost%2A> 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 <xref:System.Uri.IdnHost%2A> returns an unescaped string.

## Examples

The deprecated <xref:System.Uri.DnsSafeHost%2A> property is dependent on *app.config* settings, which cannot be changed by Windows Store applications. IdnHost is provided as the preferred alternative to using <xref:System.Uri.DnsSafeHost%2A>, because <xref:System.Uri.IdnHost%2A> is guaranteed to always be DNS safe, no matter what the current *app.config* settings might be.
The following example demonstrates the differences between <xref:System.Uri.Host%2A> and <xref:System.Uri.IdnHost%2A> for various URI types:

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.
:::code language="csharp" source="~/snippets/csharp/System/Uri/HostComparison/source.cs" id="SnippetHostComparison":::

]]></format>
</remarks>
Expand Down
Loading