Подлипенский Павел

Блог о технологиях и деньгах

Динамическое добавление ASP.NET пользовательского контрола с использованием JQuery

clock сентября 9, 2008 09:58 by author Подлипенский Павел

Недавно у меня возникла необходимость динамически подгружать пользовательские контролы на страницу. Это довольно просто реализовывается с помощью UpdatePanel. Но мне этот вариант не подошел, так как страница должна весить как можно меньше и работать как можно быстрее. Поэтому выбор пал именно на связку ASP.NET и JQuery + Web Service. Для начала давайте разберемся каким образом можно вызвать Web Method с помощью JQuery.

function getJsonAjaxObject(webServiceURL, jsonData) {
 $.ajax({
  type: "POST",
  contentType: "application/json; charset=utf-8",
  url: serviceURL,
  data: jsonData,
  success:
   function(msg){
   //код обработки успешного вызова веб-метода
   },
  error:
   function(XMLHttpRequest, textStatus, errorThrown){
    //код обработки ошибки выполнения веб-метода
   }
 });
}

Из всего множества методов (load, get, post, getJSON, ajax) я выбрал именно ajax т.к. этот метод позволяет наиболее полно контролировать процесс создания асинхронного запроса к веб-сервису.

Имя Тип Описание параметра
type string возможные варианты – GET или POST. Если параметр упущен, то по умолчанию будет использоваться метод GET. Типы запроса PUT или DELETE тоже могут быть использованы, но они поддерживаются не всеми браузерами.
contentType string при передаче данных серверу сообщает content-type. По умолчанию - application/x-www-form-urlencoded.
url string адрес веб-сервиса. Например, http://mysite.com/myservice.asmx/mywebmethod
data object данные, передаваемые на сервер. Добавляются в URL GET-запроса. Если используется объект, он должен представлять собой пары ключ/значение. Если значения представлены в виде массива, jQuery сериализует значения с некоторым ключом. Например: {foo:["bar1", "bar2"]} будет представлено как "&foo=bar1&foo=bar2".
success function указывается функция, которая будет вызвана в случае успешного завершения запроса. Функция принимает два аргумента: данные, возвращенные с сервера и отформатированные с учетом параметра dataType и строка, описывающая статус ответа(в нашем примере это строка всегда будет “success”).
error function определяет функцию, которая будет вызвана в случае неуспешного выполнения запроса.
dataType string строка, описывает тип данных, которые ожидаются в качестве ответа сервера. Если не определена, то jQuery сам попытается определить тип, основываясь на MIME-типе ответа сервера. Доступные типы: - xml: вернет XML документ, который может быть обработан через jQuery. - html: вернет HTML как plain text. - script: расценивает ответ как JavaScript и возвращает его как plain text. - json: расценивает ответ как данные в формате JSON и возвращает JavaScript объект. - jsonp: загружает данные в формате JSON используя JSONP. Необходимо дополнительно добавить "?callback=?" в конец строки запроса в URL, чтобы определить вызов. (Добавлено в jQuery 1.2). - text: строка plain text.
async boolean
по умолчанию все запросы выполняются в асинхронном режиме (значение true). Если необходимо выполнить синхронный запрос, следует установить значение false для этой опции. Помните, что синхронный запрос может временно заблокировать браузер, запретив любые действия во время выполнения запроса.
beforeSend function
может содержать функцию, которая должна быть вызвана до передачи запроса. beforeSend - это Ajax Event (события рассмотрены в другой статье).
cache boolean
опция добавлена в jQuery 1.2. По умолчанию - true. Если установить в false, запрашиваемая страница не будет кэшироваться браузером.
complete function
определяет функцию, которая будет вызвана по окончанию запроса (успешного и ошибочного выполнения). Принимает два аргумента: объект XMLHttpRequest и строку, описывающую "успешность" запроса. complete - это Ajax Event (события рассмотрены в другой статье).
global boolean
true или false. Вызывать или нет глобальные обработчики событий Ajax для этого запроса. Может быть использована для контроля различных Ajax событий. По умолчанию - true.
ifModified boolean
запрос будет успешным только в случае, если данные ответа изменились со времени последнего запроса. По умолчанию - false.
processData boolean
по умолчанию true. В опции data данные представлены в виде объекта, который преобразуется в строку запроса, подходящую для content-type по умолчанию - "application/x-www-form-urlencoded". Если необходимо иное, установите опцию processData в false.
timeout number
устанавливает локальный тайм-аут для запроса в миллисекундах. Отменяет глобальный тайм-аут для этого запроса, если тот определен через $.ajaxSetup


Необходимо также учесть, что ASP.NET Ajax enabled веб-сервис разрешает только HTTP POST (по умолчанию) для вызова метода, который возвращает JSON.

