ASP.Net при попытке прочитать xml файл "Операция была предпринята в случае несуществующего сетевого подключения"
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 выдает пустую страницу через пару минут.
Я видел это в журналах отслеживания неудачных запросов Azure:
ModuleName: DynamicCompressionModule
Уведомление: SEND_RESPONSE
HttpStatus: 500
HttpReason: ошибка внутреннего сервера
HttpSubStatus: 19
ErrorCode. Была предпринята операция по несуществующему сетевому соединению. (0x800704cd)
Как вы можете видеть, я "играл" с настройками таймаута.
Также попытался поймать все исключения, но он не поймал.
Кроме того, это работает без проблем при отладке веб-приложения локально на моем компьютере. Возможно, подключение к Интернету в моем офисе лучше, чем у Azure, в результате чего xml файл читается быстро без каких-либо проблем.
Возможные обходные пути?
Изменить: я хочу, чтобы потоковая передача XML файла (я избегаю загрузки всего файла, потому что пользователь имеет возможность читать только первые N записей в фиде). В случае, если проблему, описанную выше, нельзя избежать, я буду рад, если кто-то может помочь мне отображать значимое сообщение для пользователя, по крайней мере, вместо пустой страницы.
Ответы
Ответ 1
Вы можете просто использовать
string url = "http://www.example.com/feed.xml";
using(var reader = XmlReader.Create(url){
И он должен работать с поддержкой URL (см. здесь). Тогда потоковая передача может быть использована через yield return x
. Вероятно, это ваш лучший выбор, поскольку вы можете позволить встроенному компоненту обрабатывать потоки так, как он хочет. Вы даже можете обрезать файл с помощью метода ReadValueChunk.
Еще одно соображение, и я думаю, это вопрос, размер вашего примера Azure. Лазерные экземпляры имеют, как известно, небольшой объем памяти, если на самом высоком уровне.
Я также не вижу, что вы избавляетесь от вас от любого из ваших потоков, что также может привести к утечке памяти и чрезмерному использованию памяти.
И учитывая, что это работает на вашей машине, и большинство персональных компьютеров, по крайней мере, столь же мощны, как экземпляр A3 (один уровень ниже верхнего уровня), так и наличие среды IDE для локального удаления утечек памяти, и это кажется жизнеспособным лазером может быть проблема.
Одним из возможных решений было бы использование потоковой передачи файлов. Потоки данных и потоковая передача файлов очень схожи после определенного размера. Один использует файловую систему, в то время как другой использует файл sys (IIRC pagefile.sys), поэтому преобразование в поток файлов мало повлияет на производительность, а недостаток - очистить файл после того, как вы закончите. Но когда речь идет о долларах, потоки дисков дешевле в лазурном мире.
Ответ 2
Попробуйте использовать класс WebClient для получения XML файла.
string xmlAsString;
using (var xmlWebClient = new WebClient())
{
xmlWebClient.Encoding = Encoding.UTF8;
xmlAsString = xmlWebClient.DownloadString(url);
}
XmlDocument currentXml = new XmlDocument();
currentXml.Load(xmlAsString);
Ответ 3
попробуйте это
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 Подробнее