【问题标题】:ASP.Net when trying to read xml file, "An operation was attempted on a nonexistent network connection"ASP.Net 尝试读取 xml 文件时,“尝试在不存在的网络连接上进行操作”
【发布时间】:2016-02-22 03:01:46
【问题描述】:
string url = "http://www.example.com/feed.xml";
var settings = new XmlReaderSettings();
settings.IgnoreComments = true;
settings.IgnoreProcessingInstructions = true;
settings.IgnoreWhitespace = true;
settings.XmlResolver = null;
settings.DtdProcessing = DtdProcessing.Parse;
settings.CheckCharacters = false;
var request = (HttpWebRequest)WebRequest.Create(url);
request.Timeout = 900000;
request.KeepAlive = true;
request.IfModifiedSince = lastModified;
var response = (HttpWebResponse)request.GetResponse();
Stream stream;
stream = response.GetResponseStream();
stream.ReadTimeout = 600000;
var xmlReader = XmlReader.Create(stream, settings);

while (!xmlReader.EOF)
{
...

当我在大型 xml 文件(下载速度也很慢)上尝试此操作时,我的 azure web 应用程序会在几分钟后抛出一个空白页。

我在 Azure 的失败请求跟踪日志中看到了这一点:

模块名称:DynamicCompressionModule

通知:SEND_RESPONSE

HttpStatus:500

HttpReason:内部服务器错误

HttpSubStatus:19

ErrorCode:尝试对不存在的网络连接进行操作。 (0x800704cd)

如您所见,我一直在“玩弄”超时设置。 还尝试捕获所有异常,但没有捕获任何异常。

此外,在我的计算机上本地调试 Web 应用程序时,这可以正常工作。可能是我办公室的互联网连接比 Azure 的好,导致 xml 文件被快速读取而没有任何问题。

任何可能的解决方法? 编辑:我想继续流式传输 XML 文件(我避免下载整个文件,因为用户可以选择只读取提要的前 N ​​个条目)。如果无法避免上述问题,如果有人可以帮助我至少向用户显示有意义的消息,而不是空白页,我会很高兴。

【问题讨论】:

  • 我肯定会打赌下载的大小和时间会影响 azure 云中的某些内容代理重置您的连接。
  • 这也可能是由服务器超时引起的,也就是您的代码连接到的服务器超时(此处为“example.com/feed.xml"”)。
  • 是的@SimonMourier,我相信你可能是对的。但是当我无法捕捉到异常并给用户一个有意义的消息时,这是非常令人沮丧的。
  • 你可以试试ServiceStack 库。查看其他 SO 线程 stackoverflow.com/questions/10040680/…
  • 您尝试下载的 XML 的大小是多少?

标签: c# asp.net xml azure


【解决方案1】:

试试这个

    static IEnumerable<XElement> StreamCustomerItem(string uri)
   {
    using (XmlReader reader = XmlReader.Create(uri))
    {
        XElement name = null;
        XElement item = null;

        reader.MoveToContent();

        // Parse the file, save header information when encountered, and yield the
        // Item XElement objects as they are created.

        // loop through Customer elements
        while (reader.Read())
        {
            if (reader.NodeType == XmlNodeType.Element
                && reader.Name == "Customer")
            {
                // move to Name element
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element &&
                        reader.Name == "Name")
                    {
                        name = XElement.ReadFrom(reader) as XElement;
                        break;
                    }
                }

                // loop through Item elements
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.EndElement)
                        break;
                    if (reader.NodeType == XmlNodeType.Element
                        && reader.Name == "Item")
                    {
                        item = XElement.ReadFrom(reader) as XElement;
                        if (item != null)
                        {
                            XElement tempRoot = new XElement("Root",
                                new XElement(name)
                            );
                            tempRoot.Add(item);
                            yield return item;
                        }
                    }
                }
            }
        }
    }
}

