.NET automatisch generierten Web-Service-Client: Wie vermeide ich Schemata aus w3.org anfordernden?

StackOverflow https://stackoverflow.com/questions/217841

Frage

Ich habe einen .NET Web-Service-Client, der von einer wsdl-Datei mit dem wsdl.exe Tool automatisch generiert wurde.

Als ich zuerst die erzeugte Klasse instanziiert, es beginnt eine Reihe von Dokumenten aus w3.org und anderen zu beantragen. Die erste ist http://www.w3.org/2001/XMLSchema.dtd

Neben nicht will, unnötiger Verkehr bewirken w3.org, ich brauche die Anwendung auszuführen zu können, ohne eine Verbindung zum Internet (der Web-Service ist ein „Intra-web-service“).

Wer die Lösung wissen?

Wenn es hilft, ist hier die Stacktrace ich, wenn ich Internet nicht haben:

"An error has occurred while opening external DTD 'http://www.w3.org/2001/XMLSchema.dtd': The remote name could not be resolved: 'www.w3.org'"

   at System.Net.HttpWebRequest.GetResponse()
   at System.Xml.XmlDownloadManager.GetNonFileStream(Uri uri, ICredentials credentials)
   at System.Xml.XmlDownloadManager.GetStream(Uri uri, ICredentials credentials)
   at System.Xml.XmlUrlResolver.GetEntity(Uri absoluteUri, String role, Type ofObjectToReturn)
   at System.Xml.XmlTextReaderImpl.OpenStream(Uri uri)
   at System.Xml.XmlTextReaderImpl.DtdParserProxy_PushExternalSubset(String systemId, String publicId)

   at System.Xml.XmlTextReaderImpl.Throw(Exception e)
   at System.Xml.XmlTextReaderImpl.DtdParserProxy_PushExternalSubset(String systemId, String publicId)
   at System.Xml.XmlTextReaderImpl.DtdParserProxy.System.Xml.IDtdParserAdapter.PushExternalSubset(String systemId, String publicId)
   at System.Xml.DtdParser.ParseExternalSubset()
   at System.Xml.DtdParser.ParseInDocumentDtd(Boolean saveInternalSubset)
   at System.Xml.DtdParser.Parse(Boolean saveInternalSubset)
   at System.Xml.XmlTextReaderImpl.DtdParserProxy.Parse(Boolean saveInternalSubset)
   at System.Xml.XmlTextReaderImpl.ParseDoctypeDecl()
   at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
   at System.Xml.XmlTextReaderImpl.Read()
   at System.Xml.Schema.Parser.StartParsing(XmlReader reader, String targetNamespace)
   at System.Xml.Schema.Parser.Parse(XmlReader reader, String targetNamespace)
   at System.Xml.Schema.XmlSchemaSet.ParseSchema(String targetNamespace, XmlReader reader)
   at System.Xml.Schema.XmlSchemaSet.Add(String targetNamespace, XmlReader schemaDocument)
   at [...]WebServiceClientType..cctor() in [...]
War es hilfreich?

Lösung 2

ich die XmlResolver benötigt, so Tamberg Lösung nicht ganz funktioniert hat. Ich löste es durch meine eigenen XmlResolver implementieren, die die erforderlichen Schemata aus eingebetteten Ressourcen lesen, anstatt sie herunterzuladen.

Das Problem hat nichts mit dem automatisch generierten Code zu tun, durch die Art und Weise.

Das Web-Service-Client hatte eine andere Implementierung-Datei, die so etwas wie dies enthielt:

