Пользователь
0,0
рейтинг
5 июля 2010 в 10:31

Разработка → Razor — новый движок представлений в ASP.NET перевод

.NET*

Одним из проектов, над которым работала моя команда, был новый движок представления для ASP.NET.

ASP.NET MVC всегда поддерживал концепцию “движка представлений”, собственно он представляет из себя заменяемые модули, которые реализуют выбор различного синтаксиса шаблона. Сегодня, стандартный движок представлений для ASP.NET MVC использует аналогичные файлы, что и ASP.NET Web Forms — .aspx/.ascx/.master. Существуют и другие популярные ASP.NET MVC движки представлений — Spark и NHaml.

Новый движок представлений, над которым мы работаем, оптимизирован под генерацию HTML-кода, фокусируясь на коде шаблона. Кодовое имя для данного движка – “Razor”, первая бета-версия будет доступна уже скоро.

Цели разработки


Во время того, как мы разрабатывали прототип и оценивали Razor, мы выделили несколько основных целей:
  • Компактный, Выразительный и Гибкий: Razor уменьшает “нагрузку на клавиатуру”, требуемую для работы в файле, предоставляет быстрый и гибкий процесс программирования. В отличии от большинства синтаксиса шаблонов, вам не нужно прерывать написание кода, чтобы явно определить серверные блоки кода в HTML. Парсер достаточно умен, для того чтобы сделать это за вас, основываясь на коде. Вы получаете компактный и выразительный синтаксис, который легко и весело набирать.
  • Легко освоить: Razor прост в освоении и позволяет вам за короткий срок стать более продуктивным с минимальным количеством усилий. Вы используете все существующие навыки языка программирования и HTML.
  • Не новый язык: Мы сознательно выбрали путь, который не основывается на новом императивном языке для Razor. Вместо этого, мы позволили разработчикам использовать уже существующие навыки работы с C#/VB(или другим языком) и предоставили синтаксис разметки шаблона, который дает вам потрясающий процесс построения HTML, оставляя выбор языка за вами.
  • Работает в любом текстовом редакторе: Razor не требует определенного инструмента и позволяет вам быть продуктивным в любом старом текстовом редакторе (даже в блокноте прекрасно работает)
  • Поддержка Intellisense: Не смотря на то, что Razor разрабатывался с учетом отсутствия привязки к определенному инструменту или редактору кода, у него будет отличная поддержка в Visual Studio. Visual Studio 2010 и Visual Web Developer 2010 скоро получат обновления для intellisense.
  • Юнит-тестирование: Новая реализация движка будет поддерживать возможность производить юнит-тесты над представлениями (не требуя контроллера или веб-сервера, можно размещать в любом проекте юнит-тестирования –отсутствует  нужда в специальных доменах приложений)
Мы потратили последние несколько месяцев разрабатывая приложения, используя данную технологию, провели юзабилити исследования с различными добровольцами, включая группы не .NET разработчиков. Отзывы от людей были превосходными.

Выбор и Гибкость


Самой прекрасной возможностью у ASP.NET, является замена буквально любой части кода. Если определенный механизм не удовлетворяет вашим потребностям, вы можете легко заменить его на свою реализацию.

Со следующей версией у ASP.NET MVC появится новое диалоговое окно “Add->View”, которое позволит вам выбрать синтаксис для нового файла шаблона представления. Оно позволит вам легко выбирать любой доступный движок представления, установленный на локальной машине:

AddView9

Razor будет присутствовать в списке, так как он будет интегрирован непосредственно в ASP.NET MVC. Все вспомогательные методы и модели будут доступны, как в Razor, так и в .ASPX движках представлений.

