Исходники.Ру - Программирование
Исходники
Статьи
Книги и учебники
Скрипты
Новости RSS
Магазин программиста

Главная » Статьи по программированию » .NET - Все статьи »

Обсудить на форуме Обсудить на форуме

Использование шаблонов дизайна в ASP .NET

Вступление

Не будем подробно останавливать на самой идее использования шаблонов, считая читателя знакомой с ней (иначе рекомендуем вначале ознакомится с идеями FastTemplate для Perl или PHP, Smarty для PHP).

Под шаблонами понимается не то, что является шаблонами в терминологии .NET, мы рассмотрим достаточно старую и хорошо себя зарекомендовавшую в других языках веб-программирования (PERL, PHP) технологию шаблонов дизайна. Будем называть их в дальнейшем именно так – шаблоны дизайна, чтобы избежать путаницы.

Итак, одной из основных идей шаблонов дизайна является максимально полное разнесение программного кода и его html-представления. Например, когда необходимо вывести приветствие пользователю, подготавливаем шаблон дизайна:

  <HTML>
  <BODY>
  <P>Добро пожаловать в систему {{FIRST_NAME}} {{LAST_NAME}}</P> 
  
  <P>Последний раз вы заходили к нам {{LAST_LOGIN_DATE}}</P>
  <P>Сегодня {{NOW_DATE}}</P>
  </BODY>
  </HTML>
  

и используем его в обработчике шаблонов. Сообщаем обработчику шаблонов файл, содержащий шаблон дизайна, значение переменных (FIRST_NAME, LAST_NAME, …) после чего можен получить от него обработанный шаблон. Обработка может выглядеть, к примеру, так:

  MyParserCalss _Parser = new MyParserCalss();
  _Parser.OpenTemplate(“c:\inetpub\wwwroot\template\templates\template.html”);
  _Parser.SetVariable ( “FIRST_NAME”, “xxxx”);
  _Parser.SetVariable ( “LAST_NAME”, “xxxx”);
  _Parser.SetVariable ( “LAST_LOGIN_DATE”, “2003-03-02”);
  _Parser.SetVariable ( “LAST_NAME”, Sysem.DateTime.Now.ToString());
  Response.Write( _Parser.ParseToString() );
  

В простейшем случае обработка шаблона представляет собой замену всех переменных в его тексте на их значения.

Что дает использование подобного промежуточного слоя помимо потери ресурсов сервера на дополнительную обработку?

Обычно основными преимуществами такого подхода называют следующие:

  • разделение программиста и дизайнера – они не мешают друг-другу, могут работать параллельно над одной страницей, при этом вероятность того, что они внесут нарушения в написанный друг-другом код сведена к минимуму.
  • Программист может не ждать разработки / утверждения дизайна и сразу приступать к работе – он набрасывает черновик дизайна нужной ему страницы (обычно – только переменные и некоторые разделители, чтобы переменные не сливались) и работает с ним. Позже, когда для страницы появится дизайн, верстальщик привяжет его к этой странице (причем программист может об этом даже не знать)
  • На одну и ту же страницу можно назначать разный дизайн в зависимости от некоторых параметром
  • Становится гораздо легче сопровождать систему, поддерживать ее, менять дизайн.

Все эти преимущества являются достаточно значимыми при работе с Perl, PHP или ASP. Действительно, одно разделение кода и представление страницы чего стоит – однажды попробовав применить шаблоны дизайна для этой цели, вы уже не сможете заставить себя вернуться к обычной мешанине кода и элементов дизайна («колбасе», как презрительно называют ее некоторые программисты).

С приходом ASP .NET ситуация переменилась – эта технология представляет свои пути решения проблемы разнесения дизайна и кода страницы. Для многих программистов, до этого успешно использовавших технологию шаблонов дизайна, стало очень непростым выбором, что делать дальше – продолжать ее использовать (и тем самым отказаться от многих интересных возможностей в ASP .NET, конфликтующих с шаблонами), или, наоборот, отказаться от шаблонов в пользу новшеств ASP .NET?

Тем не менее, есть области, где применение шаблонов дизайна оправданно и сейчас. Рассмотрим два таких примера таких областей.

Оправка почты

Ваш сайт отправляет письма при регистрации новых пользователей, восстановлении забытого пароля или другие? Без сомнения, ответ – «да».

Текст письма – это текстовка у которой некоторые элементы – переменные. Применение здесь шаблонов дизайна явно напрашивается.

