Лично меня давно интересовал вопрос — почему разработчики ASP.NET MVC уделяют так много времени на реализицию второстепенных (ИМХО) фич (типа View/Editor Templates и тп), а не решают более острые проблемы? Самые острые проблемы, на мой взгляд — это пережитки WebForms. Возьмите, например, кеширование, которое работает совсем-совсем плохо, потому что предназначено для классического ASP.NET, а не для MVC. Ну и апофеоз архаизма — это, конечно же, WebFormViewEngine.

И вот, 2-го июля 2010 года стало известно — команда ASP.NET MVC наконец-то взялась за разработку нового движка отображения (ViewEngine) — Razor. Чтобы понять истинное значение этой новости нужно, для начала, изучить недостатки и проблемы WebFormViewEngine.

Недостатки и проблемы WebFormViewEngine

1 Несоответствие парадигм

Класс WebFormViewEngine в пространстве имен System.Web.Mvc — это, по сути, попытка адаптировать инфраструктуру WebForms для работы в концепции MVC. (Кто-то метко заметил, это тоже самое что "адаптировать каток для колки арехов"). Но известно, что WebForms и MVC используют совершенно разные парадигмы. MVC — это запросо-ориентированный фреймворк, а WebForms — компонентно-ориентированный. Отсюда и возникают проблемы:

  1. Разный жизненный цикл страниц.
  2. Для MVC не требуется множество доступных директив.
  3. Code Behind — зло для MVC.

2 Антиавтономность

От движка отображения требуется одно — генерация текста по шаблону. Естественно, эта задача актуальна не только для веб-приложений и не только для рендеринга видов. Такие генераторы (их еще называют templating engine, один из ярких представителей — velocity) применяются для генерации отчетов, электронных писем и во многих других случаях. Однако, WebFormViewEngine — это больше чем templating engine. Это целая экосистема, поэтому её не получится использовать вне ASP.NET приложения.

3 Нетестируемость

Не секрет, что про существование TDD в Microsoft узнали недавно, а ASP.NET появился давно. Также не секрет, фреймворк WebForms под завязку набит синглтонами и привязан к веб-контексту. Эти тонкие обстоятельства вызывают сложности тестирования любого рода производных от WebForms (вспомним обертки HttpContextBase и т.п. в MVC). Ну а уж если кому-то захочется заняться такой экзотической вещью как тестирование output\а WebFormViewEngine`, то из этого вряд ли получится что-нибудь хорошее.

4 Ущербная модель повторного использования разметки

Дублироване кода в шаблонах вида — такая же проблема как дублирование логики в контроллерах или любом другом месте программы. И с этим дублированием нужно бороться. WebFormViewEngine предлагает нам для этого классическую модель Master Page и эмвецешный RenderPartial. Этих механизмов явно недостаточно, для некоторых задач приходится придумывать совсем не прямые решения. Достаточно беглого взгляда на модель, которую предлагает, например, Spark, чтобы понять, что она более продвинутая. С partial-разметкой у Spark дела тоже лучше.

5 Многословный синтаксис

В WebFroms хорошим тоном было помещать логику отображения (а иногда и логику предметной области, что греха таить) в code-behind-файл (вспомним гигантские методы Page_Load). Скриптлеты (<% много_кода %>) были хоть и существенным, но всё-таки дополнением к этому механизму. В MVC же наоборот, скриптлеты — единственно верный способ описания логики шаблона вида. Так второстепенный механизм вышел на первостепенные роли — кода во вьюшках MVC бывает очень много. И некоторым стало казаться, что два-три символа (<%, <%=) — это слишком много.

Еще острее стоит проблема форматирования — масса HTML- и C#-кода в одном файле превращается в кровавое месиво, если нажать Ctrl+K+D.

Сторонние решения

Сообществу давно известны проблемы WebFormViewEngine. Поэтому сторонних движков очень много. Но основной их недостаток — нет глубокой интеграции с Visual Studio. Это проявляется в отсутствии автодополнения, а иногда и подсветки синтаксиса. ReSharper тоже не очень любит сторонние движки. Да и выбор типового .NET разработчика обычно основан на такой логике (пруфлинк, абзац 3-4):

Продукт от Microsof будет жить и поддерживаться также долго, как и сам .NET Framework. А сторонние решения могут завтра перестать существовать.

Razor → луч света в тёмном царстве

И вот появляется новость о скором релизе Razor — движке, который впитал в себя всё лучшее от Spark и NHaml. От описания прелестей хочется какать кирпичами — настолько всё хорошо. (Кому нужны кирпичи — срочно прочитайте на хабре перевод Скота Гатри: Razor — новый движок представлений в ASP.NET). Итак, нам обещают:

  1. движок, который легко можно использовать вне ASP.NET-проекта;
  2. открытый исходный код;
  3. модель Master Layout в духе Spark;
  4. легкая тестируемость;
  5. улучшена модель хелперов;
  6. «облегчённый» синтаксис.

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

Отдельно хочется сказать про хелперы. Сама концепция методов-расширений для генерации элементов разметки хорошо прижилась в MVC. Но выявились и проблемы. В хелпере сложно генерировать большой кусок разметки, потому что оперировать строками html тегов в C#-коде неудобно. Во всяком случае не так удобно, как в предназначенных специально для html файлах aspx/ascx. С другой стороны, механизм Partial View не позволяет передать в дочерний вид множество параметров также легко как в метод расширения. Поэтому приходится искать баланс между двумя этими подходами (RenderPartial vs Extension method helper). Razor производит революцию в этом направлении — теперь хелперы можно будет определять не в cs-файлах, а в файлах шаблоннов. То есть мы получаем удобство, безопасность передачи параметров в хелпер и легкость написания разметки. В дополнение к этому появляется возможность передачи мини-шаблона в качестве параметра хелпер-метода. Это тоже должно быть интересно.

В связи со всем сказанным, если Razor действительно так хорош, то после его релиза вообще не вижу смысла дальнейшего использования WebFormViewEngine. Пусть MVC идёт своей дорогой, Web Forms — своей. Учитывая отношение большинства сообщества к сторонним решениям можно предположить, что вместе с WebFormViewEngine уйдут в прошлое и источники вдохновения Razor — Spark и NHaml.

Progg it

Restuta

"В WebFroms хорошим тоном было помещать логику отображения в code-behinde-файл"

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

admax

Я имел в виду не логику предметной области, и именно логику отображения. То есть генерацию списков/таблиц, заполнение лейблов и т.п. Это всё обычно располагается в code-behind (PageLoad и т.п.) и это нормально. Другое дело, когда в том же PageLoad появляется сервисная логика, которая по всем законам должна быть инкапсулирована в отдельном классе. И здесь я с вами абсолютно согласен — это провоцирует новичков писать г-но-код.