Путь разработчика

Сборник полезных примеров и советов для .NET программистов

Архив за Апрель, 2008

web.sitemap (требования к программе)

2008-04-30 от Kosten

В первом релизе SitemapEditor предполагается реализовать следующие функции:
- создание нового файла или редактирование существующего
- представление содержимого web.sitemap файла в виде дерева
- редактирование элементов web.sitemap файла (создание, удаление, изменение)

Рубрика: .NET, SitemapEditor | Комментариев нет »

Проблема с картинками формата PNG в GDI+

2008-04-30 от Kosten

При работе над одним web-проектом я столкнулся с тем, что при выполнении следующего кода возникает исключение.

    ...
    Bitmap result = new Bitmap(...);
    ...
    result.Save(Response.OutputStream, ImageFormat.Png);

Как выяснилось позже, это результат ошибки в библиотеке GDI+. Решение данной проблемы представлено ниже:

    ...
    Bitmap result = new Bitmap(...);
    ...
    MemoryStream ms = new MemoryStream();
    result.Save(ms, ImageFormat.Png);
    Response.ContentType = "image/png";
    ms.WriteTo(HttpContext.Current.Response.OutputStream);

С сохранием картинок в других форматах такой проблемы не возникает.

Рубрика: C# | Комментариев нет »

Новостная лента на ASP.NET

2008-04-28 от Kosten

Новостная лента на ASP.NET

В настоящее время очень распространена публикация новостей на различных web-сайтах. В этой статье будет рассказано о создании новостной ленты с поддержкой RSS средствами ASP.NET.

Для хранения новостей мы будем использовать MSSQL Server 2000. Новости будут храниться в таблице, структура которой приведена ниже:

Пример таблицы БД MSSQL

Где поле id_news – уникальный идентификатор новости, news_date – дата создание новости, news_text – основной текст новости, news_link – ссылка на подробное описание новости.

Для создания этой таблицы можно использовать следующий SQL-запрос:

CREATE TABLE [dbo].[News]
(
 [id_news] [int] IDENTITY (1, 1) NOT NULL ,
 [news_date] [datetime] NOT NULL ,
 [news_text] [text] NOT NULL ,
 [news_link] [char] (250) NOT NULL
)
ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

ALTER TABLE [dbo].[News] WITH NOCHECK ADD
 CONSTRAINT [PK_News] PRIMARY KEY  CLUSTERED
 (
  [id_news]
 )  ON [PRIMARY]
GO

Для получения блока новостей будем использовать следующую хранимую процедуру:

CREATE PROCEDURE GetNews
AS BEGIN
SELECT TOP 3 news_text, news_date, news_link FROM News ORDER BY news_date DESC
END

Структура таблицы может быть дополнена или изменена по усмотрению разработчика.

Прежде чем приступить непосредственно к программированию, кратко познакомимся с технологией RSS.

RSS (Really Simple Syndication) — дословно можно перевести как «очень простое синдицирование». Syndicate (англ.) – печатное агентство приобретающие информацию или непосредственно процесс приобретения информации. Другими словами, RSS – это формат обмена информацией в web. Изначально данный формат был разработан компанией Netscape для крупных новостных порталов. В последствии Netscape отказалась от поддержки своей версии формата RSS и передала его другой компании. В это время другая организация развивала свою версию RSS. В результате, в настоящее время известно семь форматов RSS разных версий. Возникает вопрос, какой формат RSS использовать в своих разработках? В данный момент, наиболее популярны версии 1.0 и 2.0, как стабильные. Остальные форматы отменены. Сравним форматы RSS 1.0 и 2.0.

Версия Преимущества Состояние Рекомендации
1.0 Основан на языке RDF. Расширяется с помощью модулей. Не зависит от какой-либо одной компании Стабилен. Ведется активная разработка модулей Используйте для приложений, где используется RDF, либо в том случае, если вам нужен какой-то определенный модуль
2.0 Расширяется с помощью модулей. Прост при миграции с ветки форматов 0.9х Стабилен. Ведется активная разработка модулей Используйте для публикации новостей общего назначения

В нашем примере мы будем работать с RSS 2.0. Рассмотрим структуру простого RSS документа (будем использовать только обязательные элементы):

<?xml version=’1.0′ encoding=’windows-1251′ ?>
<rss version=’2.0′>
 <channel>
  <title>Простой RSS канал</title>
  <link>http://www.mypage.ru</link>
  <description>Новости с моего сайта<description>
  <item>
   <title>Первая новость</title>
   <link>http://www.mypage.ru/news/1</link>
   <description>Сайт начал работу.</description>
  </item>
  <item>
   <title>Открыт форум</title>
   <link>http://www.mypage.ru/news/2</link>
   <description>На сайте открыт форум.</description>
  </item>
 </channel>
</rss>

