Статьи:







Рекламка:

Предупреждение

Данный материал не может распространяться без письменного разрешения его правообладателя, за исключением публикации на Веб-страницах, при условии целостности содержания материала и указания ссылки на исходную страницу, с которой была скопирована эта статья.

Объединяем RSS-каналы

Объединяем RSS-каналы




Автор: Петер Бернхардт (Peter Bernhardt), Компания 3Leaf Development
Взято отсюда


Статья посвящена методам расширения базового пользовательского элемента управления RSS для работы более чем с одним веб-каналом. Объединяя тематическую информацию из разных источников, можно расширить охват тем, предоставляемых на веб-узле. Пользователи веб-узла могут отбирать и компоновать информацию нужным для себя образом.


Основываясь на предыдущей моей публикации, в этой статье я хочу показать, как можно расширить наш базовый пользовательский элемент управления RSS для работы с несколькими веб-каналами. Объединяя тематическую информацию из разных источников, можно расширить охват тем, предоставляемых на веб-узле. Пользователи веб-узла могут отбирать и компоновать информацию нужным для себя образом.

В качестве источника интересной вспомогательной информации хотелось бы упомянуть статью Кента Шарки (Kent Sharkey) на сайте MSDN, озаглавленную "E Pluriblog Unum: Merging RSS Feeds", в которой продемонстрированы некоторые остроумные способы объединения RSS-каналов в один файл. Поскольку статья основана на версии 1.1 среды .NET Framework, приложенный к ней исходный текст можно использовать в качестве основы для создания собственных проектов. Я не делал этого сам, но использовал некоторые идеи по агрегированию тематического содержимого в сводное представление.

Первая рассмотренная задача — управление списком отдельных веб-каналов. Хотя для отслеживания списка исходных веб-каналов можно использовать целый ряд различных способов, например, файл на языке Outline Processor Markup Language (OPML), для реализации базового диспетчера RSS-каналов я решил использовать возможности сервера SQL Server 2005 Express Edition и возможности работы с данными среды ASP.NET 2.0. Основной причиной для выбора такого метода явилось наличие в ASP.NET 2.0 готовой среды для личной настройки – так называемых веб-частей. В конечном счете основная задача приложения такого типа — предоставление индивидуальным пользователям возможности выбора собственного списка веб-каналов. Но не будем забегать вперед: в этой статье мы рассмотрим управление самим списком веб-каналов.

Создав новый проект в среде Visual Studio Web Developer Express, добавим к нему новую базу данных SQL. Создадим в базе данных единственную таблицу с именем feeds (веб-каналы). При помощи встроенного конструктора таблиц создадим в таблице три столбца: столбец идентификаторов и два столбца для строковых значений, в которых будут храниться название и адрес веб-канала.


Рисунок 1.



Теперь добавим к проекту новый пользовательский веб-элемент управления. С панели инструментов перетащим элемент управления SqlDataSource в поле конструктора пользовательского веб-элемента управления. Элемент SqlDataSource является краеугольным камнем усовершенствованной модели доступа к данным в среде ASP.NET 2.0. Он обеспечивает непосредственное подключение элементов управления пользовательского интерфейса к управляемому поставщику ADO.NET (в данном случае, к базе данных SQL). В меню смарт-тега выберем «Configure Data Source...» (Настроить источник данных...), после чего запустится соответствующий мастер настройки.


Рисунок 2.



Воспользуемся мастером для создания новой строки подключения к базе данных, удостоверившись в том, что включено сохранение строки подключения в файле конфигурации приложения. Мастер предоставляет страницу для создания инструкции SELECT языка SQL, используемой по умолчанию. Здесь можно задать собственную инструкцию языка SQL или хранимую процедуру; мы же воспользуемся имеющейся в базе данных таблицей для непосредственного создания инструкции запроса.


Рисунок 3.



После выбора таблицы доступные столбцы появляются в списке «Columns». При выборе тех или иных столбцов текст инструкции SELECT соответствующим образом обновляется. На следующей странице мастера можно протестировать запрос. В данном случае это не слишком эффективно, поскольку в базе нет данных.

После завершения работы мастера вернемся к панели инструментов и добавим на страницу пользовательского веб-элемента управления элемент GridView. Немедленно появится меню смарт-тега элемента управления GridView. Воспользуемся раскрывающимся меню «Choose Data Source», и для свойства DataSourceID укажем элемент управления SqlDataSource.


Рисунок 4.



Затем в меню смарт-тега выберем пункт «Edit Columns...» (Изменить столбцы), чтобы изменить столбцы элемента управления GridView. При помощи редактора сделаем столбец идентификатора (feedId) невидимым и поменяем заголовки в столбцах title и url, чтобы они выглядели более наглядно при показе на веб-странице.


Рисунок 5.



