Как вызвать метод страницы с параметром через событие javascript?

У меня есть такой метод в моем .cs:

[System.Web.Services.WebMethod]
public static void GetServiceInformation(IInfo x) //IInfo  is an interface
{
    x.l_power = true;
    x.lb_InboxCount = UserTrans.GetInbox(int.Parse(emp_num), 0);
}

Теперь я хочу вызвать этот метод с помощью javascript-метода в качестве метода страницы, но он не работает.

<script type ="text/javascript">

    function GetInfo() {
        PageMethods.GetServiceInformation(this);
    }
   window.onload = setTimeout("GetInfo()", 3000);
</script>

  <telerik:RadScriptManager ID="RadScriptManager1" runat="server" EnablePageMethods="true">
  </telerik:RadScriptManager>

My.cs:

 public partial class AppMaster : Log, IInfo //My page
    {
        public string Inbox
        {
            get
            {
                return hpl_Inbox.NavigateUrl;
            }

            set
            {
                hpl_Inbox.NavigateUrl = value;
            }
        }
        public string Draft
        {
            get
            {
                return hpl_Draft.NavigateUrl;
            }

            set
            {
                hpl_Draft.NavigateUrl = value;
            }
        }

        public string New
        {
            get
            {
                return hpl_New.NavigateUrl;
            }
            set
            {
                hpl_New.NavigateUrl = value;
            }
        }
        public string Approved
        {
            get
            {
                return hpl_Approved.NavigateUrl;
            }
            set
            {
                hpl_Approved.NavigateUrl = value;
            }
        }
    //------- etc
 }

Мой интерфейс:

public interface IInfo
    {
        string Inbox { get; set; }
        string Draft { get; set; }
        string New { get; set; }
        string Approved { get; set; }
        string archive { get; set; }
        string search { get; set; }
        string cand { get; set; }
        string pri { get; set; }
        string power { get; set; }
        string admin { get; set; }
        string help { get; set; }
        bool l_cand { get; set; }
        bool l_pri { get; set; }
        bool l_power { get; set; }
        bool l_admin { get; set; }

        string lb_ApprovedCount { get; set; }
        string lb_InboxCount { get; set; }
        string lb_archive { get; set; }
        string lb_DraftCount { get; set; }

    }

Ответы

Ответ 1

Я делаю следующее:

Создайте новую страницу и назовите ее: Counts.aspx

 protected void Page_Load(object sender, EventArgs e)
        {

                        emp_num = int.Parse(Session["empnum"].ToString());
                        Thread.Sleep(3000);
                        string res = GetCounts(emp_num);
                        Response.Write(res);

        }
        /***********************************************************************************************/
        protected string GetCounts(int empNum)
        {

            string outbox = UserTransaction.getoutboxCount(empNum, 0);
            string inbox = UserTransaction.getinboxCount(empNum, 0);
            string archive = UserTransaction.getarchivecount(empNum, 0);
            string draft = UserTransaction.getdraftcount(empNum, 0);
            return outbox + "~" + inbox + "~" + archive + "~" + draft + "~";

        }

и на моей главной странице:

 <script type="text/javascript">

        function loadXMLDoc() {
            var xmlhttp;
            if (window.XMLHttpRequest) {
                xmlhttp = new XMLHttpRequest();
            }
            else {
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
            xmlhttp.onreadystatechange = function() {
                if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                    var split = xmlhttp.responseText.split('~');

                    var outbox = split[0];
                    var inbox = split[1];
                    var archive = split[2];
                    var draft = split[3];
                    document.getElementById("lbl_DraftCount").innerHTML = draft;
                    document.getElementById("lbl_InboxCount").innerHTML = inbox;
                    document.getElementById("lbl_ApprovedCount").innerHTML = outbox;
                    document.getElementById("lbl_archive").innerHTML = archive;
                }
            }
            xmlhttp.open("GET", "Counts.aspx", true);
            xmlhttp.send();
        }
        loadXMLDoc();


    </script>

Ответ 2

Ответ Редактировать на основе обсуждения чата

Во-первых, спасибо за разъяснение вашего вопроса. Было трудно понять проблему, которую вы пытались решить. Причина? Потому что ваш код недостаточно ясен, и это обычно происходит, когда возникают проблемы с дизайном. Это эффективно то, что вы сталкиваетесь здесь с проблемой дизайна. Во-первых, я укажу на некоторые ошибки...

В этой функции javascript...

function GetInfo() {
        PageMethods.GetServiceInformation(this);
    }

this НЕ является экземпляром вашей страницы. Поэтому нет никакой пользы, чтобы ваша страница реализовала интерфейс...

public partial class AppMaster : Log, IInfo{}

и ожидайте, что вызов javascript будет отображать экземпляр System.Web.UI.Page для вашего класса (не говоря уже о реализации интерфейса IInfo). Вы можете слепо отбросить этот подход, потому что это постоянный дизайн, и он даже не собирается работать.