static void Main(string[] args)
{
    XStreamingElement root = new XStreamingElement("Root",
        from el in StreamCustomerItem("Source.xml")
        select new XElement("Item",
            new XElement("Customer", (string)el.Parent.Element("Name")),
            new XElement(el.Element("Key"))
        )
    );
    root.Save("Test.xml");
    Console.WriteLine(File.ReadAllText("Test.xml"));
}

基于以下 XML

<?xml version="1.0" encoding="utf-8"?>
<Root>
  <Item>
    <Customer>A. Datum Corporation</Customer>
    <Key>0001</Key>
  </Item>
  <Item>
    <Customer>A. Datum Corporation</Customer>
    <Key>0002</Key>
  </Item>
  <Item>
    <Customer>A. Datum Corporation</Customer>
    <Key>0003</Key>
  </Item>
  <Item>
    <Customer>A. Datum Corporation</Customer>
    <Key>0004</Key>
  </Item>
  <Item>
    <Customer>Fabrikam, Inc.</Customer>
    <Key>0005</Key>
  </Item>
  <Item>
    <Customer>Fabrikam, Inc.</Customer>
    <Key>0006</Key>
  </Item>
  <Item>
    <Customer>Fabrikam, Inc.</Customer>
    <Key>0007</Key>
  </Item>
  <Item>
    <Customer>Fabrikam, Inc.</Customer>
    <Key>0008</Key>
  </Item>
  <Item>
    <Customer>Southridge Video</Customer>
    <Key>0009</Key>
  </Item>
  <Item>
    <Customer>Southridge Video</Customer>
    <Key>0010</Key>
  </Item>
</Root>

Fore More details

【讨论】:

    【解决方案2】:

    你可以使用

    string url = "http://www.example.com/feed.xml";
    using(var reader = XmlReader.Create(url){
    

    它应该在支持 url 时工作(请参阅here)。然后可以通过yield return x 使用流媒体。这可能是您最好的选择,因为您可以让本机组件以它想要的方式处理流式传输。您甚至可以通过 ReadValueChunk 方法对文件进行分块。

    另一个考虑因素,我猜是这个问题,是 Azure 实例的大小。众所周知,Azure 实例的内存量很少,除非在最高层。

    我也没有看到您处理您的任何流,这也可能导致内存泄漏和过多的内存使用。

    考虑到它可以在你的机器上运行,而且大多数个人电脑至少和 A3 实例一样强大(在顶部下方一层),并且有一个 IDE 可以在本地清理任何内存泄漏,这似乎是可行的天蓝色实例可能是问题所在。

    一种可能的解决方案是使用文件流。内存流和文件流在一定大小后非常相似。一个使用文件系统,而另一个使用 sys 文件(IIRC pagefile.sys),因此转换为文件流对性能影响不大,缺点是完成后必须清理文件。但是当考虑到美元时,磁盘流在天蓝色的世界中更便宜。

    【讨论】:

      【解决方案3】:

      尝试使用 WebClient 类获取 xml 文件。

      string xmlAsString;
      using (var xmlWebClient = new WebClient())
                  {
                      xmlWebClient.Encoding = Encoding.UTF8;
                      xmlAsString = xmlWebClient.DownloadString(url);
                  }
      
      XmlDocument currentXml = new XmlDocument();
      currentXml.Load(xmlAsString);
      

      【讨论】:

      • 感谢安德烈!这似乎是一个不错的选择,但我试图避免它,因为我不想下载 1GB+ xml 文件并将它们加载到内存中,这就是我更喜欢流式传输它们的原因。我会记住这一点,以防我找不到更好的解决方案。
      猜你喜欢
      • 2012-03-30
      • 1970-01-01
      • 1970-01-01
      • 2021-11-04
      • 2011-04-03
      • 2015-08-22
      • 1970-01-01
      • 1970-01-01
      • 2013-06-07
      相关资源
      最近更新 更多