Yes, you can fix this.
One option is to create your own resolver that handles the DTD resolution. It can use whatever mechanism it likes, including employing a non-default proxy for outbound communications.
var xmlReaderSettings = new XmlReaderSettings
{
ProhibitDtd = false,
ValidationType = ValidationType.DTD,
XmlResolver = new MyCustomDtdResolver()
};
In the code for MyCustomDtdResolver, you'd specify your desired proxy setting. It could vary depending on the DTD.
You didn't specify, but if the DTDs you are resolving against are fixed and unchanging, then Silverlight and .NET 4.0 have a built-in resolver that does not hit the network (no proxy, no http comms whatsoever). It's called XmlPreloadedResolver. Out of the box it knows how to resolve RSS091 and XHTML1.0. If you have other DTDs, including your own custom DTDs, and they are fixed or unchanging, you can load them into this resolver and use it at runtime, and completely avoid HTTP comms and the proxy complication.
More on that.
If you are not using .NET 4.0, then you can build a "no network" resolver yourself. To avoid the W3C traffic limit, I built a custom resolver myself, for XHTML, maybe you can re-use it.
See also, a related link.
For illustration, here's the code for ResolveUri in a custom Uri resolver.
/// <summary>
/// Resolves URIs.
/// </summary>
/// <remarks>
/// <para>
/// The only Uri's supported are those for W3C XHTML 1.0.
/// </para>
/// </remarks>
public override Uri ResolveUri(Uri baseUri, string relativeUri)
{
if (baseUri == null)
{
if (relativeUri.StartsWith("http://"))
{
Trace(" returning {0}", relativeUri);
return new Uri(relativeUri);
}
// throw if Uri scheme is unknown/unhandled
throw new ArgumentException();
}
if (relativeUri == null)
return baseUri;
// both are non-null
var uri = baseUri.AbsoluteUri;
foreach (var key in knownDtds.Keys)
{
// look up the URI in the table of known URIs
var dtdUriRoot = knownDtds[key];
if (uri.StartsWith(dtdUriRoot))
{
string newUri = uri.Substring(0,dtdUriRoot.Length) + relativeUri;
return new Uri(newUri);
}
}
// must throw if Uri is unknown/unhandled
throw new ArgumentException();
}
here's the code for GetEntity
/// <summary>
/// Gets the entity associated to the given Uri, role, and
/// Type.
/// </summary>
/// <remarks>
/// <para>
/// The only Type that is supported is the System.IO.Stream.
/// </para>
/// <para>
/// The only Uri's supported are those for W3C XHTML 1.0.
/// </para>
/// </remarks>
public override object GetEntity(Uri absoluteUri, string role, Type t)
{
// only handle streams
if (t != typeof(System.IO.Stream))
throw new ArgumentException();
if (absoluteUri == null)
throw new ArgumentException();
var uri = absoluteUri.AbsoluteUri;
foreach (var key in knownDtds.Keys)
{
if (uri.StartsWith(knownDtds[key]))
{
// Return the stream containing the requested DTD.
// This can be a FileStream, HttpResponseStream, MemoryStream,
// or whatever other stream you like. I used a Resource stream
// myself. If you retrieve the DTDs via HTTP, you could use your
// own IWebProxy here.
var resourceName = GetResourceName(key, uri.Substring(knownDtds[key].Length));
return GetStreamForNamedResource(resourceName);
}
}
throw new ArgumentException();
}
The full working code for my custom resolver is available.
If your resolver does network comms, then for a general solution you may want to override the Credentials property.
public override System.Net.ICredentials Credentials
{
set { ... }
}
Also, you may want to expose a Proxy property. Or not. As I said above, you may want to automatically determine the proxy to use, from the DTD URI.