Этюды на ASP2. Делаем RSS-канал на одной SQL-процедуре.
Вообще-то RSS удобно пользоваться для динамично меняющегося контента - типа форумов или новостей. Но в 2009-м году я сделал небольшой рефакторинг своему блогу-программиста и наряду с гостевой книгой, бегущей лентой и прочим я добавил в том числе RSS-каналы.
Я нашел в интернете много какого-то глючного и крученого софта для построения RSS, не сомневаюсь что и Билл Гейтс отметится на этом поприще тоже и выпустит какую-нибудь глюковатую софтину для построения RSS. Наверняка микрософт-пресс поглумится над нами - издав справочник на 1000 страниц, как строить RSS в их софтине, наверняка MS организует обучающие курсы по построению RSS в их софтине...
Поэтому на этой страничке я покажу, как построить RSS-канал на одной-единственной процедуре и крошечной обвязке вокруг нее - формирующей вызов этой процедуры по параметрам, заданным в интернете).
Итак, у меня есть таблица со входными страничками на мой блог vb-net.com:
1: CREATE TABLE [dbo].[Entrance](
2: [i] [int] IDENTITY(1,1) NOT NULL,
3: [ID] [uniqueidentifier] NOT NULL,
4: [CrDate] [smalldatetime] NOT NULL,
5: [Type] [nvarchar](50) NOT NULL,
6: [URL] [nvarchar](250) NOT NULL,
7: [TXT] [nvarchar](250) NOT NULL,
8: [Descr] [nvarchar](1000) NULL
9: ) ON [PRIMARY]
Она заполнена примерно такими данными:
Для формирования RSS-канала нужна одна-единственная SQL-процедура. В моем случае она выдает RSS-канал по переданному параметры - новости SQL или, например новости MONO.
1: ALTER procedure GetRSS
2: @Type nvarchar(10)
3: as
4:
5: CREATE TABLE [dbo].[#X1](
6: [i] [int] IDENTITY(1,1) NOT NULL,
7: [TXT] [nvarchar](max) NULL
8: ) ON [PRIMARY]
9:
10: insert #X1
11: select
12: ' <item>' + char(13) + char(10) +
13: ' <title>' +
14: @Type + ': ' + TXT +
15: '</title>' + char(13) + char(10) +
16: ' <link>' +
17: URL +
18: '</link>' + char(13) + char(10) +
19: ' <guid>' +
20: '//forum.vb-net.com/Forum.aspx?id='+cast(ID as nvarchar(36)) +
21: '</guid>' + char(13) + char(10) +
22: ' <pubDate>' +
23: cast (CrDate as nvarchar)+
24: '</pubDate>' + char(13) + char(10) +
25: ' <description>' +
26: isnull(Descr,'') +
27: '</description>' + char(13) + char(10) +
28: ' </item>' + char(13) + char(10)
29: as RSS
30: from Entrance
31: where Type like @Type+'%'
32: order by type
33:
34:
35: select
36: '<?xml version="1.0"?>' + char(13) + char(10) +
37: '<rss version="2.0">' + char(13) + char(10) +
38: ' <channel>' + char(13) + char(10) +
39: ' <title>' + 'vb-net.com '+ @Type + ' News</title>' + char(13) + char(10) +
40: ' <link>//www.vb-net.com/</link>' + char(13) + char(10) +
41: ' <description>Блог программиста Еремина В.В.</description>' + char(13) + char(10) +
42: ' <language>ru-ru</language>' + char(13) + char(10)
43: as RSS
44: UNION ALL
45:
46: Select TXT as RSS from #X1
47:
48: UNION ALL
49: select
50: ' </channel>' + char(13) + char(10) +
51: '</rss>' + char(13) + char(10)
52: as RSS
Единственная причина, почему я сделал через временную таблу - я хотел просто просортировать новости - если вам это не надо, можно обойтись без временной таблы - это съэкономит ресурсы SQL.
Все что нам нужно еще - крошечная обвязка, чтобы проверить параметры и вызвать эту процедуру. На самом деле эту обвязку можно сделать и в пять строк, если вы не битесь досить свой SQL левыми запросами.
1: <%@ WebHandler Language="VB" Class="rss" %>
2:
3: Imports System
4: Imports System.Web
5:
6: Public Class rss : Implements IHttpHandler
7:
8: Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
9:
10:
11: Dim CN As System.Data.SqlClient.SqlConnection
12: Dim CMD As Data.SqlClient.SqlCommand
13:
14: If HttpContext.Current.Request.QueryString("Type") Is Nothing Then
15: context.Response.ContentType = "text/xml"
16: CN = New System.Data.SqlClient.SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings("SQLServer_ConnectionStrings").ConnectionString)
17: CN.Open()
18: CMD = New Data.SqlClient.SqlCommand("[GetRSS]", CN)
19: CMD.CommandType = Data.CommandType.StoredProcedure
20: CMD.Parameters.AddWithValue("Type", "")
21: ElseIf HttpContext.Current.Request.QueryString("Type") = "" Then
22: context.Response.ContentType = "text/xml"
23: CN = New System.Data.SqlClient.SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings("SQLServer_ConnectionStrings").ConnectionString)
24: CN.Open()
25: CMD = New Data.SqlClient.SqlCommand("[GetRSS]", CN)
26: CMD.CommandType = Data.CommandType.StoredProcedure
27: CMD.Parameters.AddWithValue("Type", "")
28: context.Response.ContentType = "text/xml"
29: ElseIf HttpContext.Current.Request.QueryString("Type") = "MONO" Or _
30: HttpContext.Current.Request.QueryString("Type") = "ASP.NET" Or _
31: HttpContext.Current.Request.QueryString("Type") = "NET" Or _
32: HttpContext.Current.Request.QueryString("Type") = "SOFT" Or _
33: HttpContext.Current.Request.QueryString("Type") = "SQL" Or _
34: HttpContext.Current.Request.QueryString("Type") = "UNIX" Or _
35: HttpContext.Current.Request.QueryString("Type") = "Social" Or _
36: HttpContext.Current.Request.QueryString("Type") = "Notes" Then
37: CN = New System.Data.SqlClient.SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings("SQLServer_ConnectionStrings").ConnectionString)
38: CN.Open()
39: CMD = New Data.SqlClient.SqlCommand("[GetRSS]", CN)
40: CMD.CommandType = Data.CommandType.StoredProcedure
41: CMD.Parameters.AddWithValue("Type", HttpContext.Current.Request.QueryString("Type"))
42: Else
43: context.Response.ContentType = "text/plain"
44: context.Response.Write("Bad request. Use Type=MONO,ASP.NET,NET,SOFT,SQL,UNIX,Notes,Social or blank")
45: Exit Sub
46: End If
47: '
48: Dim RDR As Data.SqlClient.SqlDataReader = CMD.ExecuteReader
49: While RDR.Read
50: context.Response.Write(RDR("RSS"))
51: End While
52: CN.Close()
53:
54: End Sub
55:
56: Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
57: Get
58: Return False
59: End Get
60: End Property
61:
62: End Class
И, наконец, в титуле этого сайта лежит следующее:
1: <link rel="alternate" type="application/rss+xml" title="vb-net.com ALL news" href="//forum.vb-net.com/rss.ashx" />
2: <link rel="alternate" type="application/rss+xml" title="vb-net.com SOFT news" href="//forum.vb-net.com/rss.ashx?type=SOFT" />
3: <link rel="alternate" type="application/rss+xml" title="vb-net.com MONO news" href="//forum.vb-net.com/rss.ashx?type=MONO" />
4: <link rel="alternate" type="application/rss+xml" title="vb-net.com ASP.NET news" href="//forum.vb-net.com/rss.ashx?type=ASP.NET" />
5: <link rel="alternate" type="application/rss+xml" title="vb-net.com NET news" href="//forum.vb-net.com/rss.ashx?type=NET" />
6: <link rel="alternate" type="application/rss+xml" title="vb-net.com SQL news" href="//forum.vb-net.com/rss.ashx?type=SQL" />
7: <link rel="alternate" type="application/rss+xml" title="vb-net.com UNIX news" href="//forum.vb-net.com/rss.ashx?type=UNIX" />
8: <link rel="alternate" type="application/rss+xml" title="vb-net.com Notes news" href="//forum.vb-net.com/rss.ashx?type=Notes" />
9: <link rel="alternate" type="application/rss+xml" title="vb-net.com Social news" href="//forum.vb-net.com/rss.ashx?type=Social" />
Вот собственно и все. И еще пять строчек ушло на формирование бегущей строки. В ней новости, напротив, намеренно перемешаны.
Если же вас интересует как сделать такой же RSS-channel на полностью бесплатной и переносимой платформе MONO, то вы можете посмотреть на эту же технику в СУБД PostgreSQL - Экспорт данных из PostgeSQL в XML.
|