четверг, 23 апреля 2009 г.

Web-сервисы с сохранением состояния на ASP

При создании web-сервисов сложного поведения, бывает, требуется необходимость в сохранении его состояния от одного запроса к другому. Добиться этого можно двумя способами:
  • Использованием файлов/БД с передачей уникального ключа в каждом запросе;
  • Использованием сессий.
Второй вариант фактически есть упрощение первого, поэтому целесообразно рассматривать его и сразу. Решается этот вопрос аргументом EnableSession атрибута WebMethod:
[WebMethod( EnableSession = true )]
public int Echo( int _Val ) { ... }
При этом мы намекаем, что при вызове web-метода Echo имеет смысл предоставить сервером контексту севриса сессию, уникальную для клиента в определенный промежуток времени. Данный промежуток времени можно указать в web.config атрибутом timeout элемента sessionState. Чтобы сервер был в курсе, какую сессию предоставлять контексту сервиса - новую или одну из существующих - необходимо определить свойство CookieContainer данного web-сервиса:
mService.CookieContainer = new CookieContainer( );
От рассмотренного второго варианта решения вопроса можно перейти к первому. ASP позволяет хранить сессии в БД. Определить эту возможность можно при помощи упомянутого ранее элемента sessionState:
<sessionstate mode="SQLServer" sqlconnectionstring="..." sqlcommandtimeout="..."></sessionstate>
При этом ёмкая сессия будет размещаться в БД, а не в памяти процесса.

среда, 22 апреля 2009 г.

Генерация таблиц в DOM'е

Данная запись посвящена динамическому созданию таблиц на html-странице. С одной стороны решение тривиальное:

var tr = document.createElement("tr");
for (var i = 0; i < 3; ++i) {
var td = document.createElement("td");
td.innerHTML = i;
tr.appendChild(td);
}

var table = document.createElement("table");
table.appendChild(tr);

var obj = document.getElementById("container");
obj.appendChild(table);

Скрипт создает строку таблицы, забивает ее ячейками с информационно-значимым контентом. Далее полученная строка добавляется к таблице - и всё ok? Во всех развитых браузерах, разумеется, этого достаточно.
Но есть один особенный бразуер, занимающий лидирующие на данный момент позиции на рынке, из-за чего качественному web-разработчику его нельзя игнорировать - ie. Создаваемая указанным скриптом таблица в ie7 выглядит следующим образом.
При этом по DOM-у все в порядке - строка и ячейки созданы и располагаются в таблице.
Оказывается, ie ещё помнит старый-добрый тег tbody. И при парсинге всем таблицам его добавляет. Так, вполне грамотная с виду таблица, записанная в виде html

<table>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
</tr>
</table>

...в DOM-е ie7 будет выглядеть следующим образом:
Посему и при динамическом создании таблиц непосредственно в DOM браузера ie7 следует делать такие поправки:

var tbody = document.createElement("tbody");
tbody.appendChild(tr);
var table = document.createElement("table");
table.appendChild(tbody);

Не будет откровением, что все грамотные браузеры без проблем распознают и указанную выше модификацию.

среда, 25 марта 2009 г.

Комментарий на видеопослание президента РФ о достигнутых результатах

Исходное послание президента.

Коррупция свойственна любому государству, в котором значимость имеют материальные ценности. В "развитых" странах т.н. первого мира она минимально заметна. В нашей стране она присутсвует на всех этапах жизненного цикла гражданина. Самой мерзкой коррупцией является чиновничий произвол, когда ресурсы нашей страны расходуются чиновниками для обеспечения собственного благосостояния, а власть, даруемая российским народом, используется против него самого, обеспечивая безопасность этих "воров в государстве".
Предполагаю, что создание дополнительных контрольных органов в государственном аппарате приведет исключительно к росту коррупци. Т.к. чиновники будут отсчитываться исключительно перед такими же чиновниками и, соответственно, возрастет величина получаемых взяток.
Более качественным инструментом контроля, считаю, является инструмент, основанный на общедоступном и открытом источнике информации - сети интернет. Чиновники, работающие на народ, должны публиковать результаты своей работы в унифицированной форме, в свободном доступе для народа. Тогда любой гражданин сможет объективно оценить эффективность работы каждого конкретного звена государственного аппарата управления. Гражданам будет предоставлена возможность увидеть, сколько чиновник получил средств из государственного бюджета, как и на что он их потратил. Имея данную информацию, инициативные граждане и специалисты своей области, смогут легко проверить, а действительно ли деньги потрачены грамотно. Действительно ли, например, качество и объем положенного во дврое дома асфальта соответсвует объему денег, потраченных на него чиновником. Либо почему муниципалитет потратил на детскую площадку в несколько раз больше средств, чем заявлена ее стоимость в прайс-листах компаний-конкурентов поставщика.
И эта информация должна быть в свободном от бюрократических заборов доступе. Ведь не за бюрократические заборы мы позволяем распоряжаться ресурсами страны.