Теперь, если вы хотите обслуживать страницу, затем выполните некоторую дополнительную обработку и, наконец, отправьте результаты этой обработки обратно клиенту асинхронно, используя javascript/ajax, у вас есть несколько подходов здесь:

  • Используя SignalR, который является моим любимым подходом (но вы уже заявили, что ваше решение не соответствует требованиям к использованию SignalR)
  • Использование jQuery ajax, который также является очень действительным подходом

Теперь я объясню второй подход

Использование jQuery Ajax

Просто отрисуйте страницу так, как обычно, в ASP.NET. Затем на клиентской стороне, когда загружается страница, сделайте запрос ajax, чтобы начать обработку информации, которую вы хотите отобразить. Вы можете запустить запрос, как только страница загрузится, чтобы сделать обработку на сервере

$(function(){
    $.ajax({
        type: 'POST',
        url: 'AppMaster.aspx/GetServiceInformation',
        data: "{}",
        contentType: 'application/json;charset=utf-8',
        dataType: 'json',
        success: function(d) {
            //load data received
            },
        error: function() {
            //process the error
            }
    });
});

В обработчике успеха вам нужно загрузить значения, полученные от вызова ajax на веб-элементах управления. Затем измените ваш интерфейс IInfo на конкретный объект в отдельном файле кода. Но помните, что этот класс не должен содержать никаких ссылок на ваши веб-элементы управления.

public class JSInfo
{
    string Inbox { get; set; }
    string Draft { get; set; }
    string New { get; set; }
    string Approved { get; set; }
    string archive { get; set; }
    string search { get; set; }
    string cand { get; set; }
    string pri { get; set; }
    string power { get; set; }
    string admin { get; set; }
    string help { get; set; }
    bool l_cand { get; set; }
    bool l_pri { get; set; }
    bool l_power { get; set; }
    bool l_admin { get; set; }

    string lb_ApprovedCount { get; set; }
    string lb_InboxCount { get; set; }
    string lb_archive { get; set; }
    string lb_DraftCount { get; set; }

}

затем измените способ своей страницы на...

[System.Web.Services.WebMethod]
public static JSInfo GetServiceInformation()
{
    //you need to get the emp_num from session

    //construct the JSInfo object
    JSInfo info = new JSInfo();

    //get the data from the database
    var data = UserTrans.GetInbox(int.Parse(emp_num), 0);

    //set the properties of the JSInfo...similar to the line below for each property...Draft, New, Approved, etc
    info.Inbox = data.Inbox;

    //return the object to the client
    return info;
}

Обратите внимание, что вам нужно получить значение emp_num из Session, так как вы указали в чате, что это значение происходит от переменной Session. Теперь вернемся к обработчику успеха вашего вызова jQuery ajax, который выполняется вскоре после получения ответа с сервера. Вы получите объект json в параметре handler d со свойствами класса JSInfo, который вы только что отправили с сервера. Затем вы установите элементы управления на странице...

success: function(d) {
            $('#id_inbox_control').val(d.Inbox);
            $('#id_draft_control').val(d.Draft);
            $('#id_new_control').val(d.New);

            //and keep doing the same for the rest of the controls
        },

Это должно быть более аккуратное решение. Из coure, я не могу охватить все подробности здесь. Но наверняка вы получите эту идею. Если нет, сообщите мне, нужно ли мне что-то расширять.

Ответ 3

function GetServiceInformation(x) {

    $.ajax({
        type: "POST",
        url: "page.aspx/GetServiceInformation",
        data: "{'x':'" + x + "'}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: on_sucess,
        error: on_error
    });
    function on_sucess(data, status) {

        alert(data);

    }
    function on_error(request, status, error) {

        alert(error);
    }

}

Извините, если он не работает

Ответ 4

Если ваша страница реализует интерфейс, вам не нужно его передавать! В коде С# напишите:

this.l_power=true;

Если вам нужно передать значения из метода JavaScript в страницу, определите каждое свойство как параметр и передайте значения методу страницы:

[System.Web.Services.WebMethod]
public static string GetServiceInformation(int value1, string value2)
{
    l_power = value1;
    something = value2;
    return "some string to indicate the result of call";
}

и

<script type ="text/javascript">
    var v1 = 15;
    var v2 = "some value";
    function GetInfo() {
        PageMethods.GetServiceInformation(v1, v2, success, fail);
    }
   window.onload = setTimeout("GetInfo()", 3000);
</script>

в котором success и fail - это имена двух функций JS, которые будут вызываться после завершения запроса. Обратите внимание, что метод страницы может возвращать строковое значение, чтобы информировать клиента о том, что произошло на сервере.

Ответ 5

Я могу думать только об одном методе.

Вы должны каким-то образом маршалировать объект this и отправить его как параметр. Я хочу сказать, что вы должны написать метод, который объединяет объект с эквивалентным json или xml и POST на ваш сервер.