Корневым элементом в документе является rss с указанием номера версии в атрибуте version. В элемент rss вложен элемент channel, который имеет следующие обязательные элементы - title (название канала), link (URL web-сайта соответствующего каналу) и description (описание канала). Элемент channel может содержать любое количество элементов item. Эти элементы могут содержать в себе публикации целиком, или же анонсы со ссылками на полные варианты публикаций. Все вложенные элементы являются необязательными, однако хотя бы один элемент <title> или <description> должен присутствовать. В нашем примере мы используем следующие элементы – title (заголовок новости), link (ссылка на полный вариант публикации), description (анонс новости).

Для разработки проекта будем использовать MS Visual Studio 2003. Создадим новый ASP.NET проект с именем rssnews:

Создание нового проекта в Microsoft Visual Studio

Добавим в проект два элемента – еще одну aspx-страницу и web user control. Назовем их rss.aspx (генератор RSS документа) и news.ascx (пользовательский элемент управления для отображения новостей). Созданную по умолчанию страницу WebForm1.aspx переименуем в Default.aspx.

Откроем элемент news.ascx в режиме Design и разместим на нем компонент Repeater:

Настройка элемента repeater

В режиме HTML отредактируем файл news.ascx следующим образом:

<asp:Repeater id="Repeater1" runat="server">
 <HeaderTemplate>
  <h4>Новости</h4>
  <table>
 </HeaderTemplate>
 <ItemTemplate>
  <tr>
   <td colspan="2"><br>
    <%# DataBinder.Eval(Container.DataItem, "text") %>
   </td>
  </tr>
  <tr>
   <td><%# DataBinder.Eval(Container.DataItem, "date") %></td>
   <td><%# DataBinder.Eval(Container.DataItem, "link") %></td>
  </tr>
 </ItemTemplate>
 <FooterTemplate>
  </table>
 </FooterTemplate>
</asp:Repeater>

Тэги HeaderTemplate, ItemTemplate и FooterTemplate предназначены для описания заголовка, элемента и «башмака» таблицы.

Перейдем в режим редактирования кода и отредактируем файл news.ascx.cs следующим образом:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
namespace rssnews
{
 /// &lt;summary&gt;
 /// Summary description for news.
 /// &lt;/summary&gt;
 public class news : UserControl
 {
  protected Repeater Repeater1;
 
  private void Page_Load(object sender, EventArgs e)
  {
   // Put user code to initialize the page here
   ArrayList alNews = new ArrayList();
   SqlConnection sqlConn = new SqlConnection(ConfigurationSettings.AppSettings["connectionString"]);
   SqlCommand sqlComd = sqlConn.CreateCommand();
   sqlComd.CommandText = "GetNews";
   sqlComd.CommandType = CommandType.StoredProcedure;
   sqlConn.Open();
   sqlComd.ExecuteNonQuery();
 
   SqlDataAdapter sqlAdap = new SqlDataAdapter();
   sqlAdap.SelectCommand = sqlComd;
 
   DataSet ds = new DataSet();
   sqlAdap.Fill(ds, "news");
   DataTable dt = ds.Tables["news"];
   foreach(DataRow dr in dt.Rows)
   {
    News n = new News();
    n.date = dr["news_date"].ToString().Substring(0, 10);
    n.text = dr["news_text"].ToString();
    n.link = "&lt;a href=" + dr["news_link"].ToString() + ">Подробнее...&lt;/a&gt;";
    alNews.Add(n);
   }
   Repeater1.DataSource = alNews;
   Repeater1.DataBind();
  }
  #region Web Form Designer generated code
  override protected void OnInit(EventArgs e)
  {
   //
   // CODEGEN: This call is required by the ASP.NET Web Form Designer.
   //
   InitializeComponent();
   base.OnInit(e);
  }
 
  /// &lt;summary&gt;
  ///  Required method for Designer support - do not modify
  ///  the contents of this method with the code editor.
  /// &lt;/summary&gt;
  private void InitializeComponent()
  {
   this.Load += new EventHandler(this.Page_Load);
 
  }
  #endregion
 }
 public class News
 {
  private string Text;
  private string Link;
  private string Date;
  public string text
  {
   get
   {
    return Text;
   }
   set
   {
    Text = value;
   }
  }
  public string date
  {
   get
   {
    return Date;
   }
   set
   {
    Date = value;
   }
  }
  public string link
  {
   get
   {
    return Link;
   }
   set
   {
    Link = value;
   }
  }
 
 }
}

Механизм работы, приведенный в коде, следующий:

  • создается соединение с БД и вызывается хранимая процедура GetNews
  • заполняется список объектов класса News
  • происходит связывание компонента Repeater со списком объектов класса News

Для реализации такого механизма в классе News используются общедоступные свойства text, date, link.

