• Microsoft .NET
  • ASP.NET
  • Внутреннее устройство ASP.NET: архитектура запроса

Блокировка экрана во время постбэка (postback)

В идеальном мире все приложения должны быть быстрыми и находчивыми, и не должно существовать такого понятия, как длительный постбэк. Но в реальном мире существует множество случаев, когда требуется несколько секунд для завершения постбэка. К примеру, когда пользователь посещает сайт резервации билетов и вводит информацию о месте отбытия и прибытия, то вывод результатов как обычно может занять несколько секунд. Аналогично данному примеру, существуют приложения, которые динамически генерируют и высылают по почте большие PDF-файлы при нажатии кнопки, или которым необходимо осуществить запрос по очень медленно работающей базе данных, расположенной в офисах в другой части света. В таких случаях пользователю зачастую приходится  выжидать некоторое время с момента отсылки данных и до получения ответа с веб-сервера.

В то время, как обозреватели предоставляют какую-либо ответную реакцию пользователю о том, что форма была выслана и ответ ожидается, данные визуальные подсказки расположены на границах обозревателя и позволяют пользователю взаимодействовать со страницей, повторно нажать кнопку либо взаимодействовать с другим элементом управления пользовательского интерфейса страницы. Многие сайты посылают пользователю сообщение, наподобие "Пожалуйста, подождите пока мы обработаем результаты..." при отсылке запроса. Это предоставляет две вещи: визуальную реакцию пользователю о том, что их данные были приняты, и предотвращает повторную отсылку поискового запроса во время обработки первого.

Вы можете повторить данную функциональность в одной странице при помощи небольшого блока JavaScript и CSS , который блокирует экран по реализации определенного действия с клиентской стороны (зачастую это отсылка данных), при этом отображая сообщение и запрещая пользователю взаимодействовать с веб-страницей. Данная статья демонстрирует способ внедрения данной функциональности в веб-страницу ASP.NET. Читайте далее, чтобы узнать больше об этом!

Блокировка экрана при помощи каскадных таблиц стилей (CSS)

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

Значение z-index может быть использовано для блокировки экрана и предотвращения возникновения взаимодействия пользователя с другими элементами на веб-странице. Это подразумевает создание HTML-элемента, который настолько велик, что он покрывает экран и имеет самое большое значение z-index среди всех элементов страницы. Такой элемент покроет все остальные элементы на странице, следовательно запретит пользователю нажатие по ссылкам, кнопкам или другим элементам управления пользовательским интерфейсом под "покрытием".

Представьте себе следующий приме: данная страница содержит некоторый текст, элемент TextBox, кнопку и элемент <div>. Элемент <div> абсолютно позиционирован в верхнем левом углу - его ширина и высота равны 200 пикселям. Его значение z-index больше значений любого другого элемента на странице. Следовательно, элемент <div> покроет содержимое, находящееся под ним.

<html> 
<body>
   <h2>Overlay Test Page</h2>
   <p>
      Please enter your name:
      <input type="text" name="name" />
   </p>
   <p>
      <input type="submit" value="Click Me!" />
   </p>
   <div style="background-color: #ccc; position: absolute; top: 0px; left: 0px; width: 200px; height: 200px; z-index: 999;">
      This content overlays the elements beneath it!
   </div>
</body>
</html> 

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

Мы можем заблокировать экран полностью создав элемент <div> , который будет настолько широк, что покроет весь экран (а не квадрат со стороной в 200 пикселей). Но вместо элемента <div>, отображаемого все время (как это видно в указанном выше примере), нам необходимо всего лишь заблокировать экран в момент, когда пользователь выполнит какие-либо действия с клиентской стороны, например, такие как отсылка формы. В дополнение, также было бы неплохо отображать некоторое сообщение, к примеру "Ваш запрос обрабатывается..." в то время, когда экран заблокирован.

Блокировка экрана в ответ на действия с клиентской стороны

Элемент <div> , который блокирует экран в HTML-примере, упомянутом выше, отображается постоянно. Что нам необходимо сделать, так это заставить данный элемент отображаться только тогда, когда пользователь нажимает кнопку "Click Me!". (Идея заключается в том, что когда пользователь нажимает кнопку, форма будет отправлена и обозреватель обновится как только сервер возвратит ответ. Пока мы ожидаем ответа, необходимо заблокировать экран, поэтому, отображая элемент <div> при нажатии кнопки экран будет заблокирован до того момента, как будет возвращен ответ с веб-сервера, после чего обозреватель отобразит новую страницу.)

Данная функциональность возможна при помощи небольшого блока JavaScript и CSS кода. Вместо того, чтобы жестко программировать настройки стиля в атрибуте style элемента <div> , давайте попробуем использовать классы CSS. Следующий пример включает в себя два CSS класса:

  • LockOff - исходный класс CSS установок для элемента <div>. Данный CSS класс указывает на то, что элемент <div> должен быть скрыт.
  • LockOn - CSS класс, который блокирует экран. Обратите внимание на то, что данный CSS-класс использует абсолютное позиционирование, большое значение z-index и растягивает элемент <div> по всему экрану. Более того, он использует атрибут opacity для того, чтобы разрешить пользователю "видеть сквозь" элемента <div> и обозревать содержимое под ним .

Класс CSS переключается при помощи функции JavaScript skm_LockScreen, которая также устанавливает атрибут innerHTML элемента <div> в передаваемую строку str. Функция skm_LockScreen вызывается при помощи кнопки "Click Me!" и отображает сообщение "Мы обрабатываем ваш запрос ..."

