Разработка электроники,

Систем автоматики,

Программного обеспечения

8(981)186-50-82

ООО "Антех ПСБ",
Санкт-Петербург

anteh@bk.ru

antehru@gmail.com

©

Некоторые AJAX способы вызова ASP.NET C# метода серверного контрола управления из .js скрипта клиентской стороны с передачей параметров. VS2008

Сайт https://anteh.ru

1. [System.Web.Services.WebMethod]

2. Интерфейс IHttpHandler

3. Интерфейс System.Web.UI.IcallbackEventHandler

4. Интерфейс System.Web.UI.IcallbackEventHandler для контрола унаследованного от GridView

Нашёлся только один способ обмена данными между клиентской стороной(web страницей) и контролом расположенным на серверной стороне страницы. Т.е. обмен данными производится не со страницей, а с серверным контролом, расположенном на странице.
Под контролом здесь подразумевается серверный элемент управления.

Приведено 3 случая вызова методов серверной стороны:
1.[System.Web.Services.WebMethod] -вызов методов серверной стороны с клиентской страницы. Прост в реализации. Через POST можно передать любые данные в любом объёме.
2.IHttpHandler -вызов методов серверной стороны с клиентской страницы. Работает быстрее 1го метода. Через POST позволяет передавать любые данные в любом объёме.
3.IcallbackEventHandler позволяет осуществлять обмен данных не только между клиентской и серверной сторонами страницы, но и между клиентской стороной и контролом серверной стороны, размещённом на странице. Используется XmlHTTP. По непроверенным данным позволяет передавать только текстовую информацию, но тут как говориться было бы желание.
Есть и другие способы реализации ajax обмена данными между страницей и сервером. TestICBEH.rar -архив проекта примера для IcallbackEventHandler.

Рассмотрим передачу данных .js скриптом клиентской страницы в серверное представление страницы: 2способа. И в серверный контрол управления, размещённый на странице: 1способ. Главная задумка в том, чтобы данные передавать в сам серверный контрол управления, размещённый на серверной стороне страницы, а не на серверное представление страницы. Страница создана в VS2008 как web приложение, создано два проекта серверных контролов управления, несколько контролов размещено на странице. Данные со страницы на сервер и обратно передаются по клику на каждый из элементов управления.

Рассмотрим передачу данных на серверное представление страницы, содержащее контрол. Рассмотрено 2 способа: через [System.Web.Services.WebMethod] и интерфейс IHttpHandler. Разумеется есть и другие. Если коротко, то через IHttpHandler быстрее, через [WebMethod] проще, но в сам контрол этими методами данные передать не получится. В контрол можно передать данные через реализацию интерфейса ICallbackEventHandler.
Ссылки на источник с примерами и описанием ICallbackEventHandler webform_docallback:
http://www.intuit.ru/department/se/aspdotnet/18/4.html

[System.Web.Services.WebMethod]


1.На странице должен присутствовать ScriptManager. В текущем случае это ToolkitScriptManager. В его свойствах параметр EnablePageMethods нужно установить в true. Этим разрешается вызов методов страницы расположенных на серверной стороне, помеченных атрибутом [WebMethod]. В reference нужно добавить System.Web.Services и соответственно using System.Web.Services; или использовать [System.Web.Services.WebMethod]. На скриншоте часть визуального редактора.
1

Пробовал работоспособность без установки EnablePageMethods -работало.
2. Код .cs. Создаём на серверной стороне статический метод расположенный в классе, описывающем страницу, в текущем случае содержащую контрол/лы. Метод должен быть статическим. Метод помечаем атрибутом [System.Web.Services.WebMethod]:

