Итак, давайте поговорим о чтении RSS-каналов в .NET-приложении. Когда кто-то упоминает RSS или Atom, я автоматически считаю SyndicationFeed краеугольным камнем решения. Действительно, это приемлемый объект для большинства случаев. Или это?
Недавно я получил электронное письмо от человека, который тестировал мой RSS-ридер для Windows Phone 7 (вы можете прочитать об этом здесь и здесь ). Он работал нормально для большинства каналов, но не для этого:
Я уверен, что это не единственный канал, который может вызвать проблемы, но он был включен в отчет, поэтому я решил проверить его. Когда пользователь предоставил этот канал для приобретения, приложение упало, выдав ошибку:
Глубокая проблема заключается в неправильно отформатированной дате, присутствующей в элементе фида (или нескольких элементах в этом отношении). Интересно, что это было не так для многих других каналов, которые были проверены мной, когда я выпустил проект. Человек, написавший мне электронное письмо, ссылался на этот вопрос в StackOverflow — кто-то уже сообщал об этой проблеме. Очевидно, об этом также сообщалось в Microsoft Connect . Тем не менее, он помечен как закрытый (фиксированный) .
Но это даже не близко к тому, чтобы быть фактически исправленным — я создал пример проекта .NET 4.0, и проблема сохраняется. Возможно, была исправлена другая сторона проблемы, но неверная дата, переданная внутри канала, по-прежнему вызывает сбой.
Как правило, в моем устройстве для чтения RSS я бы использовал WebClient для загрузки строки канала и затем анализировал ее через SyndicationFeed . Я бы вызвал событие DownloadStringCompleted и использовал следующий код:
XmlReader reader = XmlReader.Create(new StringReader(e.Result));
SyndicationFeed feed = SyndicationFeed.Load(reader);
foreach (SyndicationItem sItem in feed.Items)
{
if ((sItem != null) && (sItem.Summary != null) && (sItem.Title != null))
{
App.Model.FeedItems.Add(
new ViewModel.ItemModel()
{
ItemDetails = sItem.Summary.Text,
ItemTitle = sItem.Title.Text,
ItemLink = sItem.Links[0].Uri.ToString()
}
);
}
}
Но поскольку ошибка неизбежна для недопустимых потоков, я решил ее устранить и использовать вместо нее XDocument . С помощью простого запроса LINQ я извлекаю необходимые данные и передаю их в мою модель представления .
XDocument document = XDocument.Parse(e.Result);
var x = from c in document.Root.Element("channel").Elements("item") select c;
foreach (XElement unit in x)
{
App.Model.FeedItems.Add(
new ViewModel.ItemModel()
{
ItemDetails = unit.Element("description").Value,
ItemTitle = unit.Element("title").Value,
ItemLink = unit.Element("link").Value
}
);
}
Поэтому, если вы анализируете каналы с помощью SyndicationFeed , я бы порекомендовал вам использовать этот метод резервного копирования на тот случай, если используемый вами экземпляр SyndicationFeed не сможет правильно проанализировать канал.
Я обновил свой проект для чтения фидов WP7, и вы можете скачать новый источник здесь . Я попытался выделить части кода, которые были изменены, чтобы избежать ошибки.

