Web Services .NET自动生成的Web服务客户端:如何避免从www.example.com请求架构w3.org?

rwqw0loc  于 2022-11-15  发布在  .NET
关注(0)|答案(5)|浏览(117)

我有一个.NET Web服务客户端,它是使用wsdl.exe工具从wsdl文件自动生成的。
当我第一次示例化生成的类时,它开始从www.example.com和其他网站请求一堆文档w3.org。
除了不想对www.example.com造成不必要的流量w3.org,我还需要能够在不连接到Internet的情况下运行应用程序(Web服务是“Intra-Web-Service”)。
有人知道解决办法吗?
如果有帮助的话,下面是我在没有Internet时得到的堆栈跟踪:

"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 [...]
unftdfkk

unftdfkk1#

如果您有权访问XmlReader(或XmlTextReader),则可以执行以下操作:

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

此致,谭伯格

xghobddn

xghobddn2#

我需要XmlResolver,所以tamberg的解决方案不太好用。我通过实现自己的XmlResolver来解决这个问题,该解决方案从嵌入式资源中读取必要的架构,而不是下载它们。
顺便说一句,这个问题与自动生成的代码没有任何关系。
web-service-client有另一个实现文件,其中包含如下内容:

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();
    }

就是这个类构造函数失败了。

kt06eoxx

kt06eoxx3#

这是我的解决方案。我希望它可以让某些人不必像我那样通过.NET Framework进行调试,以解决XmlUrlResolver的基础问题。它将从本地资源(resx文本文件)、缓存加载,或者使用XmlUrlResolver的默认行为:

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, @"_");
        }
    }
}
tzdcorbm

tzdcorbm4#

Microsoft实用工具mage.exe(用于生成清单)出现问题。此应用程序可能作为DotNet、Azure DevOps上的生成/部署管道的一部分调用。
在这个github上有一个完整的解释,以及一个建议如何使用防火墙传出规则阻止访问https://github.com/WKnak/microsoft-mage-xml-bug/
例如,当尝试使用特定的DOCTYPE散列SVG文件时,它会尝试连接到W3C服务器(hans-moleman.w3.org,IP 128.30.52.100),并且存在可能产生超时的故意延迟,或者您必须等待1分40秒才能获得所请求的每个DTD。
在W3C常见问题页面上有一个与此相关的问题:
https://www.w3.org/Help/Webmaster.html#help

**为什么W3C阻止我的IP?**W3C很可能是因为流量过大而阻止您的IP;这通常是由于重复地向我们请求相同的资源(例如DTD、模式、实体或名称空间文档)。
**W3C服务器返回DTD的速度很慢。这种延迟是故意的吗?**是的。由于各种软件系统每天从我们的站点下载DTD数百万次(尽管我们的服务器有缓存指令),我们已经开始提供DTD和模式(DTD、XSD、ENT、MOD、我们这样做的目的是让更多的人关注我们正在发生的问题,并保护网站其他部分的稳定性和响应时间。

eulz3vhy

eulz3vhy5#

感谢Tamberg,您简洁正确的回答为我节省了大量的时间。我没有意识到默认的解析器会转到Web。检查MSDN是状态-

  • XmlResolver是System.Xml命名空间中所有类的默认冲突解决程序。您也可以创建自己的冲突解决程序... *

我已经实现了您的答案,将解析器设置为NULL,这样就解决了问题并减少了网络开销。

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

再次谢谢你,安迪

相关问题