… 
public partial class WebForm2 : System.Web.UI.Page //страница содержащая контролы
{
    [System.Web.Services.WebMethod]
    public static string GetSome(string param1, string param2) //принимающий, обрабатывающий и отправляющий обратно данные метод
    {
        return "S= " + param1 + " " + param2 + " =S";
    }
…


3.Код .js файл:

…
кнопка.click(function() //
{    
    $.ajax({    //Передаём введённые данные на сервер и получаем ответ
        type: "POST",
        url: window.location.href + '/GetSome', //url: адрес текущей страницы / имя статического метода на стороне сервера
        data: "{'param1': 'Fp1', 'param2': 'Sp2'}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        async: true, cache: false,
        success: function(data, textStatus, XHR)
        {
            alert('stat: ' + textStatus + ' d: ' + data.d + ' xhr: ' + XHR);
        }                            
    });
    return false;
});
…


Результат, после нажатия клиентской кнопки следующий:2

Передали данные на серверную сторону, данные были обработаны, возвращены клиентской странице и отображены в сообщении. Всё как и должно быть.


Интерфейс IHttpHandler

Случай обмена данными между DOM элементом страницы и сервером посредством IHttpHandler POST. Данные серверного элемента управления(контрола) расположенного на странице, передаются на серверную сторону представления страницы, содержащую контрол, а не в сам контрол.

1.Создаём файл .ashx -добавляем к проекту Generic Handler. В текущем случае, прямо в корень проекта web-приложения.3

2.Принимаем POST запросы, парсим в HashTable, формируем и передаём ответное сообщение. Файл *.ashx редактированию не подлежит. В нём находится единственная строка: "<%@ WebHandler Language="C#" CodeBehind="HandlerEGV.ashx.cs" Class="Monitor12.HandlerEGV" %>" Содержимое *.ashx.cs файла:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Script.Serialization;
using System.Collections;
namespace Monitor12
{
    public class DataInOut
    {
        public int Id { get; set; }
        public string Data1 { get; set; }
        public string Data2 { get; set; }
    }   
    public class HandlerEGV : IHttpHandler
    {
        private DataInOut GetData(int Id) //Id -здесь это некоторый условный параметр, по которому определяем характер ответа. В текущем случае, конечно никакой фактической обработки не производится, а произвольно придуманные строки сразу отправляются как ответ на страницу клиента
        {
            var datainout = new DataInOut();
            datainout.Id = Id; //Принятая от DOM элемента информация через $.ajax({...});
            //Некоторые действия с принятыми данными и формирование ответных полей данных
            datainout.Data1 = "Dat_aa"; //Сформированная в ответ информация
            datainout.Data2 = "Dat_bb"; //Сформированная в ответ информация
            return datainout;
        }
        public void ProcessRequest(HttpContext context)
        {
            System.IO.StreamReader reader = new System.IO.StreamReader(context.Request.InputStream);
            string requestFromPost = reader.ReadToEnd();
            //Сейчас requestFromPost = "Id=10009&tst=ttss&empty="
            //Пускай осуществляется обмен только текстовыми данными
            //Создаём HashTable, где ключ = json пришедший ключ, data = json пришедшие данные. Если ключи дублируются, то такая пара игнорируется
            char[] c1 = new char[] { '&' }; char[] c2 = new char[] { '=' };
            Hashtable ht = new Hashtable(); string[] buf = null;
            string[] parms = requestFromPost.Split(c1, StringSplitOptions.RemoveEmptyEntries);
            foreach (string s in parms)
            {
                buf = s.Split(c2); if (buf.Length < 2) { continue; }
                if (!ht.ContainsKey(buf[0])) ht.Add(buf[0], buf[1]); //На всякий, значения с повторяющимися ключами пропускаем. Проверял, пары, с повторяющимися ключами через POST не передаются:
                //.js файл $.ajax({}); запрос: data: { 'Id': '10009', 'tst': 'ttss', 'empty': '', 'tst': 'ttss', 'tst2': 'ttss' }, //Данные, передаваемые на серверную сторону
                //На сервере приняли: "Id=10009&tst=ttss&empty=&tst2=ttss" Т.е. повторная пару 'tst': 'ttss' была где-то отфильтрованна
            }
            //GetData -функция, в которой обрабатывается принятый запрос и формируется ответное сообщение, для отправки на страницу
            DataInOut dio = GetData(Convert.ToInt32((ht["Id"]).ToString())); //Обрабатываем принятые данные и формируем ответное сообщение            
            JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
            string serdio = javaScriptSerializer.Serialize(dio);
            context.Response.ContentType = "text/html";
            context.Response.Write(serdio);
            //serdio так выглядит ответное сообщение от сервера, передаваемое обратно на страницу, сделавшую запрос
            //{"Id":10009,"Data1":"Dat aa","Data2":"Dat bb"}
        }
        //если IsReusable = true, то объект хенделра будет повторно использоваться при последующих запросах. Заново, при каждом запросе создаваться не будет.
        public bool IsReusable { get { return true; } } //MSDN: Возвращает значение, позволяющее определить, может ли другой запрос использовать экземпляр класса
    }
}

3.Код .js файл. По нажатию на кнопку производится передача данных на сервер, обработка и последующий приём, с выводом сообщения.

кнопка.click(function() //
{
    $.ajax({
        type: "POST",
        cache: false,   //параметр запрета кэширования нужно установить
        async: true,
        url: "HandlerEGV.ashx", //Handler(папка)/MyHandler.ashx(файл)
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        data: { 'Id': '10009', 'tst': 'ttss', 'empty': '', 'tst': 'ttss', 'tst2': 'ttss' }, //Данные, передаваемые на серверную сторону
        responseType: "json",
        success: function(data, textStatus, XHR) //
        {
            //Отображаем принятые данные
            alert('status: ' + textStatus + '   / Data1: ' + data.Data1 + ' Data2: ' + data.Data2 + '   / xhr: ' + XHR);
        },
        error: function() //
        {
            alert("Status Error");
        }
    });
    return false;
});

Ответное сообщение на запрос с сервера, после нажатия кнопки:4

Интерфейс System.Web.UI.IcallbackEventHandler

Передача данных с клиентской страницы на серверную сторону и обратно посредством реализации интерфейса IcallbackEventHandler для создаваемого контрола.

TestICBEH.rar -архив проекта примера для IcallbackEventHandler.

Скриншот тестового примера для интерфейса IcallbackEventHandler. Содержит 3 статически размещённых, через визуальный редактор, кнопки-расширенных серверных контролов, серверный контрол унаследованный от GridView и 2 динамически созданные через jQuery кнопки. Клик по каждому из элементов приводит к передаче данных на сервер, обработку, возврат результата обратно на страницу и отображение в диалоговом окне.88


Нужно осуществить следующее: разрабатываем серверный контрол управления. Есть несколько одинаковых контроллов размещённых на странице. Пускай контролом будет кнопка, функциональность которой расширяем. Кнопка динамически создаваемая в контроле. Нужно, чтобы по нажатию на динамически созданную кнопку контрола на сервер передавались некоторые данные, обрабатывались, и возвращались обратно в клиентское представление контрола.
Рассмотрим последовательность действий.
Пускай интерфейс IScriptControl и всё, что к нему полагается уже реализованно. Подключаем интерфейс IcallbackEventHandler. public class tbutt : Button, IScriptControl, ICallbackEventHandler
1.При загрузке страницы, в методе onload контрола на серверной стороне, через Page.ClientScript.GetCallbackEventReference формируется WebForm_DoCallback прототип функции, содержимое в cbReference. Далее в ручную создаём скрипт cbScript. Он описывает функцию UseCallback, вызывающую WebForm_DoCallback для осуществления обратной передачи. Далее регистрируется программно созданный скрипт UseCallback функции.

protected override void OnLoad(EventArgs e)
{
    this.Attributes.Add("onclick", "return false"); //Отключаем штатный PostBack у текущего контрола-кнопки
    this.Attributes.Add("a6sSm1z", ""); //Уникальный идентификатор, присвоенный текущему контролу. Для выделения в .js всех таких же контролов, находящихся на странице
    //Cоздаём функцию, которая будет управлять запросами и ответами на стороне клиента
    string cbReference = Page.ClientScript.GetCallbackEventReference(this, "arg", "ProcessResult", "context"); //ProcessResult -функция зарегистрирована в качестве получателя результата на стороне клиента .js скрипт
    string cbScript = "function UseCallback(arg, context)" + "{" + cbReference + ";" + "}"; //UseCallback -функция инициирующая процесс обратной передачи на сервер данных. Запускается из .js скрипта, например по нажатию кнопки
    Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "UseCallback", cbScript, true); //регистрируем скрипт UseCallback только что созданной функции
    base.OnLoad(e);
}