Также обновим представление элемента управления GridView при помощи редактора автоформата (доступного в меню смарт-тега). После этого перейдем в окно «Properties» (Свойства) для элемента управления GridView. Чтобы пользователи могли обновлять или удалять элементы непосредственно в списке, изменим значения свойств AutoGenerateDeleteButton и AutoGenerateEditButton на true. При этом автоматически изменяется представление элемента GridView в конструкторе. Как показано ниже, теперь с левой стороны от сетки появились ссылки «Edit» (Изменить) и «Delete» (Удалить).


Рисунок 6.



Объектная модель среды ADO.NET 2.0 очень проста: элемент управления SqlDataSource обеспечивает выполнение операций создания, чтения, изменения и удаления (CRUD) в отношении источника данных от имени связанных с ним серверных элементов управления. В нашем случае элемент управления SqlDataSource обеспечивает выполнение не только инструкции SELECT для извлечения данных, но и инструкций DELETE и UPDATE. В окне «Properties» для элемента управления SqlDataSource для свойства DeleteQuery откроем «Command and Property Editor» (Редактор команд и свойств) и введем инструкцию SQL для удаления данных.


Рисунок 7.



Заметьте, что использованный параметр записывается в виде @original_feedId. Элемент управления SqlDataSource имеет также другое свойство, OldValuesParameterFormatString, которое указывает, каким образом входной параметр должен отображаться в запросе. По умолчанию это свойство имеет значение original_{0}, где {0} — прототип фактического значения параметра. Также заметьте, что значение свойства Parameter source изменено на Control, а значение свойства ControlID указывает на элемент управления GridView. Выполнив те же действия, добавим в свойство UpdateQuery элемента управления SqlDataSource инструкцию языка SQL UPDATE.

Все это правильно и должно работать. Однако мы видим, что элемент управления GridView не предоставляет простого способа для добавления записей в базу данных. Для решения этой проблемы имеется ряд различных способов (включая творческий подход к использованию шаблона нижнего колонтитула GridView). Мы же воспользуемся элементом управления DetailsView, который является еще одним гибким способом работы с данными. Он позволяет перемещаться в пределах набора данных, показывая записи по одной, изменять или удалять текущую запись или добавлять новую запись. Этот элемент управления может использоваться в сочетании с GridView, в результате получится классическое представление данных список и подробности. В GridViewпоказывается список доступных для выбора элементов, а подробное представление выбранных элементов выводится в DetailsView. Гибкость этих элементов управления дает большие возможности по созданию удобного пользовательского интерфейса на веб-страницах. В нашем примере представляется удобным непосредственное редактирование и удаление при помощи элемента управления GridView и использование элемента управления DetailsView для добавления записей.


Рисунок 8.



Я расположил элемент управления DetailsView непосредственно под GridView. В его свойстве DataSourceID указываем элемент управления SqlDataSource и проверяем, что значение true указано только для свойства AutoGenerateInsertButton. Для повышения производительности изменим значение свойства EnabledViewState на false. После этого добавим требуемый текст инструкции INSERT в свойство InsertQuery элемента управления SqlDataSource.


Рисунок 9.



Единственное различие между настройкой свойства InsertQuery и других свойств элемента управления SqlDataSource, связанных с запросами, заключается в том, что в качестве значения ControlID для свойства InsertQuery был указан элемент управления DetailsView (а не элемент управления GridView).

Следует отметить, что вся логика управления списком веб-каналов была реализована без написания хотя бы одной строчки текста программы. Разумеется, загрузка и объединение веб-каналов представляет собой отдельную задачу, но определенно стоит приостановиться на этом этапе, чтобы оценить мощь и простоту того, как реализована привязка к данным в среде ASP.NET 2.0.

При реализации совместного показа RSS-каналов версии 2.0, первое препятствие заключается в выборе общего формата для работы с их данными. Поскольку нам требуется показ лишь нескольких стандартных элементов информации (элементы, описания и ссылки), воспользуемся для хранения данных, полученных из каждого веб-канала, строго типизированным элементом управления DataSet. Основное преимущество такого подхода состоит в том, что можно легко привязать полученные данные к элементу управления пользовательского интерфейса. После добавления к проекту нового элемента управления DataSet откроем его в конструкторе и создадим единственный элемент DataTable с четырьмя столбцами (см. ниже).


Рисунок 10.



В дополнение к трем базовым атрибутам элемента, добавим столбец с названием Feed (веб-канал), в котором будем хранить название исходного RSS-канала с целью показа этой информации на веб-странице.

