Customizing the XmlUrlResolver Class

This document describes how to build a custom class for resolving XML data by extending the XmlUrlResolver class. The custom class in this example resolves an XML data resource from the default cache.

Extending the XmlUrlResolver Class

The default behavior of the XmlUrlResolver class is to resolve an XML data resource from its source, not from cache. In some cases, resolving a data resource from cache can improve the performance of an application by saving a trip to the data resource's server. The performance gains here must be weighed against the need for up-to-date content.

In the code example below, a new class is built to retrieve resources from the cache. The XmlCachingResolver class is built by extending the XmlUrlResolver class. This is done by overriding the Credentials property and the GetEntity method.

Class XmlCachingResolver
    Inherits XmlUrlResolver
    Dim enableHttpCaching As Boolean
    Public Shadows Credentials As ICredentials

    'resolve resources from cache (if possible) when enableHttpCaching is set to true
    'resolve resources from source when enableHttpcaching is set to false
    Public Sub New(ByVal enableHttpCaching As Boolean)
        Me.enableHttpCaching = enableHttpCaching
    End Sub

    Public Shadows Function GetEntity(ByVal absoluteUri As Uri, ByVal role As String, ByVal returnType As Type) As Object
        If absoluteUri = Nothing Then
            Throw New ArgumentNullException("absoluteUri")
        End If

        'resolve resources from cache (if possible)
        If absoluteUri.Scheme = "http" And enableHttpCaching And (returnType Is GetType(Nullable) Or returnType Is GetType(Stream)) Then
            Dim webReq As WebRequest = WebRequest.Create(absoluteUri)
            webReq.CachePolicy = New HttpRequestCachePolicy(HttpRequestCacheLevel.Default)
            If Not (Credentials Is Nothing) Then
                webReq.Credentials = Credentials
            End If
            Dim resp As WebResponse = webReq.GetResponse()
            Return resp.GetResponseStream()
            'otherwise use the default behavior of the XmlUrlResolver class (resolve resources from source)
        Else
            Return MyBase.GetEntity(absoluteUri, role, returnType)
        End If

    End Function
End Class
class XmlCachingResolver : XmlUrlResolver
{
    bool enableHttpCaching;
    ICredentials credentials;

    //resolve resources from cache (if possible) when enableHttpCaching is set to true
    //resolve resources from source when enableHttpcaching is set to false 
    public XmlCachingResolver(bool enableHttpCaching)
    {
        this.enableHttpCaching = enableHttpCaching;
    }

    public override ICredentials Credentials
    {
        set
        {
            credentials = value;
            base.Credentials = value;
        }
    }

    public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
    {
        if (absoluteUri == null)
        {
            throw new ArgumentNullException("absoluteUri");
        }
        //resolve resources from cache (if possible)
        if (absoluteUri.Scheme == "http" && enableHttpCaching && (ofObjectToReturn == null || ofObjectToReturn == typeof(Stream)))
        {
            WebRequest webReq = WebRequest.Create(absoluteUri);
            webReq.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.Default);
            if (credentials != null)
            {
                webReq.Credentials = credentials;
            }
            WebResponse resp = webReq.GetResponse();
            return resp.GetResponseStream();
        }
        //otherwise use the default behavior of the XmlUrlResolver class (resolve resources from source)
        else
        {
            return base.GetEntity(absoluteUri, role, ofObjectToReturn);
        }
    }
}

The caching behavior of the XmlCachingResolver class is implemented in the GetEntity method. This is done by creating new WebRequest and HttpRequestCachePolicy objects. The HttpRequestCachePolicy object is created using the Default member of the HttpRequestCacheLevel enumeration.

The CachePolicy property of the WebRequest object is set with the HttpRequestCachePolicy object.

An instance of the XmlCachingResolver class is created with the Boolean enableHttpCaching. With this set to true, the instance resolves a resource from the default cache if possible. If the enableHttpCaching is set to false, the behavior defaults to that of the XmlUrlResolver class.

Note

This example leverages the extensibility of the XML Classes in the .NET Framework. Other classes can be extended and customized to suit the needs of a particular application.

Using the Extended XmlUrlResolver Class

The following example uses the GetEntity method of the XmlCachingResolver class to get a stream containing XML data. An XmlTextReader is used to read the data and display it.

    Dim resolver As New XmlCachingResolver(True)
    Dim baseUri As New Uri("https://localhost/")
    Dim fulluri As Uri = resolver.ResolveUri(baseUri, "books.xml")

    'Get a stream object containing the XML file
    Dim s As Stream = CType(resolver.GetEntity(fulluri, Nothing, GetType(Stream)), Stream)

    'Read the stream object and display the contents of the file
    Dim reader As New XmlTextReader(s)
    Do While reader.Read()
        Console.WriteLine(reader.ReadOuterXml())
    Loop
End Sub
XmlCachingResolver resolver = new XmlCachingResolver(true);
Uri baseUri = new Uri("https://serverName/");
Uri fulluri = resolver.ResolveUri(baseUri, "fileName.xml");

// Get a stream object containing the XML file
Stream s = (Stream)resolver.GetEntity(fulluri, null, typeof(Stream));

// Read the stream object and display the contents of the file
XmlTextReader reader = new XmlTextReader(s);
while (reader.Read())
{
    Console.WriteLine(reader.ReadOuterXml());
}

See Also

Concepts

Design Goals for XML Classes in the .NET Framework

Resolving Resources Using the XmlResolver

Reading XML with the XmlReader

Other Resources

Resolve External XML Resources Named by a URI