How to enable IDN/IRI Support for URI-Class by code?

3.4k views Asked by At

I'm trying to enable the IDN/IRI support for the URI class, because I need the "Uri.IsWellFormedUriString" method on german umlaut-domains (e.g. www.bücher.de).

I found similar question at https://stackoverflow.com/a/6107682/413531 (taken from http://msdn.microsoft.com/en-us/library/system.uri.aspx at "International Resource Identifier Support") but the solution is not working for me. My current app.config file looks something like this:

<configuration>
    <configSections>
        <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="..." type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
        <!-- ... some sections in here ... -->
        </sectionGroup>
        <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
        <!-- ... some sections in here ... -->
        </sectionGroup>
    </configSections>
    <userSettings>
        <!-- ... some settings in here ... -->
    </userSettings>
    <applicationSettings>
        <!-- ... some settings in here ... -->
    </applicationSettings>
</configuration>

when I just add

  <uri>
  <idn enabled="All" />
  <iriParsing enabled="true" />
  </uri>

as an other child of at the end, an exception is thrown: ConfigurationErrorsException - {"Das Konfigurationssystem konnte nicht initialisiert werden."}

So I read further in http://msdn.microsoft.com/en-us/library/system.uri.aspx an came across

IRI and IDN processing in the Uri class can also be controlled using the System.Configuration.IriParsingElement, System.Configuration.IdnElement, and System.Configuration.UriSection configuration setting classes. The System.Configuration.IriParsingElement setting enables or disables IRI processing in the Uri class. The System.Configuration.IdnElement setting enables or disables IDN processing in the Uri class. The System.Configuration.IriParsingElement setting also indirectly controls IDN. IRI processing must be enabled for IDN processing to be possible. If IRI processing is disabled, then IDN processing will be set to the default setting where the .NET Framework 2.0 behavior is used for compatibility and IDN names are not used.

Unfortunatly I was not able to find an example for the usage of System.Configuration.IriParsingElement, System.Configuration.IdnElement, and System.Configuration.UriSection. I've no clue how these are used...

So basically, my problem comes down to: I want to enable IDN/IRI support in the URI class, but I can't figure out how to do this. The config-solution is not working for me, so I would like to try it by code, but can't figure out how. Btw. I would also like to know why the config thing isn't working ;)

2

There are 2 answers

0
Hirnhamster On BEST ANSWER

I found a solution - at least for the app.config part. According to http://social.msdn.microsoft.com/Forums/nl-NL/netfxnetcom/thread/56a73dbb-c0d4-4cad-876d-83ad74064393 one has to add an additional line in the app.config if a .Net version lower 4.0 is used:

<configSections>
  <section name="uri" type="System.Configuration.UriSection, System,
                      Version=2.0.0.0, Culture=neutral,
                      PublicKeyToken=b77a5c561934e089" />
</configSections>

After adding this line, I could also add

<uri>
    <idn enabled="All" />
    <iriParsing enabled="true" />
</uri>

without getting an error. My complete app.config now looks like this:

<configuration>
    <configSections>
        <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="..." type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
    <!-- ... some sections in here ... -->
        </sectionGroup>
        <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
    <!-- ... some sections in here ... -->
        </sectionGroup>

<!-- ... insert Missing section ... -->

        <section name="uri" type="System.Configuration.UriSection, System,
                      Version=2.0.0.0, Culture=neutral,
                      PublicKeyToken=b77a5c561934e089" />

    </configSections>

<!-- ... insert URI settings ... -->

    <uri>
        <idn enabled="All" />
        <iriParsing enabled="true" />
    </uri>

    <userSettings>
    <!-- ... some settings in here ... -->
    </userSettings>
    <applicationSettings>
    <!-- ... some settings in here ... -->
    </applicationSettings>
</configuration>
0
MDK. dc On

This is my solution, tested worked.

Basically, you need to change the value of the static non-public fields of System.Uri:

  • s_IdnScope
  • s_IriParsing

    public static bool ToggleIDNIRISupport(bool enable)
    {
        //Important: Try IsWellFormedUriString() once to initialize static fields: s_IdnScope, s_IriParsing
        Uri.IsWellFormedUriString("http://example.com/query=ü", UriKind.Absolute);
    
        //Get the assembly that contains the class
        Assembly assembly = Assembly.GetAssembly(typeof(Uri));
        if (assembly != null)
        {
            //Use the assembly in order to get the type of the class
            Type uriType = assembly.GetType("System.Uri");
            if (uriType != null)
            {
                object idnScope = uriType.InvokeMember("s_IdnScope", BindingFlags.Static | BindingFlags.GetField | BindingFlags.NonPublic, null, null, new object[] { });
                if (idnScope != null)
                {
                    if (enable)
                    {
                        uriType.InvokeMember("s_IdnScope", BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic, null, null, new object[] { UriIdnScope.All });
                    }
                    else
                    {
                        uriType.InvokeMember("s_IdnScope", BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic, null, null, new object[] { UriIdnScope.None });
                    }
                }
    
                object iriParsing = uriType.InvokeMember("s_IriParsing", BindingFlags.Static | BindingFlags.GetField | BindingFlags.NonPublic, null, null, new object[] { });
                if (iriParsing != null)
                {
                    uriType.InvokeMember("s_IriParsing", BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic, null, null, new object[] { enable });
                }
            }
        }
    
        return true;
    }