Презентацию к данной лекции Вы можете скачать здесь.
На предыдущих лекциях была рассмотрена технология
UpdatePanel , за счет чего метод Page.Render отрисовывает не всю Среди недостатков подхода . Если же отказаться от использования , то для восстановления
Один из подходов к решению этих проблем заключается в использовании
Вместо того чтобы каждый раз ради отправки или получения данных посылать или получать всю
При этом, однако, многократно возрастает нагрузка на клиент. Это может привести к тому, что данный подход станет неприменим в случаях, когда у клиентов слабые компьютеры или на них установлены старые браузеры, плохо поддерживающие
При работе с
На Веб-
(рис 14.1) Взаимодействие клиент-сервер
Браузер вызывают методы
Чтобы вызвать метод XMLHTTP.
Код в прокси-классах скрывает сложность XMLHTTP [6] и различия между браузерами. Он упрощает клиентский сценарий, необходимый для вызова
Существует два подхода к вызовам методов
POST -запрос состоит из основной части, содержащей данные, которые обозреватель отправляет на сервер. Этот запрос не имеет ограничений по размеру. Поэтому можно использовать POST -запрос, если размер данных превышает внутреннее ограничение по размеру для запроса GET. Клиент сериализует запрос в формат POST. Сервер выполняет POST -запросу, однако существует несколько отличий:GET -запрос может вызвать только метод ScriptMethodAttribute ;На рис. 14.2 показана клиентская архитектура технологии
(рис 14.2) Клиентская архитектура AJAXК элементам клиентской архитектуры относятся уровень взаимодействия XMLHTTP браузера, который предоставляет возможность
WebRequest.Предоставляет функциональные возможности клиентского сценария для создания Веб-запроса.WebRequestManager. Управляет потоком Веб-запросов, направленных объектом Sys.Net.WebRequest соответствующему объекту-исполнителю.XmlHttpExecutor.Выполняет асинхронные сетевые запросы, используя поддержку XMLHTTP Веб-обозревателем.eval JavaScript.По умолчанию ScriptMethodAttribute, предписывающий методу
[ScriptMethod(ResponseFormat.Xml)]
На рис. 14.3 показана серверная архитектура
(рис 14.3) Серверная архитектура AJAXЭлементы серверной архитектуры включают уровень связи Веб-служб, обработчик HTTP-данных и классы
WebService, который служит для обозначения открытого класса, реализующего логику WebMethod. Среда
При построении
В начале ASMX- WebService, атрибуты которой содержат сведения о реализации WebService:
<%@ WebService Language="c#" Codebehind="Service1.asmx.cs"
Class="WebService1.Service1" %>
Атрибут Language указывает, какой язык программирования использовался для разработки сервиса.
При создании сервиса в управляемом коде с использованием Visual Studio .NET ее реализация находится в файле с выделенным кодом. Файл с выделенным кодом связывается с ASMX- Codebehind.
При использовании шаблона сервиса Class указывает, какой класс в файле с выделенным кодом реализует функциональные возможности сервиса.
Клиенты
Прежде чем обсуждать, каким образом можно использовать прокси-классы для вызова Веб-методов, рассмотрим, как можно решить ту же задачу при помощи класса WebRequest. Этим может потребоваться, если необходимо управлять уровнем связи или выполнять проверку данных, отправляемых на или с сервера, или если заранее не известны параметры самого сервиса.
В следующем примере показаны способы использования объекта WebRequest для реализации Веб-запросов GET и POST при подключении к указанным URL-адресам (конечные точки HTTP):
var resultElement;
function pageLoad()
{
resultElement = $get("ResultId");
}
// Эта функция вызывает GET запрос.
function GetWebRequest()
{
// Создаем объект WebRequest.
var wRequest = new Sys.Net.WebRequest();
// Указываем адрес.
wRequest.set_url("getTarget.htm");
alert("Target Url: getTarget.htm");
// Указываем команду.
wRequest.set_httpVerb("GET");
// Указываем-callback функцию.
wRequest.add_completed(OnWebRequestCompleted);
// Очищаем содержимое элемента, который будет использоваться для вывода результата.
resultElement.innerHTML = "";
// Вызываем запрос.
wRequest.invoke();
}
// Эта функция вызывает POST запрос.
function PostWebRequest()
{
// Создаем объект WebRequest.
var wRequest = new Sys.Net.WebRequest();
// Указываем адрес.
wRequest.set_url("postTarget.aspx");
alert("Target Url: postTarget.aspx");
// Указываем команду.
wRequest.set_httpVerb("POST");
// Указываем обработчик запроса.
wRequest.add_completed(OnWebRequestCompleted);
// Указываем тело POST.
var requestBody = "Message=Привет, Мир!";
wRequest.set_body(requestBody);
wRequest.get_headers()["Content-Length"] = requestBody.length;
// Очищаем содержимое элемента, который будет использоваться для вывода результата.
resultElement.innerHTML = "";
// Вызываем запрос.
wRequest.invoke();
}
// Эта функция вызывается асинхронно, когда завершится запрос.
function OnWebRequestCompleted(executor, eventArgs)
{
if(executor.get_responseAvailable())
{
// Отобразим статус запроса.
resultElement.innerHTML +=
"Status: [" + executor.get_statusCode() + " " +
executor.get_statusText() + "]" + "<br/>";
// Отобразим заголовки запроса.
resultElement.innerHTML += "Headers: ";
resultElement.innerHTML += executor.getAllResponseHeaders() + "<br/>";
// Отобразим тело запроса.
resultElement.innerHTML += "Body:";
if(document.all)
resultElement.innerText += executor.get_responseData();
else
resultElement.textContent += executor.get_responseData();
}
}
if (typeof(Sys) !== "undefined") Sys.Application.notifyScriptLoaded();
В табл. 11.1 перечислены основные классы, связанные с
| Имя | Описание |
|---|---|
Пространство имен Sys.Net |
Содержит классы, управляющие взаимодействием между клиентскими приложениями |
Пространство имен Sys.Serialization |
Содержит классы, связанные с |
Пространство имен Sys.Services |
Содержит типы, которые обеспечивают доступ сценариев клиентских приложений |
В табл. 11.2 перечислены основные классы, связанные с
| Имя | Описание |
|---|---|
System.Web.Script.Serialization |
Содержит классы, обеспечивающие |
Более удобный способ вызова Sys.Net.WebServiceProxy. Чтобы вызвать метод
Из сценария можно предоставить доступ к ScriptServiceAttribute. Отдельные методы, вызываемые из сценария, должны быть дополнены атрибутом WebMethodAttribute.
В следующем примере показан порядок использования этих атрибутов в коде
[ScriptService]
public class SimpleWebService : System.Web.Services.WebService
{
[WebMethod]
public string EchoInput(String input)
{
// Здесь расположен код метода.
}
}
Чтобы разрешить вызов Веб-служб из сценария, следует зарегистрировать обработчик HTTP ScriptHandlerFactory в файле Web.config приложения. Этот обработчик используется для обработки вызовов Веб-служб из сценария. В следующем примере показан элемент файла Web.config, определяющий добавление обработчика:
<system.web>
<httpHandlers>
<remove verb="*" path="*.asmx"/>
<add verb="*" path="*.asmx"
type="System.Web.Script.Services.ScriptHandlerFactory"
validate="false"/>
</httpHandlers>
<system.web>
Вызовы Веб-служб, выполненные не из сценария ScriptHandlerFactory делегирует используемому по умолчанию обработчику, в котором вместо формата Web.config необходимо определить следующие параметры конфигурации:
<system.web>
<webServices>
<protocols>
<clear/>
</protocols>
</webServices>
</system.web>
Чтобы разрешить вызов Веб-служб (ASMX) из клиентского сценария на Веб- . Чтобы определить ссылку на asp:ServiceReference к элементу управления . После этого необходимо установить URL-адрес path. Объект ServiceReference определяет необходимость создания прокси-класса
Добавим в начало :
<asp:ScriptManager ID="Scriptmanager1" runat="server">
<Services>
<asp:ServiceReference Path="~/SimpleWebService.asmx" />
</Services>
</asp:ScriptManager>
Объект ServiceReference может ссылаться на
При отображении , для SimpleWebService.asmx создается прокси-класс SimpleWebService.asmx.
Свойство InlineScript объекта ServiceReference определяет порядок включения прокси-класса InlineScript установлено значение false (используется по умолчанию), получение сценария прокси-класса выполняется с помощью отдельного запроса. Этот параметр рекомендуется использовать в том случае, если несколько
Если для свойства InlineScript установлено значение true, сценарий прокси-класса включается на InlineScript установлено значение true, необходимо использовать относительный путь. Путь, задаваемый относительно домена, должен содержать ссылку на то же Веб-приложение.
Вызов метода
Рассмотрим большинство указанных выше аспектов использования
В первом примере показан метод ColorObject, а также метод GetDefaultColor, который возвращает некоторый объект с цветом. Клиент после полной отрисовки
В первой части примера показана asmx, который содержит описание сервиса, и на файл HandleColor.js, который содержит
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html >
<head id="Head1" runat="server">
<title>Получение составного типа данных</title>
<style type="text/css">
body { font: 11pt Trebuchet MS;
font-color: #000000;
padding-top: 72px;
text-align: center }
.text { font: 8pt Trebuchet MS }
</style>
</head>
<body>
<h2>Получение составного типа данных</h2>
<form id="form1" runat="server">
<asp:ScriptManager runat="server" ID="scriptManager">
<Services>
<asp:ServiceReference Path="HandleColor.asmx" />
</Services>
<Scripts>
<asp:ScriptReference Path="HandleColor.js" />
</Scripts>
</asp:ScriptManager>
<table style="font-size:12px">
<tr>
<td>Цвет по умолчанию для Web-сервиса:</td>
<td>
<button id="Button1"
onclick="GetDefaultColor(); return false;">Получить цвет по умолчанию</button>
</td>
</tr>
</table>
<hr />
<!—Отображение текущего цвета.-->
<p>
<span style="background-color:Yellow">Цвет:</span>
<span id="ResultId"></span>
</p>
</form>
</body>
</html>
В следующей части примера показан клиентский сценарий HandleColor.js, который используется для вызова службы:
// Эта функция извлекает значение по умолчанию для цвета
function GetDefaultColor()
{
// Вызываем нужный Веб-сервис
Samples.AspNet.HandleColor.GetDefaultColor(SucceededCallback);
}
// Это функция обратного вызова, обрабатывающая результат вызова сервиса
function SucceededCallback(result)
{
// Извлечение данных, полученных от сервиса
var message = result.message;
var rgb = result.rgb;
var timeStamp = result.timeStamp;
// Преобразование RGB массива в строку
var serverColor = rgb[0]+ rgb[1] + rgb[2];
// Отображение результата
var displayResult = document.getElementById("ResultId");
displayResult.style.color = "yellow";
displayResult.style.fontWeight = "bold";
if (document.all)
displayResult.innerText = message + " " + timeStamp;
else
// Firefox
displayResult.textContent = message + " " + timeStamp;
displayResult.style.backgroundColor = "#" + serverColor;
}
if (typeof(Sys) !== "undefined") Sys.Application.notifyScriptLoaded();
В следующей части примера показана вызываемая на HandleColor.asmx, которая реализуется классом Samples.AspNet.HandleColor:
<%@ WebService Language="C#" Class="Samples.AspNet.HandleColor" %>
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Script.Services;
using System.Web.Script.Serialization;
namespace Samples.AspNet
{
// Определяем объект "Цвет" для общения с клиентом
public class ColorObject
{
public string message = "Цвет по умолчанию – синий.";
public string[] rgb = new string[] { "00", "00", "FF" };
public string timeStamp;
}
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[GenerateScriptType(typeof(ColorObject))]
[ScriptService]
public class HandleColor : System.Web.Services.WebService
{
[WebMethod]
public ColorObject GetDefaultColor()
{
// Создаем новый объект.
ColorObject co = new ColorObject();
// Указывает текущее время.
co.timeStamp = DateTime.Now.ToString();
return co;
}
}
}
Результат работы разработанной
(рис 14.4) Работа Веб-сервиса, возвращающего составной тип данныхВ следующем примере дорабатывается созданный сервис и ColorHelper, который используется для передачи на клиент списка доступных цветов. Также демонстрируется использование клиентских обработчиков ошибок.
В первой части примера показана HandleColor.asmx, который содержит описание сервиса, и на файл HandleColor.js, который содержит
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head id="Head1" runat="server">
<title>Получение составного типа данных</title>
<style type="text/css">
body
{
font: 11pt Trebuchet MS;
font-color: #000000;
padding-top: 72px;
text-align: center;
}
.text
{
font: 8pt Trebuchet MS;
}
</style>
</head>
<body>
<h2>Получение составного типа данных</h2>
<form id="form1" runat="server">
<asp:ScriptManager runat="server" ID="scriptManager">
<Services>
<asp:ServiceReference Path="HandleColor.asmx" />
</Services>
<Scripts>
<asp:ScriptReference Path="HandleColor.js" />
</Scripts>
</asp:ScriptManager>
<table style="font-size: 12px;">
<tr align="center">
<td class="text">
Изменить цвет:
</td>
<td>
<select id="ColorSelectID" onchange="OnChangeDefaultColor(this);" runat="server">
</select>
</td>
</tr>
</table>
<hr />
<!—Отображение текущего цвета.-->
<span style="background-color: Yellow">Цвет:</span>
<span id="ResultId"></span>
</form>
</body>
</html>
В следующей части примера показан клиентский сценарий HandleColor.js, который используется для вызова службы:
// Цвет по умолчанию для сервиса.
var defaultRgb;
// Элемент, отвечающий за отображение результата.
var displayResult;
// Получаем список доступных цветов и цвет по молчанию.
function GetServerColors() {
// Получаем цвет по умолчанию.
Samples.AspNet.HandleColor.GetDefaultColor(
SucceededCallback, FailedCallback);
// Получаем список доступных цветов.
Samples.AspNet.HandleColor.GetColorList(
SucceededCallback, FailedCallback);
}
// Эта функция отправляет на сервер выбранный пользователем объект цвет в элементе select
function OnChangeDefaultColor(comboObject) {
// Создаем экземпляр объекта.
var color = new Samples.AspNet.ColorObject();
// Поучаем выбранный пользователем цвет
var selectionIndex = comboObject.selectedIndex;
var selectedColor = comboObject.options[selectionIndex].text;
// Получаем RGB представление цвета.
var selectionValue = comboObject.value;
// И превращаем его в массив.
var colorArray = selectionValue.split(",");
// Присваиваем значения полей объекта
color.message = "Новый цвет по умолчанию " + selectedColor + ".";
color.rgb = colorArray;
// Вызываем сетод Веб-сервиса для изменения цвета.
Samples.AspNet.HandleColor.ChangeDefaultColor(
color, SucceededCallback, FailedCallback);
}
// Эта фунуция обрабатывает результат работы методов сервиса
function SucceededCallback(result, userContext, methodName) {
switch (methodName) {
case ("GetColorList"):
{
// Получаем элемент select.
var selectObject = document.getElementById("ColorSelectID");
var i = 0;
// Пробегаемся по списку для заполнению select данными
for (var j=0; j < result.length; j++) {
var item = result[j];
var option = new Option(item.name, item.rgb);
selectObject.options[i] = option;
// Устанавливаем значение по умолчанию.
if (item == defaultRgb[0] + defaultRgb[1] + defaultRgb[2])
selectObject.options[i].selected = true;
i++;
}
break;
}
default:
{
var message = result.message;
defaultRgb = result.rgb;
var timeStamp = result.timeStamp;
var serverColor = defaultRgb[0] + defaultRgb[1] + defaultRgb[2];
displayResult.style.color = "yellow";
displayResult.style.fontWeight = "bold";
if (document.all)
displayResult.innerText = message + " " + timeStamp;
else
// Firefox
displayResult.textContent = message + " " + timeStamp;
displayResult.style.backgroundColor = "#" + serverColor;
break;
}
}
}
// Функция обратного вызова, используемая в случае, если Веб-сервис отработал с ошибками
function FailedCallback(error, userContext, methodName) {
if (error !== null) {
displayResult.innerHTML = "Произошла ошибка: " + error.get_message();
}
}
// Получаем список цветов и цвет по умолчанию
function pageLoad() {
displayResult = document.getElementById("ResultId");
GetServerColors();
}
if (typeof (Sys) !== "undefined") Sys.Application.notifyScriptLoaded();
В следующей части примера показана вызываемая на HandleColor.asmx, которая реализуется классом Samples.AspNet.HandleColor:
<%@ WebService Language="C#" Class="Samples.AspNet.HandleColor" %>
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Script.Services;
using System.Web.Script.Serialization;
using System.Collections.Generic;
namespace Samples.AspNet
{
// Определяем объект цвет для "общения с клиентом"
public class ColorObject
{
public string message;
public string[] rgb;
public string timeStamp;
public ColorObject()
{
this.message = "Цвет по умолчанию – красный.";
this.rgb = new string[] { "FF", "00", "00" };
this.timeStamp = DateTime.Now.ToString();
}
}
// вспомогательный класс для отображения списка цветов
public class ColorHelper
{
public string name;
public string rgb;
public ColorHelper()
{
}
}
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[GenerateScriptType(typeof(ColorObject))]
[GenerateScriptType(typeof(ColorHelper))]
[ScriptService]
public class HandleColor : System.Web.Services.WebService
{
[WebMethod]
public ColorObject GetDefaultColor()
{
// Возвращаем новый объект.
ColorObject co = new ColorObject();
return co;
}
[WebMethod]
public ColorObject ChangeDefaultColor(ColorObject color)
{
// Создаем новый объект.
ColorObject co = new ColorObject();
// Присваиваем переданные значения.
co.message = color.message;
co.rgb = color.rgb;
// Указываем текущее время.
co.timeStamp = DateTime.Now.ToString();
return co;
}
[WebMethod]
public List<ColorHelper> GetColorList()
{
//Создаем таблицу цветов.
List<ColorHelper> result = new List<ColorHelper>();
//Добавляем несколько вариантов цветов.
result.Add(new ColorHelper() { rgb = "00,00,FF", name = "Синий" });
result.Add(new ColorHelper() { rgb = "FF,00,00", name = "Красный" });
result.Add(new ColorHelper() { rgb = "00,FF,00", name = "Зеленый" });
result.Add(new ColorHelper() { rgb = "00,00,00", name = "Черный" });
return result;
}
}
}
Результат работы сервиса и
(рис 14.5) Работа веб-сервиса, возвращающего список доступных цветовПредставленный подход позволяет улучшить производительность приложения, снизить нагрузку на сервере и упростить работу пользователя с сайтом. При этом, очевидно, что для отображения получаемых от
В результате получается, что
XmlHttpExecutor, WebRequestManager, WebRequest,
Основной недостаток
Рассмотрим простой пример: предположим, на UserControl, и наследника WebControl. У каждого из вариантов есть плюсы и минусы. В первом случае несомненным плюсом является возможность создания разметки, скриптов и стилей прям в ASCX-файле, но при этом данный
В обоих случаях, при реализации клиентской части
ClietnID Обобщим все возможные проблемы, при создании
PostBack'e, даже там, где это не нужно, что в свою очередь не очень хорошо сказывается на производительности;Технология
Создание нового приложения на WebSite/WebApplication, а использовать существующий. Главное, чтобы был добавлен Reference на сборку web.config для работы
<configuration>
<configSections>
<section name="jaspSettings" type="Jasp.Configuration.SettingsSection"/>
</configSections>
<jaspSettings />
<system.web>
<httpHandlers>
<add verb="*" path="*.jasp" type="Jasp.Web.HttpHandler, Jasp"/>
</httpHandlers>
</system.web>
<system.webServer>
<handlers>
<add name="JaspCommonHandler" path="*.jasp" verb="*" type="Jasp.Web.HttpHandler, Jasp"
resourceType="Unspecified" preCondition="integratedMode"/>
</handlers>
</system.webServer>
</configuration>
.jasp .Для создания . Имя класса должно совпадать с именем
Создадим "Hello world!".
using Jasp.Web.UI;
using Jasp.Web.UI.HtmlControls;
namespace Jasp.Examples
{
public class HelloWorld : Page
{
protected override void OnInit()
{
Body.Controls.Add(new Literal("Hello world!"));
}
}
}
Чтобы зайти на /HelloWorld.. Пока не будем углубляться в детали сгенерированного HTML, а просто убедимся, что все работает – в браузере увидим "Hello world!", и при загрузке
Рассмотрим пример создания
Для примера, создадим с библиотекой
Далее создадим класс для Example1:
using Jasp.Resources;
using Jasp.Web.UI;
namespace Jasp.Examples
{
[Resources("jquery-1_2_6_min.js")]
public class Example1 : Page
{
}
}
Добавим классу атрибут ResourcesAttribute с указанием имени файла с
Теперь создадим CSS файл Example1.css со стилями для текста
.text-style
{
color:red;
font-weight:bold;
font-size:large;
}
Также создадим файл Example1.htm с разметкой, содержащий текст, который будет анимироваться:
<html> <head> <title>Пример 1</title> </head> <body> <span id="text">Анимированный текст!</span> </body> </html>
Теперь создадим Example1.js с кодом, который будет анимировать текст:
{
// функция, вызываемая при инициализации контрола
$init: function(){
// указатель на текущий контрол
var self = this;
// дожидаемся инициализации jQuery
jQuery(document).ready(function(){
// запускаем анимацию
self.animateText();
});
},
// функция для анимации текста
animateText: function(){
// указатель на текущий контрол
var self = this;
// производим анимацию
jQuery(self.$text.$dom).toggleClass('text-style').toggle(1000, function(){
self.animateText();
});
}
}
После загрузки
Рассмотрим, каким образом
При загрузке
<script type="text/javascript" src="?$scripts=7_5_2_3_4_6_v=-1720007920"> </script> <link rel="stylesheet" type="text/css" href="?$styles=v=-1720007920" />
По-хорошему, у всех ), содержащая одинаковый набор базовых стилей и скриптов. Таким образом, данные
<script type="text/javascript" src="?$pageScripts=2_$r=v=-1720007920"> </script> <link rel="stylesheet" type="text/css" href="?$pageStyles=2_$r=v=-1720007920" />
У каждой
Зачастую в проектах бывает один или пару CSS файлов, в которые без разбора добавляются все стили из всего проекта, даже если стиль используется один раз для определенного элемента. Такой файл получается довольно большим и трудно поддерживаемым. В
Необходимо отметить, что
{
}
Если в объекте определена функция $init, то она будет вызвана сразу же после вызова клиентского конструктора (конструкторы создаются автоматически и подменять или модифицировать их нельзя):
{ $init: function(){
// код инициализации
}
}
Также в контексте данного объекта могут быть определены и другие функции
HTML
Также \deploy\<имя сборки> в корне сайта. В HTML, CSS и ~<имя сборки>/<путь к ресурсу>, например в CSS можно написать:
body {
background-image: url('~Jasp.Examples/Files/Images/background.gif')
}
В результирующий CSS попадет отформатированная ссылка на
body {
background-image: url('/deploy/Jasp.Examples/Files/Images/background.gif')
}
При разработке, нет необходимости каждый раз после изменения файла делать перекомпиляцию проекта –
Конечно, же, никто не мешает использовать обычный подход к
Зачастую, разные проекты на нужды одной компании имеют похожий интерфейс. Используя с layout 'ом по умолчанию,
Для создания , после чего, , будет обрабатываться по запросу /Example1., а с классом по адресу /OldExamples/Example2.. Естественно, имена
Для создания . В
Каждому alias, алиас) с помощью атрибута AliasAttribute, чтобы не указывать зачастую длинные полные имена, и использовать его в
Как говорилось ранее, в ResourcesAttribute, в котором перечислить названия общих
Также важно отметить, что на клиентской стороне $j<системный номер компонента>, но вероятность того, что данные "алиасы" могут вызвать конфликт с другими
Создать экземпляр
При использовании первых двух вариантов, Controls ), так и на клиентской (массив $controls ). Также на клиентской стороне у родительского $ ).
Для создания Add в коллекцию Controls родительского OnInit:
protected override void OnInit()
{
Controls.Add(new MyUserControl());
}
Для создания
<jasp.examples.controls.myusercontrol id="control1" title="Контрол 1" />
Для создания new, и передать необходимые параметры первым аргументом:
{
$init: function() {
var control = new Jasp.Examples.Controls.MyUserControl({
title: 'Контрол 1'
});
// производим необходимые действия с контролом
}
}
Если в аргументе задано свойство callback (типа function ), то callback будет вызван после создания
{
$init: function() {
new Jasp.Examples.Controls.MyUserControl({
title: 'Контрол 1',
callback: function(control) {
// производим необходимые действия с контролом
}
});
}
}
Если в аргументе задано свойство arg (типа array ), то при создании arg (поддерживается перегрузка только по числу параметров, по типу параметров перегрузка не поддерживается). По своей сути arg – это аргумент конструктора. При этом на сервере все дочерние JsonRpcMethodAttribute.
Например, у нас есть следующий
public class MyUserControl : UserControl
{
private int _x, _y;
public MyUserControl()
{
}
[JsonRpcMethod]
public MyUserControl(int x, int y)
{
_x = x;
_y = y;
}
protected override void OnLoad()
{
Title = string.Format("Сумма {0}", _x + _y);
}
public string Title
{
get { return (string)Data["title"]; }
set { Data["title"] = value; }
}
///// <summary>
///// Данная реализация свойства работает с компонентом title, определенным в разметке
///// </summary>
//public string Title
//{
// get { return ((HtmlControl)GetById("title")).InnerText; }
// set { ((HtmlControl)GetById("title")).InnerText = value; }
//}
}
JsonRpcMethodAttribute был удален. Теперь все публичные методы доступны из Одновременно создание
{
$init: function() {
var control = new Jasp.Examples.Controls.MyUserControl({
title: 'Контрол 1',
arg: [3, 2]
});
// производим необходимые действия с контролом
}
}
Как видно из примера, на сервере происходит сложение двух чисел, переданных в клиентский конструктор через параметр arg. Результат записывается в свойство Title, которое может передавать результат на клиентскую сторону в виде Data либо через произвольный HTML элемент. Например, через конструктор удобно передавать идентификаторы либо другие объекты, характеризующие какие-либо сущности, далее загружать необходимые данные на сервере и возвращать их на клиентскую сторону вместе с
Если arg не определен, то произойдет только клиентское создание
Для передачи данных на клиентскую сторону, на сервере можно использовать словарь Data, который есть у каждого $data.
Например, записав при загрузке текущую дату:
protected override void OnLoad()
{
Data["serverTime"] = DateTime.Now;
}
До нее можно с легкостью добраться на клиентской стороне:
{
$init: function() {
alert(this.$data.serverTime);
}
}
Данную методику можно использовать только в момент загрузки
Если на клиентской стороне необходимо получить/отправить данные в произвольный момент, можно воспользоваться удаленным вызовом функции (RPC). Все методы RpcMethodAttribute, можно вызывать удаленно.
Пример таких методов представлен ниже. Остается отметить, что такие методы, по сути, являются методами
public class MyUserControl : UserControl
{
[JsonRpcMethod]
public Person GetPersonById(int personId)
{
// возвращаем Person
}
[JsonRpcMethod]
public void SavePerson(Person person)
{
// сохраняем Person
}
}
Перегрузка функций поддерживается только по количеству параметров. По типу параметров перегрузка не поддерживается. В качестве параметров или возвращаемого значения могут быть произвольные объекты, которые впоследствии будут отформатированы в
в
Для
По умолчанию, HTML разметка копируется от базового <replacement> можно заменять или удалять базовые
<body> <div id="div1">Первоначальный текст </div> </body>
И производная разметка:
<replacement id="div1"> <div id="div2">Переопределенный текст</div> И другой текст </replacement>
При копировании разметки из базового div1 будет подставлена замена из тега replacement с одноименным идентификатором.
При добавлении CSS
{
hi: function() {
alert('Базовый привет!');
}
}
И производного:
{
hi: function() {
alert('Привет!');
BaseFooControl.prototype.call(this);
}
}
Для библиотек, которые поддерживают ClientBaseAttribute:
[ClientBase("Ext.Window")]
public class FooControl : UserControl
{
//....
public FooControl(int fooId)
{
// подгружаем необходимые данные
}
}
Клиентский код:
{
onFooButtonClick: function() {
// Создаем FooControl
// происходит вызов серверного конструктора – в нем можно подгрузить необходимые данные
// и вызов $init – в нем инициализировать окно, подставить загруженные данные
var fooControl = new FooControl({
arg: [1] // параметры конструктора
});
// Показываем окно (метод show наследован из ExtJs)
fooControl.show();
}
// ...
}
Благодаря этому, $. Так, например, удается избежать конфликтов идентификаторов ( id ) или часто распространенных имен функций ( init ).
web.config.
Также необходимо добавить HttpHadler и WebServer Hadler, чтобы
| Название | Описание | Значение в Release | Значение в Debug | Тип |
|---|---|---|---|---|
deployPath |
Путь, относительный от корня сайта, куда "распаковывать" бинарные |
deploy |
deploy |
String |
resourceFilter |
Полное имя класса, который фильтрует все текстовые |
, |
, |
String |
gzipEnabled |
Включен ли GZIP. |
True |
False |
Boolean |
watchResources |
Включено ли слежение за изменением текстовых |
False |
True |
Boolean |
compressJavaScript |
Включено ли сжатие |
True |
False |
Boolean |
clientCaching |
Включена ли отправка HTTP заголовков кэширования. | True |
False |
Boolean |
indentHtml |
Включено ли форматирование HTML. | False |
True |
Boolean |
exceptionFormatter |
Полное имя класса, занимающегося форматирование исключения в |
, |
, |
String |
Параметр resourceFilter определяет класс, экземпляр которого будет заниматься фильтрацией текстовых и переопределять метод Filter(string name, StringBuilder data). Отфильтрованный
Параметр exceptionFormatter используется для указания класса, экземпляр которого форматирует исключение при RPC-вызовах в nHibernate, то это без труда можно сделать, переопределив метод Format класса .
Узнав, что все embedded resource, многие думают, что для вступления в силу изменений в HTML, CSS или в watchResources. Если он установлен в True, то
При работе с
Обмен данными между клиентом и сервером осуществляется асинхронно, как правило, в формате
Существует два подхода к вызовам методов
POST HTTP ;GET HTTP.Основные элементы уровня связи Веб-служб:
WebRequest;WebRequestManager ;XmlHttpExecutor ;Элементы серверной архитектуры
WebRequest;Основным отличием
При загрузке
Для создания .
Для создания .
Экземпляры
Для передачи данных на клиентскую сторону, на сервере можно использовать словарь Data, который есть у каждого
web.config.
Презентацию к данной лекции Вы можете скачать здесь.
На предыдущих лекциях была рассмотрена технология
UpdatePanel , за счет чего метод Page.Render отрисовывает не всю Среди недостатков подхода . Если же отказаться от использования , то для восстановления
Один из подходов к решению этих проблем заключается в использовании
Вместо того чтобы каждый раз ради отправки или получения данных посылать или получать всю
При этом, однако, многократно возрастает нагрузка на клиент. Это может привести к тому, что данный подход станет неприменим в случаях, когда у клиентов слабые компьютеры или на них установлены старые браузеры, плохо поддерживающие
При работе с
На Веб-
(рис 14.1) Взаимодействие клиент-сервер
Браузер вызывают методы
Чтобы вызвать метод XMLHTTP.
Код в прокси-классах скрывает сложность XMLHTTP [6] и различия между браузерами. Он упрощает клиентский сценарий, необходимый для вызова
Существует два подхода к вызовам методов
POST -запрос состоит из основной части, содержащей данные, которые обозреватель отправляет на сервер. Этот запрос не имеет ограничений по размеру. Поэтому можно использовать POST -запрос, если размер данных превышает внутреннее ограничение по размеру для запроса GET. Клиент сериализует запрос в формат POST. Сервер выполняет POST -запросу, однако существует несколько отличий:GET -запрос может вызвать только метод ScriptMethodAttribute ;На рис. 14.2 показана клиентская архитектура технологии
(рис 14.2) Клиентская архитектура AJAXК элементам клиентской архитектуры относятся уровень взаимодействия XMLHTTP браузера, который предоставляет возможность
WebRequest.Предоставляет функциональные возможности клиентского сценария для создания Веб-запроса.WebRequestManager. Управляет потоком Веб-запросов, направленных объектом Sys.Net.WebRequest соответствующему объекту-исполнителю.XmlHttpExecutor.Выполняет асинхронные сетевые запросы, используя поддержку XMLHTTP Веб-обозревателем.eval JavaScript.По умолчанию ScriptMethodAttribute, предписывающий методу
[ScriptMethod(ResponseFormat.Xml)]
На рис. 14.3 показана серверная архитектура
(рис 14.3) Серверная архитектура AJAXЭлементы серверной архитектуры включают уровень связи Веб-служб, обработчик HTTP-данных и классы
WebService, который служит для обозначения открытого класса, реализующего логику WebMethod. Среда
При построении
В начале ASMX- WebService, атрибуты которой содержат сведения о реализации WebService:
<%@ WebService Language="c#" Codebehind="Service1.asmx.cs"
Class="WebService1.Service1" %>
Атрибут Language указывает, какой язык программирования использовался для разработки сервиса.
При создании сервиса в управляемом коде с использованием Visual Studio .NET ее реализация находится в файле с выделенным кодом. Файл с выделенным кодом связывается с ASMX- Codebehind.
При использовании шаблона сервиса Class указывает, какой класс в файле с выделенным кодом реализует функциональные возможности сервиса.
Клиенты
Прежде чем обсуждать, каким образом можно использовать прокси-классы для вызова Веб-методов, рассмотрим, как можно решить ту же задачу при помощи класса WebRequest. Этим может потребоваться, если необходимо управлять уровнем связи или выполнять проверку данных, отправляемых на или с сервера, или если заранее не известны параметры самого сервиса.
В следующем примере показаны способы использования объекта WebRequest для реализации Веб-запросов GET и POST при подключении к указанным URL-адресам (конечные точки HTTP):
var resultElement;
function pageLoad()
{
resultElement = $get("ResultId");
}
// Эта функция вызывает GET запрос.
function GetWebRequest()
{
// Создаем объект WebRequest.
var wRequest = new Sys.Net.WebRequest();
// Указываем адрес.
wRequest.set_url("getTarget.htm");
alert("Target Url: getTarget.htm");
// Указываем команду.
wRequest.set_httpVerb("GET");
// Указываем-callback функцию.
wRequest.add_completed(OnWebRequestCompleted);
// Очищаем содержимое элемента, который будет использоваться для вывода результата.
resultElement.innerHTML = "";
// Вызываем запрос.
wRequest.invoke();
}
// Эта функция вызывает POST запрос.
function PostWebRequest()
{
// Создаем объект WebRequest.
var wRequest = new Sys.Net.WebRequest();
// Указываем адрес.
wRequest.set_url("postTarget.aspx");
alert("Target Url: postTarget.aspx");
// Указываем команду.
wRequest.set_httpVerb("POST");
// Указываем обработчик запроса.
wRequest.add_completed(OnWebRequestCompleted);
// Указываем тело POST.
var requestBody = "Message=Привет, Мир!";
wRequest.set_body(requestBody);
wRequest.get_headers()["Content-Length"] = requestBody.length;
// Очищаем содержимое элемента, который будет использоваться для вывода результата.
resultElement.innerHTML = "";
// Вызываем запрос.
wRequest.invoke();
}
// Эта функция вызывается асинхронно, когда завершится запрос.
function OnWebRequestCompleted(executor, eventArgs)
{
if(executor.get_responseAvailable())
{
// Отобразим статус запроса.
resultElement.innerHTML +=
"Status: [" + executor.get_statusCode() + " " +
executor.get_statusText() + "]" + "<br/>";
// Отобразим заголовки запроса.
resultElement.innerHTML += "Headers: ";
resultElement.innerHTML += executor.getAllResponseHeaders() + "<br/>";
// Отобразим тело запроса.
resultElement.innerHTML += "Body:";
if(document.all)
resultElement.innerText += executor.get_responseData();
else
resultElement.textContent += executor.get_responseData();
}
}
if (typeof(Sys) !== "undefined") Sys.Application.notifyScriptLoaded();
В табл. 11.1 перечислены основные классы, связанные с
| Имя | Описание |
|---|---|
Пространство имен Sys.Net |
Содержит классы, управляющие взаимодействием между клиентскими приложениями |
Пространство имен Sys.Serialization |
Содержит классы, связанные с |
Пространство имен Sys.Services |
Содержит типы, которые обеспечивают доступ сценариев клиентских приложений |
В табл. 11.2 перечислены основные классы, связанные с
| Имя | Описание |
|---|---|
System.Web.Script.Serialization |
Содержит классы, обеспечивающие |
Более удобный способ вызова Sys.Net.WebServiceProxy. Чтобы вызвать метод
Из сценария можно предоставить доступ к ScriptServiceAttribute. Отдельные методы, вызываемые из сценария, должны быть дополнены атрибутом WebMethodAttribute.
В следующем примере показан порядок использования этих атрибутов в коде
[ScriptService]
public class SimpleWebService : System.Web.Services.WebService
{
[WebMethod]
public string EchoInput(String input)
{
// Здесь расположен код метода.
}
}
Чтобы разрешить вызов Веб-служб из сценария, следует зарегистрировать обработчик HTTP ScriptHandlerFactory в файле Web.config приложения. Этот обработчик используется для обработки вызовов Веб-служб из сценария. В следующем примере показан элемент файла Web.config, определяющий добавление обработчика:
<system.web>
<httpHandlers>
<remove verb="*" path="*.asmx"/>
<add verb="*" path="*.asmx"
type="System.Web.Script.Services.ScriptHandlerFactory"
validate="false"/>
</httpHandlers>
<system.web>
Вызовы Веб-служб, выполненные не из сценария ScriptHandlerFactory делегирует используемому по умолчанию обработчику, в котором вместо формата Web.config необходимо определить следующие параметры конфигурации:
<system.web>
<webServices>
<protocols>
<clear/>
</protocols>
</webServices>
</system.web>
Чтобы разрешить вызов Веб-служб (ASMX) из клиентского сценария на Веб- . Чтобы определить ссылку на asp:ServiceReference к элементу управления . После этого необходимо установить URL-адрес path. Объект ServiceReference определяет необходимость создания прокси-класса
Добавим в начало :
<asp:ScriptManager ID="Scriptmanager1" runat="server">
<Services>
<asp:ServiceReference Path="~/SimpleWebService.asmx" />
</Services>
</asp:ScriptManager>
Объект ServiceReference может ссылаться на
При отображении , для SimpleWebService.asmx создается прокси-класс SimpleWebService.asmx.
Свойство InlineScript объекта ServiceReference определяет порядок включения прокси-класса InlineScript установлено значение false (используется по умолчанию), получение сценария прокси-класса выполняется с помощью отдельного запроса. Этот параметр рекомендуется использовать в том случае, если несколько
Если для свойства InlineScript установлено значение true, сценарий прокси-класса включается на InlineScript установлено значение true, необходимо использовать относительный путь. Путь, задаваемый относительно домена, должен содержать ссылку на то же Веб-приложение.
Вызов метода
Рассмотрим большинство указанных выше аспектов использования
В первом примере показан метод ColorObject, а также метод GetDefaultColor, который возвращает некоторый объект с цветом. Клиент после полной отрисовки
В первой части примера показана asmx, который содержит описание сервиса, и на файл HandleColor.js, который содержит
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html >
<head id="Head1" runat="server">
<title>Получение составного типа данных</title>
<style type="text/css">
body { font: 11pt Trebuchet MS;
font-color: #000000;
padding-top: 72px;
text-align: center }
.text { font: 8pt Trebuchet MS }
</style>
</head>
<body>
<h2>Получение составного типа данных</h2>
<form id="form1" runat="server">
<asp:ScriptManager runat="server" ID="scriptManager">
<Services>
<asp:ServiceReference Path="HandleColor.asmx" />
</Services>
<Scripts>
<asp:ScriptReference Path="HandleColor.js" />
</Scripts>
</asp:ScriptManager>
<table style="font-size:12px">
<tr>
<td>Цвет по умолчанию для Web-сервиса:</td>
<td>
<button id="Button1"
onclick="GetDefaultColor(); return false;">Получить цвет по умолчанию</button>
</td>
</tr>
</table>
<hr />
<!—Отображение текущего цвета.-->
<p>
<span style="background-color:Yellow">Цвет:</span>
<span id="ResultId"></span>
</p>
</form>
</body>
</html>
В следующей части примера показан клиентский сценарий HandleColor.js, который используется для вызова службы:
// Эта функция извлекает значение по умолчанию для цвета
function GetDefaultColor()
{
// Вызываем нужный Веб-сервис
Samples.AspNet.HandleColor.GetDefaultColor(SucceededCallback);
}
// Это функция обратного вызова, обрабатывающая результат вызова сервиса
function SucceededCallback(result)
{
// Извлечение данных, полученных от сервиса
var message = result.message;
var rgb = result.rgb;
var timeStamp = result.timeStamp;
// Преобразование RGB массива в строку
var serverColor = rgb[0]+ rgb[1] + rgb[2];
// Отображение результата
var displayResult = document.getElementById("ResultId");
displayResult.style.color = "yellow";
displayResult.style.fontWeight = "bold";
if (document.all)
displayResult.innerText = message + " " + timeStamp;
else
// Firefox
displayResult.textContent = message + " " + timeStamp;
displayResult.style.backgroundColor = "#" + serverColor;
}
if (typeof(Sys) !== "undefined") Sys.Application.notifyScriptLoaded();
В следующей части примера показана вызываемая на HandleColor.asmx, которая реализуется классом Samples.AspNet.HandleColor:
<%@ WebService Language="C#" Class="Samples.AspNet.HandleColor" %>
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Script.Services;
using System.Web.Script.Serialization;
namespace Samples.AspNet
{
// Определяем объект "Цвет" для общения с клиентом
public class ColorObject
{
public string message = "Цвет по умолчанию – синий.";
public string[] rgb = new string[] { "00", "00", "FF" };
public string timeStamp;
}
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[GenerateScriptType(typeof(ColorObject))]
[ScriptService]
public class HandleColor : System.Web.Services.WebService
{
[WebMethod]
public ColorObject GetDefaultColor()
{
// Создаем новый объект.
ColorObject co = new ColorObject();
// Указывает текущее время.
co.timeStamp = DateTime.Now.ToString();
return co;
}
}
}
Результат работы разработанной
(рис 14.4) Работа Веб-сервиса, возвращающего составной тип данныхВ следующем примере дорабатывается созданный сервис и ColorHelper, который используется для передачи на клиент списка доступных цветов. Также демонстрируется использование клиентских обработчиков ошибок.
В первой части примера показана HandleColor.asmx, который содержит описание сервиса, и на файл HandleColor.js, который содержит
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head id="Head1" runat="server">
<title>Получение составного типа данных</title>
<style type="text/css">
body
{
font: 11pt Trebuchet MS;
font-color: #000000;
padding-top: 72px;
text-align: center;
}
.text
{
font: 8pt Trebuchet MS;
}
</style>
</head>
<body>
<h2>Получение составного типа данных</h2>
<form id="form1" runat="server">
<asp:ScriptManager runat="server" ID="scriptManager">
<Services>
<asp:ServiceReference Path="HandleColor.asmx" />
</Services>
<Scripts>
<asp:ScriptReference Path="HandleColor.js" />
</Scripts>
</asp:ScriptManager>
<table style="font-size: 12px;">
<tr align="center">
<td class="text">
Изменить цвет:
</td>
<td>
<select id="ColorSelectID" onchange="OnChangeDefaultColor(this);" runat="server">
</select>
</td>
</tr>
</table>
<hr />
<!—Отображение текущего цвета.-->
<span style="background-color: Yellow">Цвет:</span>
<span id="ResultId"></span>
</form>
</body>
</html>
В следующей части примера показан клиентский сценарий HandleColor.js, который используется для вызова службы:
// Цвет по умолчанию для сервиса.
var defaultRgb;
// Элемент, отвечающий за отображение результата.
var displayResult;
// Получаем список доступных цветов и цвет по молчанию.
function GetServerColors() {
// Получаем цвет по умолчанию.
Samples.AspNet.HandleColor.GetDefaultColor(
SucceededCallback, FailedCallback);
// Получаем список доступных цветов.
Samples.AspNet.HandleColor.GetColorList(
SucceededCallback, FailedCallback);
}
// Эта функция отправляет на сервер выбранный пользователем объект цвет в элементе select
function OnChangeDefaultColor(comboObject) {
// Создаем экземпляр объекта.
var color = new Samples.AspNet.ColorObject();
// Поучаем выбранный пользователем цвет
var selectionIndex = comboObject.selectedIndex;
var selectedColor = comboObject.options[selectionIndex].text;
// Получаем RGB представление цвета.
var selectionValue = comboObject.value;
// И превращаем его в массив.
var colorArray = selectionValue.split(",");
// Присваиваем значения полей объекта
color.message = "Новый цвет по умолчанию " + selectedColor + ".";
color.rgb = colorArray;
// Вызываем сетод Веб-сервиса для изменения цвета.
Samples.AspNet.HandleColor.ChangeDefaultColor(
color, SucceededCallback, FailedCallback);
}
// Эта фунуция обрабатывает результат работы методов сервиса
function SucceededCallback(result, userContext, methodName) {
switch (methodName) {
case ("GetColorList"):
{
// Получаем элемент select.
var selectObject = document.getElementById("ColorSelectID");
var i = 0;
// Пробегаемся по списку для заполнению select данными
for (var j=0; j < result.length; j++) {
var item = result[j];
var option = new Option(item.name, item.rgb);
selectObject.options[i] = option;
// Устанавливаем значение по умолчанию.
if (item == defaultRgb[0] + defaultRgb[1] + defaultRgb[2])
selectObject.options[i].selected = true;
i++;
}
break;
}
default:
{
var message = result.message;
defaultRgb = result.rgb;
var timeStamp = result.timeStamp;
var serverColor = defaultRgb[0] + defaultRgb[1] + defaultRgb[2];
displayResult.style.color = "yellow";
displayResult.style.fontWeight = "bold";
if (document.all)
displayResult.innerText = message + " " + timeStamp;
else
// Firefox
displayResult.textContent = message + " " + timeStamp;
displayResult.style.backgroundColor = "#" + serverColor;
break;
}
}
}
// Функция обратного вызова, используемая в случае, если Веб-сервис отработал с ошибками
function FailedCallback(error, userContext, methodName) {
if (error !== null) {
displayResult.innerHTML = "Произошла ошибка: " + error.get_message();
}
}
// Получаем список цветов и цвет по умолчанию
function pageLoad() {
displayResult = document.getElementById("ResultId");
GetServerColors();
}
if (typeof (Sys) !== "undefined") Sys.Application.notifyScriptLoaded();
В следующей части примера показана вызываемая на HandleColor.asmx, которая реализуется классом Samples.AspNet.HandleColor:
<%@ WebService Language="C#" Class="Samples.AspNet.HandleColor" %>
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Script.Services;
using System.Web.Script.Serialization;
using System.Collections.Generic;
namespace Samples.AspNet
{
// Определяем объект цвет для "общения с клиентом"
public class ColorObject
{
public string message;
public string[] rgb;
public string timeStamp;
public ColorObject()
{
this.message = "Цвет по умолчанию – красный.";
this.rgb = new string[] { "FF", "00", "00" };
this.timeStamp = DateTime.Now.ToString();
}
}
// вспомогательный класс для отображения списка цветов
public class ColorHelper
{
public string name;
public string rgb;
public ColorHelper()
{
}
}
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[GenerateScriptType(typeof(ColorObject))]
[GenerateScriptType(typeof(ColorHelper))]
[ScriptService]
public class HandleColor : System.Web.Services.WebService
{
[WebMethod]
public ColorObject GetDefaultColor()
{
// Возвращаем новый объект.
ColorObject co = new ColorObject();
return co;
}
[WebMethod]
public ColorObject ChangeDefaultColor(ColorObject color)
{
// Создаем новый объект.
ColorObject co = new ColorObject();
// Присваиваем переданные значения.
co.message = color.message;
co.rgb = color.rgb;
// Указываем текущее время.
co.timeStamp = DateTime.Now.ToString();
return co;
}
[WebMethod]
public List<ColorHelper> GetColorList()
{
//Создаем таблицу цветов.
List<ColorHelper> result = new List<ColorHelper>();
//Добавляем несколько вариантов цветов.
result.Add(new ColorHelper() { rgb = "00,00,FF", name = "Синий" });
result.Add(new ColorHelper() { rgb = "FF,00,00", name = "Красный" });
result.Add(new ColorHelper() { rgb = "00,FF,00", name = "Зеленый" });
result.Add(new ColorHelper() { rgb = "00,00,00", name = "Черный" });
return result;
}
}
}
Результат работы сервиса и
(рис 14.5) Работа веб-сервиса, возвращающего список доступных цветовПредставленный подход позволяет улучшить производительность приложения, снизить нагрузку на сервере и упростить работу пользователя с сайтом. При этом, очевидно, что для отображения получаемых от
В результате получается, что
XmlHttpExecutor, WebRequestManager, WebRequest,
Основной недостаток
Рассмотрим простой пример: предположим, на UserControl, и наследника WebControl. У каждого из вариантов есть плюсы и минусы. В первом случае несомненным плюсом является возможность создания разметки, скриптов и стилей прям в ASCX-файле, но при этом данный
В обоих случаях, при реализации клиентской части
ClietnID Обобщим все возможные проблемы, при создании
PostBack'e, даже там, где это не нужно, что в свою очередь не очень хорошо сказывается на производительности;Технология
Создание нового приложения на WebSite/WebApplication, а использовать существующий. Главное, чтобы был добавлен Reference на сборку web.config для работы
<configuration>
<configSections>
<section name="jaspSettings" type="Jasp.Configuration.SettingsSection"/>
</configSections>
<jaspSettings />
<system.web>
<httpHandlers>
<add verb="*" path="*.jasp" type="Jasp.Web.HttpHandler, Jasp"/>
</httpHandlers>
</system.web>
<system.webServer>
<handlers>
<add name="JaspCommonHandler" path="*.jasp" verb="*" type="Jasp.Web.HttpHandler, Jasp"
resourceType="Unspecified" preCondition="integratedMode"/>
</handlers>
</system.webServer>
</configuration>
.jasp .Для создания . Имя класса должно совпадать с именем
Создадим "Hello world!".
using Jasp.Web.UI;
using Jasp.Web.UI.HtmlControls;
namespace Jasp.Examples
{
public class HelloWorld : Page
{
protected override void OnInit()
{
Body.Controls.Add(new Literal("Hello world!"));
}
}
}
Чтобы зайти на /HelloWorld.. Пока не будем углубляться в детали сгенерированного HTML, а просто убедимся, что все работает – в браузере увидим "Hello world!", и при загрузке
Рассмотрим пример создания
Для примера, создадим с библиотекой
Далее создадим класс для Example1:
using Jasp.Resources;
using Jasp.Web.UI;
namespace Jasp.Examples
{
[Resources("jquery-1_2_6_min.js")]
public class Example1 : Page
{
}
}
Добавим классу атрибут ResourcesAttribute с указанием имени файла с
Теперь создадим CSS файл Example1.css со стилями для текста
.text-style
{
color:red;
font-weight:bold;
font-size:large;
}
Также создадим файл Example1.htm с разметкой, содержащий текст, который будет анимироваться:
<html> <head> <title>Пример 1</title> </head> <body> <span id="text">Анимированный текст!</span> </body> </html>
Теперь создадим Example1.js с кодом, который будет анимировать текст:
{
// функция, вызываемая при инициализации контрола
$init: function(){
// указатель на текущий контрол
var self = this;
// дожидаемся инициализации jQuery
jQuery(document).ready(function(){
// запускаем анимацию
self.animateText();
});
},
// функция для анимации текста
animateText: function(){
// указатель на текущий контрол
var self = this;
// производим анимацию
jQuery(self.$text.$dom).toggleClass('text-style').toggle(1000, function(){
self.animateText();
});
}
}
После загрузки
Рассмотрим, каким образом
При загрузке
<script type="text/javascript" src="?$scripts=7_5_2_3_4_6_v=-1720007920"> </script> <link rel="stylesheet" type="text/css" href="?$styles=v=-1720007920" />
По-хорошему, у всех ), содержащая одинаковый набор базовых стилей и скриптов. Таким образом, данные
<script type="text/javascript" src="?$pageScripts=2_$r=v=-1720007920"> </script> <link rel="stylesheet" type="text/css" href="?$pageStyles=2_$r=v=-1720007920" />
У каждой
Зачастую в проектах бывает один или пару CSS файлов, в которые без разбора добавляются все стили из всего проекта, даже если стиль используется один раз для определенного элемента. Такой файл получается довольно большим и трудно поддерживаемым. В
Необходимо отметить, что
{
}
Если в объекте определена функция $init, то она будет вызвана сразу же после вызова клиентского конструктора (конструкторы создаются автоматически и подменять или модифицировать их нельзя):
{ $init: function(){
// код инициализации
}
}
Также в контексте данного объекта могут быть определены и другие функции
HTML
Также \deploy\<имя сборки> в корне сайта. В HTML, CSS и ~<имя сборки>/<путь к ресурсу>, например в CSS можно написать:
body {
background-image: url('~Jasp.Examples/Files/Images/background.gif')
}
В результирующий CSS попадет отформатированная ссылка на
body {
background-image: url('/deploy/Jasp.Examples/Files/Images/background.gif')
}
При разработке, нет необходимости каждый раз после изменения файла делать перекомпиляцию проекта –
Конечно, же, никто не мешает использовать обычный подход к
Зачастую, разные проекты на нужды одной компании имеют похожий интерфейс. Используя с layout 'ом по умолчанию,
Для создания , после чего, , будет обрабатываться по запросу /Example1., а с классом по адресу /OldExamples/Example2.. Естественно, имена
Для создания . В
Каждому alias, алиас) с помощью атрибута AliasAttribute, чтобы не указывать зачастую длинные полные имена, и использовать его в
Как говорилось ранее, в ResourcesAttribute, в котором перечислить названия общих
Также важно отметить, что на клиентской стороне $j<системный номер компонента>, но вероятность того, что данные "алиасы" могут вызвать конфликт с другими
Создать экземпляр
При использовании первых двух вариантов, Controls ), так и на клиентской (массив $controls ). Также на клиентской стороне у родительского $ ).
Для создания Add в коллекцию Controls родительского OnInit:
protected override void OnInit()
{
Controls.Add(new MyUserControl());
}
Для создания
<jasp.examples.controls.myusercontrol id="control1" title="Контрол 1" />
Для создания new, и передать необходимые параметры первым аргументом:
{
$init: function() {
var control = new Jasp.Examples.Controls.MyUserControl({
title: 'Контрол 1'
});
// производим необходимые действия с контролом
}
}
Если в аргументе задано свойство callback (типа function ), то callback будет вызван после создания
{
$init: function() {
new Jasp.Examples.Controls.MyUserControl({
title: 'Контрол 1',
callback: function(control) {
// производим необходимые действия с контролом
}
});
}
}
Если в аргументе задано свойство arg (типа array ), то при создании arg (поддерживается перегрузка только по числу параметров, по типу параметров перегрузка не поддерживается). По своей сути arg – это аргумент конструктора. При этом на сервере все дочерние JsonRpcMethodAttribute.
Например, у нас есть следующий
public class MyUserControl : UserControl
{
private int _x, _y;
public MyUserControl()
{
}
[JsonRpcMethod]
public MyUserControl(int x, int y)
{
_x = x;
_y = y;
}
protected override void OnLoad()
{
Title = string.Format("Сумма {0}", _x + _y);
}
public string Title
{
get { return (string)Data["title"]; }
set { Data["title"] = value; }
}
///// <summary>
///// Данная реализация свойства работает с компонентом title, определенным в разметке
///// </summary>
//public string Title
//{
// get { return ((HtmlControl)GetById("title")).InnerText; }
// set { ((HtmlControl)GetById("title")).InnerText = value; }
//}
}
JsonRpcMethodAttribute был удален. Теперь все публичные методы доступны из Одновременно создание
{
$init: function() {
var control = new Jasp.Examples.Controls.MyUserControl({
title: 'Контрол 1',
arg: [3, 2]
});
// производим необходимые действия с контролом
}
}
Как видно из примера, на сервере происходит сложение двух чисел, переданных в клиентский конструктор через параметр arg. Результат записывается в свойство Title, которое может передавать результат на клиентскую сторону в виде Data либо через произвольный HTML элемент. Например, через конструктор удобно передавать идентификаторы либо другие объекты, характеризующие какие-либо сущности, далее загружать необходимые данные на сервере и возвращать их на клиентскую сторону вместе с
Если arg не определен, то произойдет только клиентское создание
Для передачи данных на клиентскую сторону, на сервере можно использовать словарь Data, который есть у каждого $data.
Например, записав при загрузке текущую дату:
protected override void OnLoad()
{
Data["serverTime"] = DateTime.Now;
}
До нее можно с легкостью добраться на клиентской стороне:
{
$init: function() {
alert(this.$data.serverTime);
}
}
Данную методику можно использовать только в момент загрузки
Если на клиентской стороне необходимо получить/отправить данные в произвольный момент, можно воспользоваться удаленным вызовом функции (RPC). Все методы RpcMethodAttribute, можно вызывать удаленно.
Пример таких методов представлен ниже. Остается отметить, что такие методы, по сути, являются методами
public class MyUserControl : UserControl
{
[JsonRpcMethod]
public Person GetPersonById(int personId)
{
// возвращаем Person
}
[JsonRpcMethod]
public void SavePerson(Person person)
{
// сохраняем Person
}
}
Перегрузка функций поддерживается только по количеству параметров. По типу параметров перегрузка не поддерживается. В качестве параметров или возвращаемого значения могут быть произвольные объекты, которые впоследствии будут отформатированы в
в
Для
По умолчанию, HTML разметка копируется от базового <replacement> можно заменять или удалять базовые
<body> <div id="div1">Первоначальный текст </div> </body>
И производная разметка:
<replacement id="div1"> <div id="div2">Переопределенный текст</div> И другой текст </replacement>
При копировании разметки из базового div1 будет подставлена замена из тега replacement с одноименным идентификатором.
При добавлении CSS
{
hi: function() {
alert('Базовый привет!');
}
}
И производного:
{
hi: function() {
alert('Привет!');
BaseFooControl.prototype.call(this);
}
}
Для библиотек, которые поддерживают ClientBaseAttribute:
[ClientBase("Ext.Window")]
public class FooControl : UserControl
{
//....
public FooControl(int fooId)
{
// подгружаем необходимые данные
}
}
Клиентский код:
{
onFooButtonClick: function() {
// Создаем FooControl
// происходит вызов серверного конструктора – в нем можно подгрузить необходимые данные
// и вызов $init – в нем инициализировать окно, подставить загруженные данные
var fooControl = new FooControl({
arg: [1] // параметры конструктора
});
// Показываем окно (метод show наследован из ExtJs)
fooControl.show();
}
// ...
}
Благодаря этому, $. Так, например, удается избежать конфликтов идентификаторов ( id ) или часто распространенных имен функций ( init ).
web.config.
Также необходимо добавить HttpHadler и WebServer Hadler, чтобы
| Название | Описание | Значение в Release | Значение в Debug | Тип |
|---|---|---|---|---|
deployPath |
Путь, относительный от корня сайта, куда "распаковывать" бинарные |
deploy |
deploy |
String |
resourceFilter |
Полное имя класса, который фильтрует все текстовые |
, |
, |
String |
gzipEnabled |
Включен ли GZIP. |
True |
False |
Boolean |
watchResources |
Включено ли слежение за изменением текстовых |
False |
True |
Boolean |
compressJavaScript |
Включено ли сжатие |
True |
False |
Boolean |
clientCaching |
Включена ли отправка HTTP заголовков кэширования. | True |
False |
Boolean |
indentHtml |
Включено ли форматирование HTML. | False |
True |
Boolean |
exceptionFormatter |
Полное имя класса, занимающегося форматирование исключения в |
, |
, |
String |
Параметр resourceFilter определяет класс, экземпляр которого будет заниматься фильтрацией текстовых и переопределять метод Filter(string name, StringBuilder data). Отфильтрованный
Параметр exceptionFormatter используется для указания класса, экземпляр которого форматирует исключение при RPC-вызовах в nHibernate, то это без труда можно сделать, переопределив метод Format класса .
Узнав, что все embedded resource, многие думают, что для вступления в силу изменений в HTML, CSS или в watchResources. Если он установлен в True, то
При работе с
Обмен данными между клиентом и сервером осуществляется асинхронно, как правило, в формате
Существует два подхода к вызовам методов
POST HTTP ;GET HTTP.Основные элементы уровня связи Веб-служб:
WebRequest;WebRequestManager ;XmlHttpExecutor ;Элементы серверной архитектуры
WebRequest;Основным отличием
При загрузке
Для создания .
Для создания .
Экземпляры
Для передачи данных на клиентскую сторону, на сервере можно использовать словарь Data, который есть у каждого
web.config.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.