2.Реализуем 2 функции интерфейса IcallbackEventHandler:

string returnstring = string.Empty;
string ICallbackEventHandler.GetCallbackResult() //возвращает результат клиентскому скрипту, в данном случае
{
    return returnstring;
}
void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument) //позволяет получить со страницы данные, но только строкового типа
{
    //Что-нибудь делаем с принятыми параметрами
    returnstring = eventArgument + " Clock: " + DateTime.Now.ToString();
}

3.В .js файл добавляем следующее:

/// <reference path="jquery-1.9.0-vsdoc.js" />
function ProcessResult(result, context) //Функция принимает ответное сообщение от сервера
{
    alert('ServerAnswer: ' + result);
}
$(document).ready(function() //
{
    //Всем существующим на странице контролам-кнопкам назначаем дополнительную функциональность
    //Каждому элементу-контролу, с атрибутом a6sSm1z назначаем некоторые свойства
    $(this).find('input[a6sSm1z]').each(function() //a6sSm1z -уникальный аттрибут, в текущем случае присвоенный каждой кнопке-контролу. Присвоение производится в onload.
    {
        $(this).click(function() //this -в этой области видимости это разрабатываемый контрол
        {
            $('#' + this.id).css({ 'background-color': 'red' }); //Во время нажатия кнопка подсвечивается красным
            UseCallback('StaticButton id=' + this.id + ' ', 'Ucontext'); //Функция, инициирующая обратный вызов
        });
        //alert('id: ' + this.id);
    });
    //Создаём динамическую кнопку
    var inbtn = $(document.createElement("input")).attr({ name: 'inputIMEIbutton', value: 'dynamic jQuery button', type: 'button' });
    inbtn.click(function() //
    {
        //alert("dynamic jQuery button");
        UseCallback('DynamicButton id=' + this.id + ' ', 'Ucontext'); //Функция, инициирующая обратный вызов
    });
    $(document.body).after(inbtn); //Добавляем динамически созданную кнопку на страницу, в конец
});

