Пишу скорее для себя и г-на Зимина, ибо других программистов здесь нет.
Ситуация: есть форма создания нового объекта, например пользователя. Нажимаем на кнопку submit, отправляется запрос серверу, создается новый пользователь, форма закрывается. Нажимаем быстро два раза на кнопку submit — отправляется запрос серверу, но форма еще не закрылась и при повторном нажатии отправился еще один запрос. Как итог, были созданы два одинаковых пользователя. Нажимаем очень быстро 10 раз на кнопку submit, получаем 10 одинаковых пользователей в базе.
Вообщем-то, ларчик просто открывается — наша форма находится внутри контрола UpdatePanel, который свою очередь управляется ScriptManager'ом. Контроллировать ход асинхронной передачи можно с помощью класса Sys.Webforms.PageRequestManager — он позволяет использовать набор определенных событий, на которые можно "повесить" пользовательские функции, определяющие нужное поведение запросов. Более подробно можно прочитать здесь.
Конкретно в нашем случае мы делаем следующее:
1) Определяем js-функцию:
function CheckStatus(sender, args)
{
var prm = Sys.WebForms.PageRequestManager.getInstance();
if (prm.get_isInAsyncPostBack() & args.get_postBackElement().id == 'InsertBtn') {
args.set_cancel(true);
}
}
Данная функция проверяет, выполняется ли уже асинхронная передача и кто её инициировал. В нашем случае, если запрос на создание пользователя уже был отправлен (т.е. событие было вызвано нажатием кнопки с идентификатором "InsertBtn"), то мы не должны допустить отрпавку повторного запроса!
2) Для события initializeRequest класса Sys.Webforms.PageRequestManager определяем обработчик — функцию CheckStatus.Также мы определяем обработчик события load Sys.Application:
Sys.Application.add_load(ApplicationLoadHandler)
function ApplicationLoadHandler(sender, args)
{
Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(CheckStatus);
}
3) Финальный аккорд- сохраняем это все в отдельном файле и указываем его в качестве скрипта для нашего ScriptManager'а:
<asp:ScriptManager ID="smp" runat="server">
<Scripts>
<asp:ScriptReference Path="~/_common/js/postback.js" />
</Scripts>
</asp:ScriptManager>
Метки: ajax, cancel postback, scriptmanager, updatepanel, vb.net
А на клиентской части я бы рекомендовал кнопке отправки формы ставить свойство disabled.
Деактивировать кнопку на клиентской части сразу после нажатия — это первое, что приходит в голову. Однако проблема в том, что поиск элемента по DOM-дереву требует существенных (в данном случае) временных затрат. Проще говоря — пользователь успеет повторно нажать на кнопку прежде, чем она будет сделана disabled.
Это что за дерево такое у тебя? Может назначить id кнопке, по нему быстро поиск в дереве должен пройти. Так быстро, что пользователь не успеет два раза кликнуть)
Ребята, а на начало поста вы не обиделись? Про 2-х программистов, один из которых работает не у нас :).
vigor,
[b]Может назначить id кнопке, по нему быстро поиск в дереве должен пройти.[/b]
cм. мой ответ Иреку.
Еще раз — я не стал бы изобретать велосипед, если бы можно было просто деактивировать кнопку по id с помощью javascript.
mkp,
[cite]Однако проблема в том, что поиск элемента по DOM-дереву требует существенных (в данном случае) временных затрат. Проще говоря — пользователь успеет повторно нажать на кнопку прежде, чем она будет сделана disabled.[/cite]
Дело даже не в том, что поиск по DOM-дереву очень ресурсоемкий, а в том, что перед тем как произойдет сабмит, вызывается клиентское событие onclick у кнопки, в котором вы хотите установить в true атрибут disabled. Если вы это сделаете, то никакого сабмита не произайдет (даже самого первого), так как клиентский скрипт выполняется перед сабмитом, а у задисеблинной кнопки сабмит вызвать не получится. Так что здесь два варианта: первый – тот, который предложил Константин, второй — заменять кнопку на заранее задесейбленную кнопку, которая была невидимой до нажатия на первую.
Константин, вещь достаточно известная. Есть такой замечательный проект "муви", там подобное реализовано. Направление твоей мыслиmkp,
[cite]Деактивировать кнопку на клиентской части сразу после нажатия — это первое, что приходит в голову. Однако проблема в том, что поиск элемента по DOM-дереву требует существенных (в данном случае) временных затрат. Проще говоря — пользователь успеет повторно нажать на кнопку прежде, чем она будет сделана disabled.[/cite] верно. Так что респект "ТехМувиБогу" Воробьеву Коле!
Сейчас пришла идея — а что, если деактивацию кнопки сделать через некоторое время после нажатия, чтобы успел произойти сабмит? Т.е. на onclick кнопки повесить что-то типа:
[i]"window.setTimeout(‘$(‘#buttonID’).disabled=true’,1000); document.forms[0].submit()"[/i] ?