В большинстве случаев IIS 6 и выше требует наличия content-length элемента в запросе POST, даже если данных в запросе нет. Content-length для запроса без данных должен быть равен 0, но JQuery, в таком случае, этот элемент не добавляет. Поэтому для readonly запросов POST необходимо указывать пустой JSON объект:

data: “{}”

Это натолкнет JQuery на мысль указать корректный content-length и ваш веб-сервис сможет правильно распознать readonly-запрос, отбросив при этом пустой параметр.

Хочу еще обратить ваше внимание на то, что contentType установлен в "application/json;charset=utf-8". Этого требует ASP.NET AJAX. JSON-запросы, не имеющие подобного заголовка будут проигнорированы ASP.NET.

Еще одна проблема, с которой мне пришлось столкнуться, это “Maximum length exceed” ошибка. Она возникает в случае, когда длина JSON-ответа превышает длину по умолчанию. Во избежание этой ошибки необходимо добавить в web.config следующее:

<system.web.extensions>
  <scripting>
     <webServices>
    <jsonSerialization maxJsonLength="5000000" />
     </webServices>
  </scripting>
</system.web.extensions>

Вот так выглядит код моей страницы

<%@ Page Language="C#" EnableViewState="false"  %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="head" runat="server">
    <title>Add ASP.NET User Control dynamically with JQuery</title>
    <script language="javascript" type="text/javascript"   src="Scripts/jquery-1.2.6.pack.js"></script>
    <style type="text/css">
        body
        {
            width:95%;
            padding-left:20px;
            font-family:Arial;
            font-size:10pt;
            padding-right:20px;
        }
    </style>
</head>
<body>
    <form id="form" runat="server">
        <input type="button" value="Load GridView" onclick="getData('ScriptService.asmx/GetControlHtml','~/Controls/GridView.ascx');" />
        <input type="button" value="Load Login Control" onclick="getData('ScriptService.asmx/GetControlHtml','~/Controls/LoginControl.ascx');" />
 <div id="testDiv"></div>
    </form>
<script type="text/javascript">
…     
</script>
</body>
</html>

JavaScript для вызова веб-метода и динамического добавления пользовательского контрола на страницу

function getData(serviceURL, controlLocation) {
 $.ajax({
  type: "POST",
  contentType: "application/json; charset=utf-8",
  dataType: "json",
  url: serviceURL,
  data: "{'controlLocation':'" + controlLocation + "'}",
  success:
   function(msg){
     $('#testDiv').html(msg.d);
   },
  error:
   function(XMLHttpRequest, textStatus, errorThrown){
       alert( "Error Occured!" );
   }
 });
}

Для товарищей, малознакомых с JQuery (к коим отношусь пока и я), хочу объяснить следующую строку javascript-кода

$('#testDiv').html(msg.d);

Собственно в этой строке и происходит все чудо, а именно нам возвращается некий JSON-объект (msg), содержащий в себе строку. Часть строки $(‘#testDiv’) вернет нам набор объектов с id=’testDiv’ (в нашем случае это будет один div), далее мы вызываем метод html, который превратит нашу строку в дерево объектов и поместит его в коллекцию дочерних элементов нашего div’a. Эту операцию можно было записать несколько иначе:

$("#someElement")[0].innerHTML = msg.d;

Возможно, такая запись для кого-то будет понятней.

Данный пример доступен для скачивания. Исходные коды на C#.

Текущий рейтинг: 5.0 (5 голосов)

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


How To: Вызвать Javascript функцию после обновления UpdatePanel

clock апреля 7, 2008 16:45 by author paul

UpdatePanel - это контрол Microsoft ASP.NET AJAX, который позволяет довольно удобно интегрировать AJAX в ваше приложение. Но именно ввиду его удобства и простоты использования со стороны разработчика, некоторые вещи далеко не очевидны. К примеру как вызвать клиентский JavaScript по завершению очередного обновления этой панели?

Трюк заключается в том, чтобы добавить EndRequestHandler в request manager:

Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);

Вот пример формы с двумя TextBox, куда вы вводите текст, а сервер возвращает длину текста и отображает ее во втором TextBox:

<%@ page language="C#" autoeventwireup="true" codebehind="DemoJScriptUpdate.aspx.cs" inherits="CharterWeb.DemoJScriptUpdate" %>
 
 <script runat
="server">
 protected void txtDataOnChange(object sender, EventArgs e) {
 txtLength.Text = txtData.Text.Length.ToString();
 }
 </script>
 <html xmlns="<a href="http://www.w3.org/1999/xhtml">http://www.w3.org/1999/xhtml</a>">
 <head id="Head1" runat