Здесь: самая верхняя строчка -для работы jQuery intellisence. ProcessResult -функция принимающаяя ответное сообщение от сервера как результат клика по кнопке. UseCallback -та самая функция, формируемая программно в 1. Функция принимает 2 аргумента первый передаваемый на сервер содержит все нужные агрументы, разделённые например '&' для последующего разбора на серверной стороне. Здесь разделение не использовалось. Второй аргумент в текущем случае просто присутствует и нигде не обрабатывается.
В общем процесс выглядит так: по клику на кнопку запускается функция UseCallback, .js скрипт, содержащая первым аргументом передаваемые на сервер данные. Функция контрола-кнопки RaiseCallbackEvent на серверной стороне, принимает данные. Затем добавляет текущее системное время к принятому аргументу. Затем автоматически запускается GetCallbackResult передающая результат клиентскому представлению контрола в .js скрипт -функцию ProcessResult. Функция ProcessResult выводит результат на экран, в виде сообщения с веб-страницы. В проекте реализованы 5 кнопок 3 статических, созданных в визуальном редакторе и 2 динамическая, создаваемая динамически через jQuery.
Реализация текущего проекта VS2008 Framework 3.5.
Скриншоты кликов по статической и динамической кнопкам:5 6

Интерфейс System.Web.UI.IcallbackEventHandler для контрола унаследованного от GridView

В общем предполагал, будут нюансы при реализации IcallbackEventHandler для GridView. Нюансов не было, всё так же, разве пришлось реализовывать ObjectDataSource для GridView -взят кусок кода из другого проекта. Проект в прикреплённом файле.
Скриншот клика по таблице:7

Copyright ©Новиков Алексей Александрович,

2012-2017 Санкт-Петербург, 197372, ООО "Антех ПСБ",

anteh собака bk.ru