Я считаю, что вы можете сделать это, как вы делали это, только через чистый API и инструмент компилятора между C# и javascript для реализации RPC, как и для GWT для java и javascript.

Ответ 6

Можете ли вы сделать небольшой тест?

Объявите public class JSInfo: IInfo{} в своем коде страницы и в своем веб-методе объявите этот параметр как JSInfo.

Поскольку JSInfo реализует IInfo, ваша программная логика может без проблем работать с ней.

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

Если вы плохо заполняете объявление JSInfo в классе страницы asp.net, создайте класс, называемый WebMethodsHelper и объявите свои интерфейсы WebMethod JavaScript (адаптеры).

public class JSInfo: IInfo{
    private ControlsCollection controls;

    public JSInfo(ControlsCollection constrols){
        this.controls = controls
        FillObjects();
    }

    private void FillObjects(){
        //iterate through controls and extract you data to you 
        //class properties/fields
    }

    public void Update(ControlsCollection controls){
        this.controls=controls;
        FillObjects();
    }

    public void Update(JSInfo info, ControlsCollection controls){
        this.controls=controls;

        //populate your object based on info

        //then extract data from page controls
        FillObjects();
    }
}


public class MyPage: System.Web.UI.Page{

     protected void Page_Load(object sender, EventArgs e){
          if(!IsPostBack && Session["info_obj"])
               Session["info_obj"] = new JSInfo(this.Controls);
     }

     [System.Web.Services.WebMethod]
     public static string GetServiceInformation(JSInfo data)
     {
         JSInfo info = new JSInfo(this.Controls);
         info.Update(data);

         //or if you stored the info in the session
         JSInfo info = (JSInfo)Session["info_obj"];
         info.Update(this.Controls, data);
     }
}

JSInfo - это просто дать вашему интерфейсу IInfo некоторую структуру, чтобы он мог быть сериализован.

Из JavaScript вы можете позвонить вам следующим способом:

<script type ="text/javascript"> 

function GetInfo() { 
     var info = new JSInfo();
     info.PropertyXPTO="something";

     PageMethods.GetServiceInformation(info, onSuccess, onError);
} 

function onSuccess(result) {
    alert(result);
}

function onError(result) {
    alert('error: ' + result);
}

window.addEventListener("load", function(){
   setTimeout("GetInfo()", 10 * 1000); 
}, false);

</script>

Не нужно, чтобы у вас был ScriptManager в верхней части страницы

<asp:ScriptManager ID="ScriptManager1" EnablePageMethods="true" runat="server" />

ScriptManager несет ответственность за предоставление вам класса PageMethods в JavaScript, вдоль с другими вещами.

Также подтвердите следующее:

  • Метод страницы должен иметь атрибут System.Web.Services.WebMethod. [WebMethod]
  • Метод страницы должен быть общедоступным. [WebMethod] public...
  • Метод страницы должен быть статическим. [WebMethod] public static...
  • Метод страницы должен быть определен на странице (либо в строке, либо в коде). Он не может быть определен на контрольной странице, главной странице или базовой странице.
  • Диспетчер ASP.NET AJAX Script должен иметь значение EnablePageMethods равное true.

Ответ 7

function GetServiceInformation(x) {
$.ajax({
    type: "POST",
    url: "page.aspx/GetServiceInformation",
    data:  x, //Attention: there is no {}
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: on_sucess,
    error: on_error
});
function on_sucess(data, status) {
    alert(data);
}
function on_error(request, status, error) {
    alert(error);
}
}

И затем

<script type ="text/javascript">

function GetInfo() {
var myInfo = {
        Inbox: "",
        Draft: "",
        New: "",
        l_cand: ""
        ......//Attention, you should make this class corresponding to your server class IInfo
    };
    PageMethods.GetServiceInformation(myInfo);
}
window.onload = setTimeout("GetInfo()", 3000);

Относится к @anotherdie. И расскажите, как передать "X"

Ответ 8

В вашем .js

function GetInfo() { 
    var parameter = {};
    parameter.name = "test";
    parameter.id = 123;
    parameter.state = true;

    PageMethods.GetServiceInformation(parameter, 
            function (res) {
                if (res == true) {
                     //do some
                     alert("ok");
                   } else {
                     //do some
                     alert("bad");       
                   }
            }, function(err){
               alert("ERROR: "+err._message);
            });
}

в вашем apsx.cs(вы можете вернуть строку, список, bool, int или json-объект//для json использовать json.net http://james.newtonking.com/json) для этого я верну bool.

using System.Web.Services;

[WebMethod]
public static bool GetServiceInformation(ClassData parameters)
{
  try
  {
    //do some
    return true;
  }    
  catch(Exception ex)
  {
     return false;
  }
}

в интерфейсе ClassData.cs

   public string name { get; set; }
   public int id { get; set; }
   public bool state { get; set; }

   public ClassData(){}

   public ClassData(string _name, int _id, bool _state)
   {
     this.name = _name;
     this.id= _id;
     this.state = _state;
   }