Что это даст?

  • Тексты писем не будут вкомпилированны в dll сайта – т.е., если нам понадобиться исправить грамматическую ошибку или изменить текст письма, не придется перекомпилировать после этого сайт. Вы просто поправите тестовый файл.
  • Текст писем может изменять кто угодно, не только программист. Это может делать даже сам владелец сайта.
  • Вы можете иметь в своей библиотеке кода готовые обработчики шаблонов дизайна для часто встречающихся письм (например, восстановление пароля) и просто добавлять их в проект, изменения потребуется внести только в текст письма.

Такой подход оказывается в итоге, очень удобен, как в программировании, так и в использовании. Накладные затраты на затраты дополнительных ресурсов сервера пренебрежительно малы (особенно если вы используете оптимизированный обработчик шаблонов, грамотно написанный, кэширующий и т.п.)

Одно содержимое, несколько видов представления

Представьте ситуацию, когда у вас на странице сайта отображается некоторое содержимое (например, аналитический отчет). И это содержимое, помимо простого отображения на странице, нужно, во-первых, уметь представить в оптимизированном для печати виде, во-вторых, уметь экспортировать в Excel. Не знаю, как у вас, а в моей практике такие задачи встречаются постоянно.

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

Такая задача очень просто решается применением шаблонов дизайна – вы просто имеете три (4, 5, …) разных шаблона. И если потом вас просят добавить к этой странице еще и ссылку «отослать другу», это не будет вызывать у вас нервных реакций.

Напишем простой обработчик шаблонов для этой задачи

Простой обработчик шаблонов

Итак, напишем простой обработчик шаблонов дизайна, который будет просто заменять переменные в шаблоне на их значения и ничего больше.

У класса обработчика будет три метода:

  • OpenTemplate - открывает файл, содержащий шаблон дизайна
  • SetVariable – задает значение переменной
  • ParseToString – парсит весь шаблон в строку

Класс очень простой, поэтому просто приведем его код:

/// 
/// Класс, являющийся обработчиком шаблонов дизайна
/// 
public class Parser
{
  /// 
  /// Тэг-ограничитель переменной (окрывающий)
  /// 
  public const string TagOpen = "{{";

  /// 
  /// Тэг-ограничитель переменной (окрывающий)
  /// 
  public const string TagClose = "}}";

  /// 
  /// Путь к файлу, содержащему шаблон дизайна
  /// 
  private string TemplateFile = "";

  /// 
  /// Здесь мы будем хранить значения пронициализированных переменных
  /// 
  private Hashtable Variables;

  /// 
  /// Открываем файл, содержащий шаблон дизайна, попутно проверяя его существование
  /// 
  /// 
  public void OpenTemplate ( string TemplateFullPath )
  {
    if ( File.Exists( TemplateFullPath ) )
    {
      TemplateFile = TemplateFullPath;
    }
    else
    {
      TemplateFile = "";

      throw new Exception( String.Format("Parser.OpenTemplate: файл {0} не существует", TemplateFullPath) );
    }
  }

  /// 
  /// Установка значения переменной в шаблоне дизайна
  /// 
  /// Название переменной
  /// Значение переменной
  public void SetVariable ( string VariableName, object VariableValue )
  {
    Variables[ VariableName ] = VariableValue.ToString();
  }

  public string ParseToString ()
  {
    StreamReader _SR = new StreamReader( TemplateFile );

    StringBuilder _SB = new StringBuilder();
        
    //Пытаемся прочесть содержимое файла шаблона дизайна
    try
    {
      _SB.Append( _SR.ReadToEnd() );
    }
    catch
    {
      //может доступа нет, а может, диск с горячей заменой был...
      throw;
    }
    finally
    {
      _SR.Close();
    }

      
    // Заменим все переменные в шаблоне на их значения
    foreach ( string VariableName in Variables.Keys )
    {
      _SB.Replace( Template.Parser.TagOpen + VariableName + Template.Parser.TagClose, Variables[ VariableName ].ToString() );
    }

    return _SB.ToString();
  }

  /// 
  /// Конструктор, инициализирует необходимые переменные
  /// 
  public Parser()
  {
    Variables = new Hashtable();
  }
}

Теперь подготовим три шаблона - для отображения обычного содержимого, версии для печати и для экспорта в Excel. Первый шаблон тривиален:

  <HTML>
<HEAD>
  <TITLE></TITLE>
</HEAD>
<BODY>
  <TABLE ID="Table1" CELLSPACING="0" CELLPADDING="0" WIDTH="100%" BORDER="0">
    <TR>
      <TD WIDTH=203>Report #{{NUMBER}}</TD>
      <TD COLSPAN="2">
        <P align=right>Type #{{TYPE}}</P>
      </TD>
    </TR>
    <TR>
      <TD>Periode</TD>
      <TD>{{DAT_START}}</TD>
      <TD>{{DAT_END}}</TD>
    </TR>
    <TR><TD COLSPAN="3"><HR></TD></TR>
    <TR><TD COLSPAN="3">{{TEXT}}</TD></TR>
    <TR><TD COLSPAN="3"><HR></TD></TR>
    <TR>
      <TD COLSPAN="2"></TD>
      <TD>Verify {{MANAGER}}</TD>
    </TR>
  </TABLE>
