Итак, давайте поговорим о чтении 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, и вы можете скачать новый источник здесь . Я попытался выделить части кода, которые были изменены, чтобы избежать ошибки.