В прошлом году я писал про конференцию Patterns & Practices Roadshow. Так как о ней у меня остались исключительно хорошие впечатления, то в этом году я её тоже посетил. Теперь она уже называлась Patterns & Practices Симпозиум и проходила в офисе компании Microsoft Ukraine.

Как и большинство конференций, эта началась с регистрации, где мы получили бэйджики с именем пакет с блокнотом, программой  конференции и печатной версией свежей книги от команды Patterns& Practices.

Открывал конференцию Андрей Терихов, директор Департамента Стратегических технологий в Microsoft Ukraine. Андрей коротко рассказал о том, чем занимается компания Microsoft в Украине и какие ещё события будут в этом году. Всех заинтересовал анонс мероприятия для разработчиков, которое будет проходить в декабре целых два дня.

Первый доклад симпозиума имел не очень скромное название “Microsoft patterns & practices - главный доклад”. Докладчик - Eugenio Pace, руководитель группы patterns & practices . Что касается меня, то я так и не понял почему он был “главным”. Доклад о том, чем занимается команда Patterns & Practices, что и когда они выпускают слушать 2-й раз было не очень интересно (в прошлом году был похожий доклад). IMHO, можно было бы его сделать в два раза короче. Возможно, впечатление ещё подпортило то, что это был первый доклад, после проведённой ночи в поезде Харьков-Киев.

Следующим был доклад про Windows Azure Platform - облачную платформу от Microsoft. Докладчиком снова  был Eugenio Pace. Eugenio начал рассказ с того, какие “облака” бывают вообще и какие сервисы нам предоставляет Microsoft. Были отдельно рассмотрены все составляющие части платформы Windows Azure - SQL Azure, AppFabric, Storage, “Dallas” services. После доклады было много интересных вопросов и были получены не менее интересные ответы.

После обеда начался доклад Григория Мельника (Grigori Melnik, ведущий руководитель группы patterns & practices) - Microsoft Enterprise Library 5.0. Можно сказать, что это был главный доклад всей конференции. Григорий рассказал много интересной информации о EntLib5.0: что это такое, что нового, как перейти с более ранних версий. Отдельно хочу сказать про Enterprise Library Configuration Tool. В 5-й версии эта утилита была полностью переписана. Интерфейс хоть и сыроват, но намного удобнее предыдущего да и написан на WPF.

Предпоследний доклад на этом симпозиуме был про Prism: Prism - пособий по созданию приложений на WPF и Silverlight. Докладчик: Chris Keyser, руководитель группы patterns & practices. Prism - каркас приложения на WPF или Silverlight с применением необходимых паттернов проектирования, даёт вам возможность писать приложения не думаю о том, что получите в итого: настольное приложение на WPF или RIA-приложение на Silverlight. Если вы разрабатываете на упомянутых выше технологиях, то обязательно стоит познакомится с Microsoft Prism.

Последний по счёту на конференции доклад  был от Chris Keyser - SharePoint Development Guidance. Доклад быр расчитан на тех разработчиков, которые уже сталкивались с разработкой под SharePoint. Chris рассказывал нам о best practices, а так же о том, как не нужно делать при разработке под Chris SharePoint


1. Введение
2. Обзор framework'а
3. Жизненный цикл страницы
4. Полезные объекты и функции

1. Введение

В предыдущем посте из этой серии (ASP.NET Ajax. Часть 1: что внутри?) я рассказал что такое AJAX и как Microsoft помогает нам его использовать. Сегодня я более подробно расскажу о его клиентской части. Частично из-за того, что эту информацию не так просто найти в MSDN, как хотелось бы, частично  из-за того, что в последнее время Microsoft уделяет этой части всё меньше внимания, агитируя использовать jQuery, многие разработчики даже на догадываются какой мощных инструмент находится у них в руках.

2. Обзор framework'а