P.S. Данный комментарий был опубликован на сайте президента 25 марта 2009 года

пятница, 20 марта 2009 г.

Определение асинхронного запроса при использовании asp .net ajax

Встречаются ситуации, в которых необходимо разделить поведение управляющего элемента, расположенного на UpdatePanel в зависимости от того, асинхронный запрос приходит на обновление, или нет.
При использовании asp .net ajax ScriptManager клиентской части определяет переменную __ASYNCPOST при обращении к странице значением "true". Таким образом, разделить поведение пользовательского элемента в зависимости от типа запроса можно следующим образом:
public partial class UIControls_MyControl : System.Web.UI.UserControl
{
bool IsAsyncRequest
{
get
{
return ( Page.Request.Params.Get( "__ASYNCPOST" ) != null )
}
}

protected void Page_Load(object sender, EventArgs e)
{
if ( IsAsynRequest )
{
//что-то делаем
}
else
{
//делаем что-то
}
}

}
Примером использования данного решения может быть ситуация, в которой накладно выполнять всю функциональность пользовательского элемента на каждый асинхронный запрос. Что как раз и позволяет автоматизировать UpdatePanel из asp .net ajax.

пятница, 13 марта 2009 г.

Дружим canvas и asp .net ajax под ie7

Известно, что ie7 - особенный браузер со взглядами далекими от общепринятых стандартов. Одним из таких стандартов, незаметных для ie7, является html5. В частности, его элемент canvas.
Одним из решений для поддержки страниц, использвующих тег canvas, в брузере ie7 является библиотека excanvas от Google. Библиотека реализует требуемый стандартом объект CanvasRenderingContext2D использованием Microsoft VML с одной стороны, с другой стороны предоставляя клиентским приложениям интерфейс, описанный стандартом html5.
Указанное решение позволяет вполне комфортно вести разработку страниц с тегом canvas до тех пор, пока не начинают возникать вопросы построения изображений, зависимых от результатов выполнения серверных сценариев, в режиме реального времени.
Если разработка ведется по технологиям, близким LAMP - проблем нет никаких. Рисование осуществляется средствами javascript. Поэтому заменить исходные данные асинхронным http-запросом с последующей перерисовкой - дело не сложное. Подробнее с примером это описано в статье "Canvas, Ajax, and the Supertrain".
Совсем другое дело, если разработка ведется в рамках ASP с использвоанием asp .net ajax. В данной ситуации очень не хочется воротить собственную реализацию ajax, которая при асинхронных запросах обновляла бы только исходные данные для графического отображения. Вполне нормально в рамках ASP желать обновления пользовательского элемента управления прозрачно, использованием UpdatePanel.
На перепутье canvas, asp, ajax и ie7 возникают следующие сложности:
  • После асинхронной перезагрузки элемента canvas на странице, excanvas его не воспринимает;
  • При использовании RegisterStartupScript объекта ClientScriptManager для построения javascript-кода инициализации элемента в обработчике Page_PreRender, код не выполняется по завершении асинхронного запроса.
Решить первую помогает изучение исходного кода библиотеки excanvas. В библиотеке при завершении загрузки страницы (по значению complete свойства document.readyState) осуществляется связывание элементов DOM страницы, подходящих под описание элемента canvas, с VML-реализацией функционала тега canvas из стандарта html5. Занимается этим метод init_ некоторого менеджера - G_vmlCanvasManager. Ниже представлен псевдокод библиотеки:
if (!window.CanvasRenderingContext2D) {
(function () {
Описание vmlCanvasManager
...
G_vmlCanvasManager.init()
...
Описание интерфейса canvas
...
Определение CanvasRenderingContext2D
})();
}

Метод init связывает вызов метода init_ с обработчиком onreadystatechange. Тут и кроется подвох. Ведь document.readyState всегда complete после загрузки страницы, несмотря на асинхронные запросы - onreadystatechange не происходит. Поэтому определить контекст нового элемента документа, приходящего с результатом выполнения асинхронного запроса, необходимо вызовом метода init_ по завершении передачи данных от сервера. Тут мы сталкиваемся со второй проблемой.
А вторая проблема решается путем использования метода RegisterStartupScript класса ScriptManager. Пример представлен ниже:
protected void Page_PreRender ( object sender, EventArgs e )
{
StringBuilder sbStartScript = new StringBuilder( );
sbStartScript.Append( "window.alert('ку-ку');" );
sbStartScript.Append( "G_vmlCanvasManager.init_();" );
ScriptManager.RegisterStartupScript( this, Page.GetType( ), ID + "StartupScript", sbStartScript.ToString( ), true );
}

Более подробное решение второй проблемы описано в заметке "Inline Script inside an ASP.NET AJAX UpdatePanel".