<html> 
<head>
   <style type="text/css">
      .LockOff {
         display: none;
         visibility: hidden;
      }

      .LockOn {
         display: block;
         visibility: visible;
         position: absolute;
         z-index: 999;
         top: 0px;
         left: 0px;
         width: 105%;
         height: 105%;
         background-color: #ccc;
         text-align: center;
         padding-top: 20%;
         filter: alpha(opacity=75);
         opacity: 0.75;
      }
   </style>

   <script type="text/javascript">
      function skm_LockScreen(str)
      {
         var lock = document.getElementById('skm_LockPane');
         if (lock)
            lock.className = 'LockOn';

         lock.innerHTML = str;
      }
   </script>
</head>
<body>
   <h2>Overlay Test Page</h2>
   <p>
      Please enter your name:
      <input type="text" name="name" />
   </p>
   <p>
      <input type="submit" value="Click Me!" onclick="skm_LockScreen('Мы обрабатываем ваш запрос...');" />
   </p>

   <div id="skm_LockPane" class="LockOff"></div>
</body>
</html>

Упаковка функциональности блокирования экрана в специализированный класс базовой страницы (ASP.NET Base Page Class)

Блокировка экрана требует добавления HTML-элементов к странице (элемент "lock" <div> ), функции JavaScript skm_LockScreen и кода JavaScript для вызова данной функции при определенных действиях с клиентской стороны (таких как, нажатие кнопки). Мы можем упростить процесс добавления данной функциональности к ASP.NET-странице путем внедрения JavaScript и элемента <div> из кода серверной стороны. Более того, расположив данную функциональность в специализированном базовом классе страниц мы можем расширить данное поведение и использовать его на всех страницах вашего ASP.NET приложения.

Код, доступный в конце статьи, включает в себя специализированный класс базовой страницы (BasePage), который содержит три метода:

  • AddLockScreenScript() - данная функция добавляет необходимый код JavaScript и элемент <div> на страницу для того, чтобы заблокировать экран. Данный метод отмечен как Private и поэтому не может быть вызван с ваших страниц - вместо этого, он используется следующими двумя методами для того, чтобы обеспечить наличие механизмов блокировки экрана в нужном месте.
  • LockScreenAfterClick(WebControl, message) - добавляет скрипт клиентской стороны в переданный элемент управления (WebControl) , поэтому когда WebControl будет нажат, экран будет заблокирован, отображая сообщение (message). Представьте что вы хотели заблокировать экран и отобразить сообщение "Ваш запрос обрабатывается ..." при нажатии элемента управления Button btnSubmit . Это можно выполнить добавление следующего кода в обработчик события Page_Load:
    rotected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
       MyBase.LockScreenAfterClick(btnSubmit, "Ваш запрос обрабатывается...")
    End Sub

    Обратите внимание: для того, чтобы иметь возможность использовать блок кода, указанного выше, класс с фоновым кодом ASP.NET-страницы должен расширять специализированную базовую страницу. Также обратите внимание на то, что данный метод должен быть вызван при каждом посещении страницы (первичный вызов и все последующие постбэки).

  • LockScreenAfterDDLChange(DropDownList, message) - похож на LockScreenAfterClick, но данный метод блокирует экран после того, как переданный элемент управления DropDownList был изменен на клиентской стороне. Это пригодится вам в случае, если у вас есть элемент DropDownList , чье свойство AutoPostBack установлено в True, при этом выполняемый постбэк длителен.
Приложение в конце данной статьи включает в себя пример ASP.NET-страницы, который демонстрирует способ использования методов классов специализированной базовой страницы. Данный пример включает в себя элемент управления Button, при нажатии которого блокируется экран, а также DropDownList , который блокирует экран будучи измененным. Также есть элемент Button, который не блокирует экран, поэтому вы сможете сравнить нормальное поведение с блокировкой экрана. При выполнении постбэка, ASP.NET-страницы "спит" 5 секунд для симуляции.

Следующий рисунок демонстрирует пользовательский интерфейс с заблокированным окном после того, как был нажат элемент Button. Обратите внимание на то, что экран заблокирован и отображено сообщение "Processing Request...". Как уже было упомянуто ранее в предыдущих примерах, в то время как экран является заблокированным, пользователь не может взаимодействовать с элементами пользовательского интерфейса, находящимися под "покрытием".


Данный пример был протестирован и работает как положено в обозревателях Safari 3.2 (для PC), Firefox 3.0, Internet Explorer 7.0 и Google Chrome 1.0.

Блокировка экрана при выполнении частичного постбэка
Техника блокировки, обсуждаемая в данной статье, фокусируется на блокировке экрана в ответ на полный постбэк. Тем не менее, данная техника может быть также использована в приложениях, поддерживающих Ajax.

Вывод

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

Данная статья демонстрирует способ блокировки экрана используя некоторый код JavaScript и CSS. При помощи данного подхода вы можете использовать скрипт для того, чтобы элемент <div> был отображен в ответ на действия с клиентской стороны. Данный элемент <div> простирается на весь экран и покрывает все другие элементы на странице, тем самым запрещая пользователю повторно высылать форму. Это также служит хорошей подсказкой пользователю о том, что его действие было принято и что скоро будет получен результат.

Веселого программирования!

Scott Mitchell

Скачать исходные коды примера