public partial class [...]WebServiceClientType
  {
    private static readonly XmlSchemaSet _schema;

    static KeyImportFileType()
    {
      _schema = new XmlSchemaSet();
      _schema.Add(null, XmlResourceResolver.GetXmlReader("http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd"));
      _schema.Add(null, XmlResourceResolver.GetXmlReader("http://www.w3.org/TR/2002/REC-xmlenc-core-20021210/xenc-schema.xsd"));
      _schema.Compile();
    }

und es war diese Klasse-Konstruktor, der fehlgeschlagen ist.

Andere Tipps

Wenn Sie haben Zugriff auf die XmlReader (oder XmlTextReader) können Sie folgendes tun:

XmlReader r = ...
r.XmlResolver = null; // prevent xsd or dtd parsing

Viele Grüße, Tamberg

Hier ist meine Lösung. Ich hoffe, es spart jemand aus, durch das .NET Framework debuggen, wie ich die Untermauerung XmlUrlResolver musste auszuarbeiten. Es wird entweder Last von einer lokalen Ressource (resx Textdatei), Cache oder XmlUrlResolver Standardverhalten verwenden:

using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Net;
using System.Net.Cache;
using System.IO;
using System.Resources;

namespace AxureExport {

    //
    // redirect URL resolution to local resource (or cache)
    public class XmlCustomResolver : XmlUrlResolver {

        ICredentials _credentials;
        ResourceManager _resourceManager;

        public enum ResolverType { useDefault, useCache, useResource };
        ResolverType _resolverType;

        public XmlCustomResolver(ResolverType rt, ResourceManager rm = null) {
            _resourceManager = rm != null ? rm : AxureExport.Properties.Resources.ResourceManager;
            _resolverType = rt;
        }

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

        public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn) {
            object response = null;

            if (absoluteUri == null)
                throw new ArgumentNullException(@"absoluteUri");

            switch (_resolverType) {
                default:
                case ResolverType.useDefault:                   // use the default behavior of the XmlUrlResolver
                    response = defaultResponse(absoluteUri, role, ofObjectToReturn);
                    break;

                case ResolverType.useCache:                     // resolve resources thru cache
                    if (!isExternalRequest(absoluteUri, ofObjectToReturn)) {
                        response = defaultResponse(absoluteUri, role, ofObjectToReturn);
                        break;
                    }

                    WebRequest webReq = WebRequest.Create(absoluteUri);
                    webReq.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.Default);
                    if (_credentials != null)
                        webReq.Credentials = _credentials;

                    WebResponse wr = webReq.GetResponse();
                    response = wr.GetResponseStream();
                    break;

                case ResolverType.useResource:                  // get resource from internal resource
                    if (!isExternalRequest(absoluteUri, ofObjectToReturn)) {
                        response = defaultResponse(absoluteUri, role, ofObjectToReturn);    // not an external request
                        break;
                    }

                    string resourceName = uriToResourceKey(absoluteUri);
                    object resource = _resourceManager.GetObject(resourceName);
                    if (resource == null)
                        throw new ArgumentException(@"Resource not found.  Uri=" + absoluteUri + @" Local resourceName=" + resourceName);

                    if (resource.GetType() != typeof(System.String))
                        throw new ArgumentException(resourceName + @" is an unexpected resource type.  (Are you setting resource FileType=Text?)");

                    response = ObjectToUTF8Stream(resource);
                    break;
            }

            return response;
        }

        //
        // convert object to stream
        private static object ObjectToUTF8Stream(object o) {
            MemoryStream stream = new MemoryStream();

            StreamWriter writer = new StreamWriter(stream, Encoding.UTF8);
            writer.Write(o);
            writer.Flush();
            stream.Position = 0;

            return stream;
        }

        //
        // default response is to call tbe base resolver
        private object defaultResponse(Uri absoluteUri, string role, Type ofObjectToReturn) {
            return base.GetEntity(absoluteUri, role, ofObjectToReturn);
        }

        //
        // determine whether this is an external request
        private static bool isExternalRequest(Uri absoluteUri, Type ofObjectToReturn) {
            return absoluteUri.Scheme == @"http" && (ofObjectToReturn == null || ofObjectToReturn == typeof(Stream));
        }

        //
        // translate uri to format compatible with reource manager key naming rules
        // see: System.Resources.Tools.StronglyTypedResourceBuilder.VerifyResourceName Method
        //   from http://msdn.microsoft.com/en-us/library/ms145952.aspx:
        private static string uriToResourceKey(Uri absoluteUri) {
            const string repl = @"[ \xA0\.\,\;\|\~\@\#\%\^\&\*\+\-\/\\\<\>\?\[\]\(\)\{\}\" + "\"" + @"\'\:\!]+";
            return Regex.Replace(Path.GetFileNameWithoutExtension(absoluteUri.LocalPath), repl, @"_");
        }
    }
}

Danke Tamberg, gespeichert Sie mir viel Zeit mit Ihrer prägnanten und richtigen Antwort. Ich wusste nicht, die Standard-Resolver auf die Bahn gehen würden. Überprüfen MSDN ist Staaten -

  

XmlResolver ist die Standard-Resolver für alle Klassen im System.Xml-Namespace. Sie können auch Ihre eigenen Resolver erstellen ...

ich Ihre Antwort implementiert haben, den Resolver auf NULL Einstellung, die das Problem löst und reduziert den Netzwerk-Overhead.

XmlReader r = ...r.XmlResolver = null; // prevent xsd or dtd parsing

Nochmals vielen Dank, Andy

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top