</BODY>
</HTML>

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

Третий файл (версия для экспорта в Excel) представляет определенный интерес. Начиная с Office 2000, Microsoft ввела в Excel очень интересный формат – Excel XML. Он интересен тем, что это простой XML файл с определенной разметкой, следовательно, с нашей точки зрения это просто очередное представление дизайна. Вообще, чтобы подготовить шаблон для этого файла, нужно разобраться в структуре Excel XML, но, как истинно ленивые программисты пойдем более легким (и оптимальным путем) :). Откроем Excel и просто наберем в нем нужно вида текст. После этого выберем в меню File команду Save As и укажем при сохранении файла, что сохранять его нужно как Excel XML. Вот и все – шаблон готов.

Далее напишем страницу, которая будет открывать и обрабатывать эти шаблоны:

/// 
/// Страница, над которой мы будем ставить эксперименты
/// на вход принимаем номер шаблона (?Template=):
/// 1 - обычный
/// 2 - версия для печати
/// 3 - Excel версия (для открытия требует Excel 2000 или XP)
/// 
public class Default : System.Web.UI.Page
{
  /// 
  /// Не Page_Load - зачем нам эти лишнии инициализации, все равно не используем.
  /// Здесь вообще спорный вопрос, стоит ли от System.Web.UI.Page наследоваться
  /// 
  /// 
  override protected void OnInit(EventArgs e)
  {
    string UseTemplateNumber = "1";

    // Считываем номер файла темплейтов, который нам нужно открыть, на всякий случай проверив
    if ( Request.QueryString["Template"] != null)
    {
      UseTemplateNumber = Request.QueryString["Template"].ToString();
        
      if ( UseTemplateNumber != "1" && UseTemplateNumber != "2" && UseTemplateNumber != "3")
        UseTemplateNumber = "1";
    }

    Trace.Warn("Начали работать с темплейтами");

    // Открываем наш парсер и скармливаем ему файл, содержащий шаблон дизайна
    Parser _Parser = new Parser();

    _Parser.OpenTemplate( String.Format( "{0}Templates/default_{1}.htm",
                 AppDomain.CurrentDomain.BaseDirectory, UseTemplateNumber ) );


    // Задаем значения переменных
    _Parser.SetVariable("NUMBER", "2347687" );
    _Parser.SetVariable("TYPE", "234-234-DD-9" );
    _Parser.SetVariable("DAT_START", "2003/01/01" );
    _Parser.SetVariable("DAT_END", "2003/03/03" );
    _Parser.SetVariable("TEXT", "Что-нибудь умное, с графиками, диаграммами, без ошибок" );
    _Parser.SetVariable("MANAGER", "Такой Т.О." );


    // Если мы хотим, чтобы файл был открыт сразу Excel-ем, подкрректируем заголовоки
    if ( UseTemplateNumber == "3" )
    {
      Response.ContentType = "application/vnd.ms-excel";
      Response.AddHeader( "Content-Disposition", "attachment; filename=Template_3.xls" );
    }

    // И выводим в ответ на запрос
    Response.Write( _Parser.ParseToString() );

    Trace.Warn("Закончили работать с темплейтами");
  }
}
  

Посмотрим, насколько эффективно это работает – включим трасерт и засечем время работы написанного обработчика – 0.0004 сек – хороший результат. Конечно, при использовании объемных файлов шаблонов, заполнении их информаций из БД, использовании более сложных обработчиков шаблонов время парсинга возрастет, но, как показывает опыт работы с реальными проектами, эти накладные расходы на обработку файлов шаблонов пренебрежительно малы.

Выводы

Технология шаблонов дизайна совсем не излишняя в ASP .NET, ее можно и нужно применять. Причем наиболее эффективно ее применение не вместо механизмов, предлагаемых ASP .NET, а совместно с ними, дополняя их и облегчая решение рутинных задач.


Текст примеров данной статьи можно выкачать здесь


Может пригодится:


Автор: Сергей Тимонов
Прочитано: 3284
Рейтинг:
Оценить: 1 2 3 4 5

Комментарии: (0)

Добавить комментарий
Ваше имя*:
Ваш email:
URL Вашего сайта:
Ваш комментарий*:
Код безопастности*:

Рассылка новостей
Рейтинги
© 2007, Программирование Исходники.Ру