По умолчанию, эти скрипты грузятся на страницу, на которой есть ScriptManager по ссылке вида ScriptResource.axd?d=scriptIdentificator. Сами же скрипты находятся в ресурсах сборки System.Web.Extensions (если у кого-то всё-ещё установлена VS2005, то эти скрипты можно найти в папке c:\Program Files\Microsoft ASP.NET\ASP.NET 2.0 AJAX Extensions\v1.0.61025\MicrosoftAjaxLibrary\System.Web.Extensions\). Также можно загружать эти скрипты с помощью CDN. Подробнее об этом способе можно почитать тут.
Сам скирт немного отличается для WebForms и ASP.NET MVC, но ядро у них общее.
Все функции/объекты разделены на пространства имён (namespaces) по аналогии с серверной частью. Перечислять я их не буду, так как на MSDN (http://msdn.microsoft.com/en-us/library/bb397536.aspx, http://msdn.microsoft.com/en-us/library/dd410060.aspx) всё хорошо описано.

3. Жизненный цикл страницы

Кроме стандартных для DOM модели событий, ASP.NET Ajax предоставляет нам  доступ как к событиям всего приложения (init, load, unload и др.), так и события, связанные с запросами на сервер (beginRequest, endRequest и др.). Как всегда, за полной информацией лучше обратиться в первоисточник, а именно - http://msdn.microsoft.com/en-us/library/bb386417.aspx.

4.Полезные объекты и функции

MS Ajax Library предоставляет нам как новые типы/функции, так и расширения для стандартных - Array, Number, Date, String и др., о которых можно почитать в MSDN Magazine (http://msdn.microsoft.com/en-us/magazine/cc163300.aspx).
Одними из наиболее частоиспользуемых являются функции $get() и $find():
- $get()  - оптимизированный по производительности аналог document.getElementById, который ищет элемент по его ID и в качестве второго параметра может принимать parent-элемент, в котором нам необходимо найти нужный элемент DOM-модели.
- $find() - функция, которая очень похожа на $get(), но возвращает не DOM-элемент, а экзепмляр Ajax Client Control.
Более детальное описания использования этих функций: http://mattberseth.com/blog/2007/08/the_everuseful_get_and_find_as.html


HTML Decode/Encode.

Если кто-то слышал об такой атаке на веб-сайты, как XSS Injection, то он(она) знает что для предотвращение такой атаки необходимо использовать функции HtmlEncode/HtmlDecode. XSS Injection (Cross-site injection) - один из способов атак веб-приложений, главной идеей которого является вставка(инъекция) чужого javascript-кода на атакуемый веб-сайт. Как минимум, это может привести к краже печенек cookies и получении прав администратора сайта. ...

1.1. ASP.NET

Это происходит, примерно, так:
Допустим, у нас есть форма для отправки комментарием, где пользователь вводит свой еmail и текст коммеентария. Самый простой обработчик кнопки добавить окмментарий будет выглядить так:

protected void OnAddCommentClick(object sender, EventArgs e)
{
 var pageId = this.GetPageId();
 var email = this.txtEmail.Text;
 var comment = this.txtComment.Text;
 CommentsService.AddComment(pageId, email, comment);
}

С первой точки зрения этот код не содержит никаких ошибок, компилируется и корректно сохраняет данные в БД. Но, если в тексте  комментария будет любой HTML или JavaScript-код, то при отображении этого комментария на страницу без предварительной обработки мы увидем, что HTML и JavaScript-код без особых проблем обрабатываются браузером.
Таким образом, мы сделали наш сайт уязвимым и нарушили одно из базовых правил проектирования ПО: “Не доверять данным, которые пришли извне нашей системы”. От себя еще добавлю: вдвойне недоверять данным, которые были введенны пользователем. Чтобы исправить это ошибку, необходимо всего-лишь вызвать метод HttpServerUtility.HtmlEncode(), перед сохранением данных в базу:


 var email = Server.HtmlEncode(this.txtEmail.Text);
 var comment = Server.HtmlEncode(this.txtComment.Text);

После чего, строка вида “<script>alert(‘hello!’);</script>” будет сохранена в базу в таком виде:

 &lt;script&gt;alert(‘hello!’);&lt;/script&gt;

Теперь все хорошо: любой введенный пользователем текст не ламает нашу верстку и не вызывает выполнения стороннего javascript (пример 2).
Но все не так просто, как кажется. Теперь, если такой код вставить в обработчике OnAddPage(), где администратор сайта будет добавлять страницы, то вместо красивого текста пользователи увидят набор непонятных символов. Поэтому, при отображении содержимого страницы мы вызываем метод HttpServerUtility.HtmlDecode(), который переведет сохраненный в базе данных текст в такой вид, чтобы браузер его корректно обрабатывал.

Таким образом, мы избавили наш сайт от XSS Injection дали возможность пользователям воодить разнообразные данные без вреда для сайта.

Примечание. Во всех примерах выше свойство странице EnableRequestValidation было установлено в false для возможноти ввода символов “<“ и “>”.
Примечание для ASP.NET 4.0/ASP.NET MVC 2.0. В ASP.NET 4.0/ASP.NET MVC 2.0 появилась конструкция <%: ... %>, которая делает за нас HTML Decode/Encode.

1.2. JavaScript

Если нам необходимо реализовать данную функциональность на клиенте с помощью javascript, то нам на помощь приходит jQuery:

function htmlEncode(html) {
 return $('<div/>').text(html).html();
}
function htmlDecode(text) {
 return $('<div/>').html(text).text();
}

1.3 Python/Django

В фреймворке Django HTML Decode работает по умолчанию, и для его отключение в шаблоне (template) добавить блок {% autoescape off %} и в нем поместить все элементы, для которых нам не нужен HTML Decode, после чего закрыть блок с помощью {% endautoescape %}.

2. URL Decode/Encode.

В отличии от HTML Encode/Decode незаэкранированный url больших проблем не вызывает, за исключением двух моментов: url становится не таким простым и понятным для пользователя и это не очень хорошо влияет на SEO.

2.1 ASP.NET

Рассмотрим такую ситуацию: у нас есть сайт с функцией поиска по нем. Стандартная форма поиска содержит поле для вводи и кнопу "Поиск". В простейшем случае при нажатии на кнопку “Поиск” у нас есть такой обработчик:


protected void OnSerachClick(object sender, EventArgs e)
{
 var searchText = this.txtSearch.Text;
 car url = String.Format(“{0}?q={1}”, VirtualPathUtility.ToAbsoluteUrl(“~/Search.aspx”), searchText);
 Response.Redirect(url);
}

Вполне рабочий код, за исключением того, что в некоторых случаях в итоге мы получаем не очень красивый url вида:

/Search.aspx?q=some%20keywords

Конечно, такой url правильно обрабатывается браузером, но не всем пользователям будет понятно что он значит. Происходит это из-за того, что браузер автоматически заменяет символ пробела и ряд других символов на  их шестнадцатиричное значение вида %XX, где XX - код символа в шестнадцатиричной системе.
Сделано это было давно, кода браузеры были маленкими еще не умели отображать нелатинские символы в строке ввода адреса и для правильного отображения разнообразных символов.
И тут нам на помощь приходят методы HttpServerUtility.UrlEncode() и HttpServerUtility.UrlDecode() которые предназначены для переобразования параметров строки запроса в понятный для пользователей вид. Отдельно отчему, что эти методы предназначены для обработки исключительно параметров url, а для переобразования адреса к необходимому ресурсу существует метод HttpServerUtility.UrlPathEncode(), работа которого больше похожа на работу метода HttpServerUtility.HtmlEncode(), но учитывает все особенности построения url. Этот метод не имеет метода для обратного переобразования, но при правильном подходе к проектированию приложенич это не понадобится.

2.2. JavaScript

Аналог URL Encode в javascript - функция encodeURI()