У вас будет возможность сочетать и сравнивать шаблоны представлений, написанные с использованием различных движков в рамках одного приложения или сайта. Например, вы можете создать одни представления, используя .aspx, другие с .cshtml или .vbhtml (расширения Razor файлов, для C# и VB соответственно), третьи со Spark или NHaml. Мало того, у вас может быть шаблон представления на одном движке, используя частичное представление, написанное на другом движке. Вы капитан и выбираете то, что вам нужно.

Hello World и Razor


Razor позволяет вам начать со статического HTML (или любого текстового содержимого), далее делая его динамическим, добавляя серверный код. Одна из основных целей проектирования Razor’a, была предоставить гибкий процесс кодирования и позволить быстро интегрировать серверный код в HTML-разметку с минимумом усилий.

Чтобы увидеть простой пример, давайте создадим “hello world” пример и выведем следующее сообщение:

image

Как это выглядит при использовании .ASPX кода


Если мы собираемся построить, представленный выше “hello world” пример, используя ASP.NET и существующую разметку синтаксиса .ASPX, нам потребуется использовать <%= %> блоки, для определения областей кода внутри HTML-разметки:

image

Хотелось бы поделится одним наблюдением для данного примера – каждая область кода, требует 5 символов (<%= %>) для начала и конца последовательности кода. Некоторые из данных символов (в особенности клавиша %, которая на большинстве клавиатур располагается в верхней центральной части) не совсем просто набирать.

Как это выглядит с Razor синтаксисом


Обратите внимание на начало области кода в Razor, где используется символ @. В отличии от <% %>, Razor не требует от вас явно закрывать область кода:

image

Парсер Razor умеет семантически анализировать C#/VB в  областях кода, вот почему нам не нужно явно закрывать блок кода выше. Razor может определить выше указанные утверждения, как самостоятельные области кода и неявно закрыть их для нас.

Даже в таком тривиальном “hello world” примере мы уберегли себя от 12 лишний нажатий клавиш, которые нам пришлось бы делать раньше. Набрать символ @ на клавиатуре гораздо проще, чем символ %.

Циклы и вложенный HTML


Давайте рассмотрим другой случай, когда вам нужно вывести список продуктов (и цену напротив каждого):

image

Создаем пример с .ASPX


Если мы собираемся реализовать пример, используя ASP.NET и существующую разметку синтаксиса .ASPX, нам потребуется код, который будет динамически генерировать <ul> список с элементами <li> для каждого продукта:

image

Создаем пример с Razor


Ниже я покажу, как сгенерировать эквивалентное представление, используя Razor:

image

Обратите внимание, как мы начали цикл foreach, используя символ @, а далее разместили строку HTML содержимого с блоками кода внутри. Так как парсер Raptor понимает семантику C# в наших блоках, он может определить, что содержимое <li> должно быть внутри foreach и рассматривает его, как содержимое, которое должно быть зациклено. Он также распознает закрывающую } и останавливает foreach.

Razor так же достаточно умен, чтобы распознать @p.Name и @p.Price выражения внутри элемента <li>, как серверный код и выполнить его для каждого прохода цикла. Обратите внимание, Razor автоматически закрывает области кода @p.Name и @p.Price основываясь на совместном использовании HTML и кода.

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

Блоки if и многострочные выражения


Ниже представлено несколько примеров распространенных ситуаций:

If выражения


Как и в foreach примере, вы можете располагать содержимое внутри if выражений (или других языковых структур C# или VB), при этом явно не указывая начало/конец областей кода. Например:

image

Многострочные выражения


Вы можете обозначать несколько строчек кода обернув их в блок @{ код } следующим образом:

image

Обратите внимание, что переменные могут быть разбиты на несколько серверных блоков кода, переменная “message” объявлена в многострочном блоке @{ }, а также использована в блоке кода message. Точно так же, как и в синтаксисе .aspx файлах <% %> и <%= %>.

Комплексные выражения


Синтаксис @( ) позволяет размещать комплексные выражения. Например, мы можем переписать выше указанный код для конкатенации строки и числа вместе, внутри блока @ ( код ):

image

Интеграция содержимого и кода



Парсер Razor знает множество особенностей языка, позволяя полностью доверится ему, а не проводить время за собственной реализацией.

Конфликтует ли он с email-адресами и другими местами использования @ в HTML?


Парсер Razor достаточно умен, чтобы в большинстве случаев определить, используется ли символ @ в коде или в статическом содержимом. Например, ниже я используя символ @, как часть email-адреса:

image

Во время парсинга файла, Razor анализирует содержимое справа от символа @ и пытается определить, является ли эта часть C# кодом (если это CSHTML файл)  или VB (если это VBHTML файл), или же это статические данные. Приведенный выше код, выведет следующий HTML (где email-адрес выведется, как статическое содержимое, а @DateTime.Now определится, как код):

image

В случае, где содержимое валидно, как код, а вы хотите вывести его как статическое, достаточно явно указать два символа @@ вместо одного.

Определение вложенного содержимого


Размещая HTML-содержимое внутри if/else, foreach или других блочных выражений, следует обернуть внутреннее содержимое HTML или XML элементов для лучшего определения начала области содержимого.

Например, ниже, я обернул многострочный блок содержимого (который включает в себя фигурные скобки) в тег <span>:

image

Это сгенерирует следующий код для клиента, включая элемент <span>:

image

По желанию, вы можете обернуть вложенное содержимое в блок <text> в случаях, когда ваши данные должны сгенерироваться для клиента без тега обвертки:

image

Данный код сгенерирует ниже представленное содержимое для клиента, обратите внимание – никаких обворачивающих тегов:

image

Кодирование HTML


По умолчанию содержимое, использующее блок @ автоматически HTML-кодированно для улучшенной защиты против XSS атак.

Макет/MasterPage — Основы


Очень важно иметь единообразный вид на всех страницах вашего веб-сайта или приложения. ASP.NET 2.0 представил концепцию “мастер страниц”, которые могут помочь добиться данного результата, когда используем .aspx страницы или шаблоны. Razor так же поддерживает данную концепцию, используя “layout pages”(страницы макета), которые позволяют вам определять шаблон сайта, а далее наследовать от него представления/страницы.

Простейший пример макета


Ниже представлен простой пример страницы макета, которое мы сохраним под названием “SiteLayout.cshtml”. Он может содержать любой статический HTML, а также любой динамический серверный код. Далее добавим вызов вспомогательного метода “RenderBody()” в том месте, где мы хотим вывести определённое тело содержимого для запрашиваемого URL:

image

Далее мы можем создать шаблон представления, назвав его “Home.cshtml”, которое содержит только нужный код или содержимое для построения определенного тела запрашиваемой страницы и основывается на шаблоне макета:

image

Заметьте, как вы явно задали свойство “LayoutPage” в коде нашего Home.cshtml файла. Это означает, что мы хотим использовать шаблон SiteLayout.cshtml, как макет для данного представления. Мы можем так же задать файл макета непосредственно в контроллере ASP.NET MVC, указывая Home.cshtml, как шаблон представления или же настроив его стандартным макетом для сайта (в данном случае мы определяем его в одном файле проекта и все шаблоны представлений подхватывают его автоматически)

Когда мы сгенерируем Home.cshtml, как шаблон представления, он объединит содержимое макета и под-страницы, и отошлет содержимое клиенту:

image

Компактный, чистый и выразительный код


Хотелось бы обратить внимание на код выше и заметить, что определение макета и его использование из представлений/страниц имеет маленький размер. Код на скриншоте содержит все содержимое SiteLayout.cshtml и Home.cshtml файлов, нет никаких дополнительных настроек или тегов, нет префикса %@Page % и другой различной разметки или заданных свойств.

Мы стараемся держать код, который вы пишете, в наиболее компактном и простом виде. Мы также хотим позволить любому открывать файлы в сторонних текстовых редактора и изменять код. Не требуется никакой дополнительной генерации кода или intellisense.

Макет/MasterPage – Добавляем заменяемые части


Макет страниц поддерживает возможность определять внутри различные “секции”, которые могут изменять представления собственным содержимым. Это позволяет вам с легкостью изменять/заполнять прерывающиеся секции содержимого на странице макета и предоставляет гибкость макета для вашего сайта.

Например, мы можем вернуться к нашему SiteLayout.cshtml и определить две секции внутри макета, которые могут изменять представления. Назовем эти части “menu” и “footer” и укажем, что заполнять из необязательно, передав параметр optional=true помощнику RenderSection() (делаем мы это, используя новые необязательные параметры в C#, о которых я уже рассказывал)

image

Так как две секции помечены, как “optional”, я не обязан определять их в моем Home.cshtml файле. Мой сайт продолжает прекрасно работать, даже если их там нет.

Давайте вернемся обратно в Home.cshtml и объявим собственные части Menu и Footer. Скриншот ниже, содержит весь код Home.cshtml, больше ничего не потребуется. Однако, я перенес настройки LayoutPage на глобальный уровень, так что их здесь больше нет.

image

Наши собственные секции перезаписывают “menu” и “footer” с помощью объявленных в файле блоков @section. Мы решили не требовать обвертывать содержимое “main/body” внутри секции, а вместо этого просто оставить её в строковом виде (это позволяет сократить количество нажатий и позволит с легкостью добавлять секции на страница макета, не требуя пробегаться по всем страницам изменяя их синтаксис)

Когда мы снова сгенерируем Home.cshtml как шаблон представления, он объединит содержание макета и под-страницы, интегрируя две новых части страницы и вернет клиенту следующее:

image

Инкапсуляция и повторное использование HTML-помощников


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

Программные HTML-помощники


Сегодня у ASP.NET MVC в наличии есть вспомогательные методы, которые можно вызвать в блоках кода и которые инкапсулируют генерацию HTML. И реализованы они только в виде кода (чаще всего, как методы расширений). Все существующие методы расширения HTML, созданные с ASP.NET MVC, будут так же работать при использовании “Razor”:

image

Декларативные HTML-помощники


Генерация HTML на основе одного класса кода работает, но не является идеальной.

Одной из возможностей в Razor является простой путь для создания повторно используемых HTML-помощников, используя более декларативный подход. Наш план заключается в том, чтобы дать вам возможность объявлять повторно используемые помощники с помощью декларативного синтаксиса helper { }, как показано ниже.

image

Вы сможете размещать .cshtml файлы, которые содержат данные помощники в директории Views\Helpers и в последствии заново использовать их в любом представлении или странице на вашем сайте (никаких дополнительных действий не потребуется):

image

Обратите внимание, как помощник ProductListing() определяет аргументы и параметры. Вы можете передавать любые параметры, какие захотите (включая необязательные параметры, типы допускающие значения NULL, генерики и т.п.). Вы так же сможете отлаживать данный код в Visual Studio.

Важно: helper синтаксис не будет доступен в первой бета-версии Razor, мы надеемся он будет доступен в следующих версиях. Вспомогательные методы оформленные в виде кода, будут работать сразу.

Передача строковых шаблонов, как параметров


Другая полезная (и нереально мощная) возможность, которую мы предоставляем с Razor – это возможность передавать “строковые шаблонные” параметры во вспомогательные методы. Данные “строковые шаблоны” могут содержать в себе, как HTML, так и код, и могут быть вызваны по требованию вспомогательного метода.

Ниже вы видите пример данной функциональности в действии, я использую HTML-помощник “Grid”, который генерирует DataGrid для клиента:

image

Вызов метода Grid.Render – это C#. Мы используем новые именуемые параметры в C# для передачи строго типизированных аргументов в метод Grid.Render, данная возможность дает нам полное завершение выражений с instellisense и проверку во время компиляции.

Параметр “format”, который мы передаем, когда объявляем столбец, является “строчным шаблоном”, он содержит и html и код, мы также можем настроить под себя формат данных.  А самое прекрасное – это что помощник Grid’a может вызывать наш строчный шаблон, как метод делегата, и может вызывать его, когда нужно и сколько раз хочет. В данном случае он будет вызывать каждый раз, когда он генерирует строку грида и передает в “элемент”, который может использовать наш шаблон для отображения результата.

Данная возможность позволит разрабатывать более мощные HTML-вспомогательные методы. Вы сможете реализовывать их, как в коде (так вы это делаете сегодня), так и используя декларативный подход helper{ }.

Поддержка в Visual Studio


Как я уже замечал ранее, одной из основных целей Razor – минимизировать количество нажатий клавиш, а также легко редактировать код любым текстовым редактором. Мы постарались держать синтаксис чистым, компактным и простым.

Не смотря на это, мы спроектировали Razor таким образом, чтобы вы смогли получить все удобства редактирования кода в Visual Studio. Мы предоставим полную поддержку HTML, JavaScript и C#/VB кода в intellisense в Razor-файлах:

image

Обратите внимание, каким образом отработал intellisense для объекта Product на “ @p.”, внутри элемента <li>. Заметьте, в Solution Explorer в папке \Views присутствуют оба шаблона представлений .aspx и .cshtml. Вы можете использовать различные движки представлений в одном приложении, давая возможность прочувствовать, какой синтаксис вам по душе.

Выводы


Мы думаем “Razor” предоставляет новый изящный движок представлений для ориентированных на код шаблонов. Процесс программирования станет быстрым и веселым. Синтаксис является компактным и уменьшает количество нажатий клавиш, в то же время улучшая читабельность вашей разметки и кода. В следующей версии ASP.NET MVC движок будет встроен в систему. Вы сможете удалить файлы .cshtml/.vbhtml в своем приложении и запустить их, как отдельные страницы, что также позволяет вам использовать их в ASP.NET Web Forms приложениях.

Все разработчики, которые тестировали проект последние несколько месяцев, оставили крайне позитивные отзывы. Мы собираемся предоставить публичную бета-версию, как можно скорее и конечно же ожидаем услышать ваше мнение.
Перевод: Scott Gu
Евгений @jeje
карма
96,7
рейтинг 0,0
Пользователь
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (37)

  • –13
    Только мне одной кажется, или Microsoft опять изобрела телефон, тьфу, PHP?
    • +8
      Конечно, давайте посмотрим на велосипед от PHP
      <?php echo «lalal»; ?>

      <? foreach($m as $k):
      echo $k;
      endforeach;
      ?>
      а если еще начать использовать фигурные скобки с разрывом кода для html, то тут труба полнейшая

      Если уже сравнивать, то лучше с Ruby.
      • –2
        <?=$lalala?>
        <?php foreach($m as $k):?>
        <?=$k?>
        <?php endforeach?>
        • +4
          Это вы называете изящно? Я уже давно работаю с php и прекрасно знаю все отрицательные стороны синтаксиса. <?= не спасает, на сложных конструкциях начинаются пляски. Далее, я(как и многие другие проекты, включая Magento) всегда придерживаюсь Zend Coding Standards. Где четко указано
          PHP code must always be delimited by the full-form, standard PHP tags:
    • 0
      Нет не одной :)
  • 0
    Неплохо… А как с производительностью?
    • +8
      Я процитирую Скотта
      «Razor is fully compiled — so the performance should be great.»
  • –2
    «Процесс программирования станет быстрым и веселым» :-)
    microsoft велик )
  • 0
    Простые языковые конструкции — это понятно. А как насчет поддержки более сложных, например, лямбда-выражений?
    • +3
      Вы получите поддержку всех возможностей языка, включая лямба-выражения.
  • 0
    Ну вот, это уже намного изящнее стандартного движка. Жаль что нет еще самой беты, получился конь впереди повозки. )
    • +1
      ScottGu всегда так делает. Оно кстати и не плохо. Они фидбек еще до бета релиза собирают.
  • 0
    Интересно, чем тогда им упомянутый Haml не понравился. По их критерию, там ещё почти вдвое меньше нажатий клавиатуры, так как закрывающих тегов нет.
    • +1
      наверное, NHaml им бы не удалось расширить так, как они захотят. например добавить декларативные хелперы всякие и прочие плюшки. А тут свое — крути-верти как хочешь.
      • +4
        Плюс, Скотт пообещал постараться предоставить исходный код всего движка, это будет превосходно
  • –1
    О, потехоньку осваиваю asp.net, и буквально первое что мя в стандартном view-engine'е смутило- это не понятки как писать код, а-ля ProductListing.
    В результате обычный C#'овский метод-хелпер сделал, но извините — в ручную склеивать строки разметки и серверного кода — это маразм…
    • +1
      Делаете PartialView моделью которого является список продуктов. Далее вызываете Html.RenderPartial.
      • –1
        Попробую. Сенкс.
  • 0
    Я полагаю, оно работает по примерно такому же принципу, что и XHP от Facebook:

    www.facebook.com/notes/facebook-engineering/xhp-a-new-way-to-write-php/294003943919
    • +1
      Грубая аналогия, даже для того, чтобы вывести переменную они использую лишние фигурные скобки
      echo <span>Hello, {$_POST['name']}</span>

      • 0
        Ну, тут тоже как бы с собачки нужно начинать те части, где вставляется значение переменной :). Я, на самом деле, скорее имел ввиду реализацию — что оно просто реализует поддержку XML. Но, посмотрев на примеры, беру свои слова обратно — здесь, похоже, они действительно сделали настоящий парсер C# после собачки :)
  • –1
    Очень интересно… когда всё это можно ожидать, чтобы «пощупать»?

    Сразу маленький вопросик про конфликты с «собакой»
    допустим надо сделать такое:

    Адрес для контактов: info@Model.ActiveDomainForEmail


    как такое отработает? т.е. Model.ActiveDomainForEmail — допустим содержит "@mydomain.ru" и надо чтобы в результирующем html было info@mydomain.ru
    не подумает ли парсер, что info@Model.ActiveDomainForEmail это валидный email?
    • 0
      Предположительно, пощупаем мы в ближайшее 2 недели.
      Нет парсер все правильно найдет, у вас же есть свойства в модели. Парсер не смотрит внутрь значений, он смотрит является ли, то что вы написали справа от @ C#-кодом
      • 0
        Хорошо, допустим написано такое:

        Адрес для контактов: info@somefield.ru

        при этом somefield — это доступная переменная, ссылка на объект, а в нем строковое поле ru, содержащее строку "@mydomain.ru"
        понятно что пример синтетический, просто хочется понять, не будет ли вдруг такая «умная» краткая запись причиной путаницы
        • 0
          Нет, потому что парсер не проверяет валидность доменных имен, он ищет c# код. Я не могу ручаться на 100%, но иначе быть не может, там парни не дураки писали :)
          • 0
            а тогда одна опечатка и info@Model.ActiveDomainForEmail так и впечатается в форму
            и не понятно как с ошибками компиляции, ведь пишет что не надо закрывать выражение потому что парсер поймет где оно кончилось… значит опять же буквой ошибся и досвидание
            • 0
              Я думаю info@Model.* будет выкидывать ошибку при и пользовании ошибочного свойства.
    • –1
      парсер понимает большинство ситуаций, но когда вы не доверяете ему, то можете экранировать @ с помощью двойного написания @@, в статье про это кстати написано
      • +2
        Я про обратную ситуацию. Экранировать — это понятно, когда я хочу получить собаку в результирующий html, а я пишу про то, что мне кажется не будет понято парсером как C# код, хотя это он и есть
  • +2
    Есть ощущение, что этот синтаксис эквивалентен aspx с точностью до подстановочных знаков: т.е. автоматизированным способом razor-синтаксис конвертится в классическую aspx-разметку, а дальше по накатанной.

    Имхо минус «скобка-процент» не заслуживает того, чтобы ему присвоили отдельное название. Но может, я что-то не понимаю?
  • –1
    Да, неплохая штука, молодцы ребята. Спасибо за перевод.

    Скорее всего буду использовать ее в своем проекте. Как раз заканчиваю писать модель и юнит-тесты, а к веб-части пока не приступал.

    Кстати, кто-нибудь знает известные known issues? Ограничения и т.д.?
  • 0
    Неплохо, код шаблонов и правда почище в целом будет.
  • +3
    Spark от Microsoft.
    • +1
      Ну, так оно и есть, в принципе.
  • –3
    Я так понимаю товарищи взяли и реализовали то что уже давно было в PHP, Java и прочих ориентированных на веб языках — MVC то появился недавно в .NET а тут банальный JSTL выдают за чудо технологию
  • 0
    при использовании @Html.BeginForm() в разметку выдается лишний текст «System.Web.Mvc.Html.MvcForm»

    никто не сталкивался?
  • 0
    @using (Html.BeginForm(«метод», «контроллер»))
    {
    здесь форма
    }

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.