После этого добавим два закрытых метода в текст элемента управления FeedManager. Первый метод, MergeRssFeeds, вызывается из обработчика события Load элемента управления. В первой строке создается экземпляр уровня класса строго типизированного набора данных AggregateRSS. Он используется для хранения данных, полученных от RSS-каналов. После этого выполняется перебор строк элемента управления GridView, каждая из которых представляет собой RSS-канал. В цикле For выполняется вызов второго метода – AddRssFeed – с указанием в качестве параметров названия RSS-канала и его URL-адреса:
private void MergeRssFeeds()
{
    RssData = new AggregatedRSS();
    try
    {
        if (this.GridView1.Rows.Count > 0)
        {
            for (int i = 0; i < this.GridView1.Rows.Count; i++)
            {
                AddRssFeed(this.GridView1.Rows[i].Cells[2].Text,
                this.GridView1.Rows[i].Cells[3].Text);
            }
        }
        this.Repeater1.DataSource = RssData;
        this.Repeater1.DataBind();
    }
    catch (WebException wx)
    {
        Literal1.Text = String.Format(
        "<h3>Ошибка</h3><p>При объединении RSS-потоков возникла исключительная " + 
        " ситуация.<br/>Убедитесь, что есть связь с  " + 
        "Интернетом.</p><p><em>{0}<em></p>", wx.Message);
        Literal1.Visible = true;
    }
}


В конце цикла в качестве свойства DataSource элемента управления Repeater указывается заполненный элемент DataSet, после чего вызывается метод DataBind элемента Repeater для привязки данных к элементу управления.

Вспомогательный метод AddRssFeed выполняет основную часть тяжелой работы в этом приложении. Сначала выполняется получение RSS-канала при помощи класса WebRequest и загрузка данных в объект XmlTextReader. После этого выполняется цикл While для перебора данных в XML-потоке. Чтобы сделать пояснения более наглядными, ниже приведены несколько первых строк исходного текста:
private void AddRssFeed(string feedTitle, string feedUrl)
{
    XmlTextReader rssReader = null;
    int itemCount = 0;

    try
    {
        WebRequest rssFeed = WebRequest.Create(feedUrl);
        rssReader = new xmlTextReader(rssFeed.GetResponse().GetResponseStream());
        while (rssReader.Read())
        {
            // [Подробнее см.ниже]

        }
    }
    finally
    {
        if (itemReader != null) itemReader.Close();
    }
}


Во внешнем цикле While выполняется поиск элементов «item» в RSS-потоке. Нахождение такого элемента означает, что текущим XML-узлом является элемент данных RSS-канала. В таком случае создается новый объект RssItemRow для хранения данных из найденного элемента. Затем при помощи метода ReadSubTree родительского объекта XmlReader создается новый объект типа XmlReader под названием ItemReader. В этом объекте хранятся данные текущего элемента RSS. Для нахождения всех интересующих элементов данных вызывается метод Read дочернего объекта XmlReader. В случае результативного поиска значение данных сохраняется в соответствующей ячейке элемента RssItemRow. В конце выполнения внутреннего цикла While вызывается строго типизированный метод AddRssItemRow объекта DataTable и строки добавляются к элементу DataSet.
while (rssReader.Read())
{
	if ((rssReader.IsStartElement()) && ("item" == rssReader.LocalName))
	{
		XmlReader itemReader = null;
		try
		{
			AggregatedRSS.RssItemRow newRow = RssData.RssItem.NewRssItemRow();
			itemReader = rssReader.ReadSubtree();
			newRow.Feed = feedTitle;
			while (itemReader.Read())
			{
				if (itemReader.IsStartElement())
				{
					if ("title" == itemReader.LocalName)
						newRow.Title = itemReader.ReadString();
					else if ("description" == itemReader.LocalName)
					{
						string newDescription = itemReader.ReadString();
						//Ограничиваем длину описания до 100 символов

						if (newDescription.Length > 100)
							newDescription = newDescription.Substring(0, 100) +
								" ...";
						newRow.Description = newDescription;
					}
					else if ("link" == itemReader.LocalName)
						newRow.Link = itemReader.ReadString();
				}
			}
			
			RssData.RssItem.AddRssItemRow(newRow);
			itemCount++;
		}
		finally
		{
			if (itemReader != null)
				itemReader.Close();
		}
		
		// В каждом канале читаем только первые 5 сообщений 

		if (itemCount >= 5)
			break;
	}
}


Это — весь программный текст, необходимый для объединения информации из RSS-каналов. Как видно, самой сложной частью создания приложения была настройка объекта XmlReader и перебор списка этих объектов для извлечения необходимых данных из веб-каналов. Но после выполнения этой задачи исключительные возможности ASP.NET по привязке к данным делают создание этого приложения очень простым.


Рисунок 11.





Заглядывая вперед, скажем, что следующим шагом в развитии этого проекта будет разделение компонентов диспетчера веб-каналов и показа веб-каналов в различные элементы управления и добавление настройки веб-частей ASP.NET 2.0. До следующей встречи!
Метки: RSS, VS Express, ADO.NET
Идентификатор статьи: 61
Дата занесения/обновления: 03.02.2007 19:50

Комментарии к статье

Ваш комментарий будет первым!
Имя:
Текст:
  mml?
Пожалуйста, подтвердите, что вы человек, введя значение выражения 16+0=