Страница с новостями готова, перейдем к реализации RSS в нашем проекте.
Откроем страницу rss.aspx в режиме HTML и удалим все строки кроме первой, содержащей директиву Page:

<%@ Page language="c#" Codebehind="rss.aspx.cs" AutoEventWireup="false" Inherits="rssnews.rss" %>

Перейдем в режим редактирования кода и отредактируем файл rss.aspx.cs следующим образом:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Web.UI;
 
namespace rssnews
{
 /// <summary>
 /// Summary description for rss.
 /// </summary>
 public class rss : Page
 {
  private void Page_Load(object sender, EventArgs e)
  {
   // Put user code to initialize the page here
   SqlConnection scConn = new SqlConnection(ConfigurationSettings.AppSettings["connectionString"]);
   SqlCommand scComd = scConn.CreateCommand();
   string strCmd = "select news_theme title, news_text description, news_link link from news item &quot;;
   strCmd += &quot;ORDER BY news_date DESC FOR XML  AUTO,ELEMENTS&quot;;
   scComd.CommandText = strCmd;
   scComd.CommandType = CommandType.Text;
   scConn.Open();
   scComd.ExecuteNonQuery();
 
   SqlDataAdapter sda = new SqlDataAdapter();
   sda.SelectCommand = scComd;
   DataSet ds = new DataSet();
   sda.Fill(ds, "xml");
   DataTable dt = ds.Tables["xml"];
   string strRss = "<?xml version='1.0' encoding='windows-1251'?><rss version='2.0'><channel>";
   strRss += "<titlе>Новости сайта</titlе><linк>http://site.ru/News.aspx</linк><description>Наши последние новости</description><language>en-us</language>";
   strRss += dt.Rows[0][0].ToString();
   strRss += "</channel></rss>";
   Response.ContentType = "text/xml";
   Response.Write(strRss);  
  }
  #region Web Form Designer generated code
  override protected void OnInit(EventArgs e)
  {
   //
   // CODEGEN: This call is required by the ASP.NET Web Form Designer.
   //
   InitializeComponent();
   base.OnInit(e);
  }
 
  /// <summary>
  /// Required method for Designer support - do not modify
  /// the contents of this method with the code editor.
  /// </summary>
  private void InitializeComponent()
  {    
   this.Load += new EventHandler(this.Page_Load);
  }
  #endregion
 }
}

Разберем приведенный выше листинг. В первую очередь производится соединение с БД и выполнятся SQL – запрос. На запросе остановимся подробнее. Используемый в программе SQL-запрос имеет следующий вид:

SELECT news_theme title, news_text description, news_link link FROM news item
ORDER BY news_date DESC FOR XML  AUTO, ELEMENTS

В данном запросе из таблицы News выбираются поля news_theme, news_text, news_link, которым даются псевдонимы title, description link соответственно. Самой таблице News дается псевдоним item. Выборка сортируется по полю news_date. Окончательный результат представляется в XML формате:

<item>
<title>…</title>
<link>…</link>
<description>…</description>
</item>
<item>
…
</item>

Пример работы новостной ленты на ASP.NET

Таким образом, мы получили часть RSS документа. Далее полученный XML ответ из БД дополняется до необходимого формата, соответствующего спецификации RSS.

Для тестирования новостной ленты необходимо обратится к сайту, указав соответствующий адрес в адресной строке браузера (на моей машине он выглядит так - http://localhost/aspdev/rssnews/Default.aspx). Примерный результат представлен на рисунке. Что изменить вид новостной ленты, необходимо изменить содержимое тэгов HeaderTemplate, ItemTemplate и FooterTemplate компонента Repeater.

Тестирование RSS производится при помощи любого RSS reader’а. В качестве адреса потока (feed) необходимо указать адрес страницы генерирующей RSS документ (в моем случае он выглядит так http://localhost/aspdev/rssnews/rss.aspx).

Замечание: во всех приведенных примерах для получения строки соединения (connection string) с БД используется параметр connectionString записанный в файл web.config следующим образом:

<add key="connectionString" value="workstation
id=computerName;packet size=4096;user id=user;pwd=secret;
data source=computerName;persist security info=False;initial catalog=DBName" />



Скачать исходник: rssnews.zip (13 кб)

Рубрика: .NET, ASP.NET, C#, Develop | 1 комментарий »

web.sitemap

2008-04-26 от Kosten

Во время знакомства с ASP.NET 2.0 обратил внимание на web.sitemap, который позволяет, достаточно просто, организовывать меню на сайте. Ложкой дегтя является отстутствие какой-либо утилиты для наглядной работы web.sitemap. В настоящее время для описания структуры меню необходимо править XML-файл.
В данный момент я работаю над создание утилиты, которая поможет наглядно представлять и редактировать меню, генерируемое из файла web.sitemap.
Следите за обновлениями.

Рубрика: .NET, ASP.NET, Develop | Комментарии (4) »