="server">
 
 
 <script type="text/javascript">
 function EndRequestHandler(sender, args) {
 if (args.get_error() == undefined)
 alert("Your text has: " + document.getElementById("txtLength").value + " character(s)");
 else
 alert("There was an error" + args.get_error().message);
 }
 function load() {
 Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
 }
 </script>
 
 <form id="form1" runat
="server">
 <?xml:namespace prefix ="" asp /></asp:scriptmanager id="_scriptManager" runat="server">
 
 <asp:updatepanel id="UpdatePanel1" runat
="server">
 <contenttemplate>
 Write something: </asp:textbox id="txtData" runat="server" autopostback="true" ontextchanged="txtDataOnChange">
 <br />
 Server says the length is: </asp:textbox id="txtLength" runat="server" autopostback="true">
 </contenttemplate>
 </asp:updatepanel>
 
 </form> 

Текущий рейтинг: 4.9 (7 голосов)

  • Currently 4,857143/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


xhtmlConformance mode="Legacy" vs ASP.NET AJAX

clock апреля 2, 2008 16:42 by author paul

 Проблема:

Недавно у меня возникла проблема: после добавления контрола PowerWeb Zoom на страницу, напрочь отказывался работать AJAX. Оказалось этот контрол добавляет в Web.config следующую строчку для корректной работы своих JavaScriptов

<configuration>

    
<system.web>
        
<xhtmlConformance mode="Legacy" />
    </
system.web>


</configuration>

Объяснение:

При разработки еще ранних версий VS 2005 считалось что большинство приложений будут совместимы с XHTML, но для обратной совместимости решили оставить режим "Legacy" (non-XHTML формат страниц, аналогично страницам в ASP.NET 1.1). Иногда подобное изменение приводит и к изменению внешнего вида страниц.

Решение:

Добиться того, чтобы приложение отображало свои страницы в non-XHTML формате и при этом умело работать с асинхронными страницами невозможно, поэтому вам необходимо будет выбрать что-то одно. Хотя в некоторых случаях вы можете попробовать изменить режим на Transitional mode (XHTML Transitional) или на Strict mode (XHTML Strict).

В помощь вам будет список подобных "ловушек" при использовании AJAX, Visual Studio 2005, работы с данными и тп.

Текущий рейтинг: 5.0 (6 голосов)

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Search


LinkedIn Profile

Tags

Posts

  • Интересно бы почитать сравнение с jsUnit
    vasyas

  • Ну, если вы посмотрели и выяснили, что bottleneck в строго определенном месте и это место - доступ к данным, тогда оптимизацией этого места и стоит заняться.
    Merle

  • Улыбнуло :-) Особенно на фоне тех шестилитровых пикапов, на которых эти "экономные" амеры любят ездить.
    Vitalii Tsybulnyk

  • Да, Виталик, ты прав - проблема в извлечении данных. Но тут врядли что-то получиться исправить, скорее придумать иной способ извлечения данных. Мы сейчас думаем над использованием базы данных, возможно встроенной или попробовать заюзать xslt для формирования html файлов. Саша, страница слава богу не популярная и пользуются ей 2-3 человека. А dotTrace смотрели, но ничего нового не увидели - страница слишком проста, чтобы там затерятся 3333-ем поползновениям к источнику данных.
    Подлипенский Павел

  • Да, Паш, именно это и смутило :) Если у вас на одном пользователе такая загрузка, то что будет, если эту страницу откроют 2, 5, 10 пользователей? Возможно, это не самая популярная страница, но что-то мне подсказывает, что такая ситуация потенциально возможна. Это же веб. Если вы еще не пробовали запускать dotTrace, то я вам настоятельно рекомендую это сделать. Я у нас на проекте уже раз пять оптимизировал отдельные страницы приложения и один раз - все приложение в целом. Садился, записывал, разбирался. Как правило, оказывало, что у нас то алгоритм неоптимальный, то локального кеширования где-то нет и вместо этого мы 3333 раза лезем в базу вместо одного, то идет дублирование вызовов. И все это лечится за 5-10 минут, а прирост производительности в определенных ситуациях может достичь двух порядков.
    Merle

  • Думаю, как раз это смутило не только нас, но судя по ночному звонку, заказчика тоже... Если удалось успокоить его 10% ослаблением нагрузки - вероятно это не надолго и стоит воспользоваться передышкой и ускорить процедуру извлечения (обработки) данных, если проблема всё же в ней...
    Vitalii Tsybulnyk

Categories

Calendar

<<  Январь 2009  >>
воповтсрчепясу
28293031123
45678910
11121314151617
18192021222324
25262728293031
1234567

Archive

© Copyright 2009

Sign in

Ó÷àñòíèê ïëàíåòû Developers.org.ua

Bookmark and Share

Web Developement Blogs - Blog Catalog Blog Directory