How to call page method with a parameter through in a javascript event?
Asked Answered
I

8

16

I have method like this in my .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);
}

Now i want to call this method through a javascript method as a page method but it doesn't work .

<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
 }

My interface :

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; }

    }
Inaccessible answered 29/12, 2013 at 10:26 Comment(11)
So you want call server side code through client side? O.oValli
@antindexer : yeah , this's a special needInaccessible
You are passing this to the page method in JavaScript. While you have an interface in your C# code. This can not be achieved this way. Tell us more about what you are trying to do, so we can help.Urdar
@Urdar : i have some controls and i i set those controls through the interface , my page implement the interface public partial class AppMaster : Log, IInfo i want to pass the interface so i can set the properties in itInaccessible
GetServiceInformation(IInfo x) should be GetServiceInformation(object x),then js function will call page methodHeartbreaker
@just_name please give it a look at my answer. thanksJuryman
@JoãoPinho :please take a look at my question again , i revise it so u could understand what i mean , i want to pass this the current object of my page AppMaster so i could set some controls in that page after the page loadInaccessible
this question is crazy. Why do you need Page Methods and ajax to set the controls? Can't you just set the control from javascript? What controls are you trying to set? And why? Can you give a bit of a context to your question instead of showing some crazy code that's obviously reinventing the wheel?Housemaster
@Leo:i'm not trying to invent the wheel . what i want to do is setting some controls (labels , hyperlinks ...etc) wiz values comes from server side after the page load because those calculations take a lot of time so i don't want the user to wait those analytical values , i want them rendered after the page load event in the background , so i try to use ajax to do what i want , if u have any ideas instead of being nervous , i'll be grateful :)Inaccessible
@just_name sorry, don't get it the wrong way...I'm just trying to squeeze out some information from you because it's still not clear to me why you have gone that way in your implementation. It's quite messy (in a constructive tone). I'll suggest a few approaches you can follow in an answer...Housemaster
@Housemaster : U are welcome , if u have any ideas to render some server side values of the controls on the page after Page_load() i'll be grateful :)Inaccessible
I
0

I do the following :

Create New Page and called it : 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 + "~";

        }

and in my main page :

 <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>
Inaccessible answered 16/1, 2014 at 13:7 Comment(0)
X
6
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);
    }

}

Sorry, if it doesn't work

Xochitlxp answered 7/1, 2014 at 4:58 Comment(4)
How to call this method GetServiceInformation(x) ?? and what should i pass to the x paramInaccessible
you can call function GetServiceInformation(x) by javascript and you can send parameter x and recieve x in behind codeXochitlxp
Could u check the question again please , i want to do that because i want to set some controls on the page after the pageload say 2s after the page loadInaccessible
u can't set control in web method, if u want to set control u can set it in the function on_sucess and use jquery or javascript.Xochitlxp
H
6

Answer Edit Based On Chat Discussion

First, thanks for clarifying your question. It was bit hard to understand the problem you were trying to solve. The reason? Because your code wasn't clear enough and that usually happens when there are design issues. That's effectively what your facing here a bit of a design issue. First, I'll point out some mistakes...

In this javascript function...

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

this is NOT an instance of your page. So there's no use to make your page implement an interface...

public partial class AppMaster : Log, IInfo{}

and expect that a javascript call would page an instance of System.Web.UI.Page to your class (not to mention an implementation of the IInfo interface). You can blindly ditch this approach because it's a permanent design issue and it's not even going to work.

Now, if what you want is to serve the page, then do some further processing and finally send the results of this processing back to the client asynchronously using javascript/ajax you have a couple of approaches here:

  1. Using SignalR which is my favourite approach (but you already stated your solution doesn't meet the requirements to use SignalR)
  2. Using jQuery ajax which is also a very valid approach

Now, I'll explain the second approach

Using jQuery Ajax

Simply render the page as you would normally do in ASP.NET. Then on the client-side, when the page loads, make an ajax request to start processing the information you want to display. You can start the request as soon as the page loads to make the processing on the server

$(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
            }
    });
});

In the success handler you need to load the values received from the ajax call on your web controls. Then change your IInfo interface to a concrete object in a separate code file. But, remember that this class should NOT hold any references whatsoever to your web controls

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; }

}

then change your page method to...

[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;
}

Notice that you need to get the emp_num value from Session since you stated in the chat discussion that this value comes from a Session variable. Now, going back to the success handler of your jQuery ajax call which executes soon after the response is received back from the server. You will receive a json object in the handler parameter d with the properties of the JSInfo class that you just sent from the server. Then you set the controls on the page...

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
        },

That should be a neater solution. Of coure, I cannot cover every single details here. But for sure you will get the idea. If not, let me know if I need to expand on something.

Housemaster answered 14/1, 2014 at 8:54 Comment(21)
Firstly : thank u so much for your great explanation.i think i can't use SignalR cuz i use framework 3.5 (visual studio 2008). So i try the second long way ,and plz could i ask u if i face any problem ?Inaccessible
Definitely...feel free to askHousemaster
change your IInfo interface to a concrete object what do y mean by this ? did u mean that i have to change it to a class rather than interface ?Inaccessible
Yes, change to a class so that the underlying serializer can easily serialize the object without further efforts on your partHousemaster
ok should this class be in the same class page (in this case cuz it's nested it will be static autonatically) or out of my page class ,and in this case i'll not able to access my controls through . should this class to be like interface just definitions or with implementation like what exist in my question ?Inaccessible
No, don't do that. Define it as a public class outside of your page. This class should be as simple as possible, with automatic properties and it should NOT hold any reference to your any web controls. This does NOT need to access your web controls. Do you understand that?Housemaster
Good i create my class and create my server side method GetServiceInformation(JSInfo x). but i don't understand the following function function getInboxInfo() how this method will set the controls ,and success: should i call the JSON method ?? this point need more clarification pleaseInaccessible
I don't understand what do u mean by jsonObj["Inbox"] = $('selector').val(); How can u read values from controls which are not set yet?!Inaccessible
let us continue this discussion in chatHousemaster
How can u read values from controls which are not set yet?! that's exactly what you are doing in your question!!! Can you actually state what exactly it is that you want? Right now, you're just all over the place!!!!Housemaster
I debug the code and i find the web method returning the required data , but after that the labels still empty !! Does they lose their values !?Inaccessible
what are you doing in the success handler?Housemaster
As u write : success: function(d) { $('#lbl_InboxCount').val(d.lb_InboxCount); //and keep doing the same for the rest of the controls },Inaccessible
you're kidding me, aint you? Have you got brain damage or what?Housemaster
I can't believe how much time I have wastedHousemaster
Never mind, I give up...read some tutorials mate and stop wasting people's time here. You can't assume anyone is going to write the whole project for youHousemaster
This 's the first time i use page method , i'm sorry for wasting your time . anyway thank u so much for your help .Inaccessible
U don't need to hurt me ,I appreciate your help, and really thank u so much , i read some articles right now about how to call page method using jquery to fix my problem .Inaccessible
Seriously, you already have that working...i recommend you to read a tutorial about jQuery. I'm glad I could help but you have to realize that none of us can guide you an entire solution here for obvious reasonsHousemaster
I try to alert (d.lb_InboxCount) but undefinedInaccessible
Thanks for your effort :) although i still don't know what the wrong i have made .Inaccessible
U
3

If your page implements the interface, you don't have to pass it! In your c# code write:

this.l_power=true;

If you need to pass values from JavaScript to page method, define each property as a parameter and pass values to the page method:

[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";
}

And:

<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>

in which success and fail are the names of two JS functions that will be called after the request is completed. Note that a page method can return a string value to inform the client about what happened on the server.

Urdar answered 29/12, 2013 at 11:26 Comment(3)
Thanks but i want to pass the current instance instead of variable cuz some properties i set like this in my method info.lb_DraftCount = TransDAL.Draft_Count(int.Parse(emp_num), 0);Inaccessible
It's a static method. You can't use this.Inexpungible
@JohnSaunders Thanks. My mistake. Again, I insist that it can not be done this way. He should take another approach.Urdar
U
2

I can only think of one method.

You should somehow marshal the this object, and send it as parameter. I mean you should write a method that marshalls an object to equivalent json or xml, and POST that to your server.

I believe you can do it as you did above only through a clean API and compiler tool between C# and javascript to implement RPC just like GWT was written for java and javascript.

Uel answered 6/1, 2014 at 8:6 Comment(0)
Q
2

Can you do a little test?

Declare a public class JSInfo: IInfo{} in your page code, and in your web method declare that parameter of yours as JSInfo.

As JSInfo implements IInfo, your program logic can work with it without any problem.

Just to let you know, your code does not work because you cannot serialize interfaces as they are not concrete types, if you think about it, interfaces have no real correlation in XML schema. There's no way to represent the data. Base classes will work however.

If you fill bad in declaring the JSInfo in the asp.net page class, then create a class called WebMethodsHelper and declare your JavaScript WebMethod Interfaces (Adaptors) there.

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);
     }
}

The JSInfo is just to give your IInfo interface some structure so it can be serialized.

From JavaScript you should be able to call you page method like this:

<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>

Not that you should have a ScriptManager at the top of your page

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

The ScriptManager is responsible for giving you the PageMethods class in the JavaScript, along with other things.

Also, confirm the following:

  • The page method must have the System.Web.Services.WebMethod attribute. [WebMethod]
  • The page method must be public. [WebMethod] public ...
  • The page method must be static. [WebMethod] public static ...
  • The page method must be defined on the page (either inline or in the code-behind). It cannot be defined in a control, master page, or base page.
  • The ASP.NET AJAX Script Manager must have EnablePageMethods set to true.
Quote answered 6/1, 2014 at 15:27 Comment(12)
I do this <script type ="text/javascript"> function GetInfo() { var info = this; PageMethods.GetServiceInformation(info, onSucess); } function onSucess(result) { alert(result); } window.onload = setTimeout("GetInfo()", 3000); </script> but i get javascript error too much recursion errorInaccessible
@just_name Please check my answer again... if you got any error, report them back to me, here. Thanks.Juryman
The problem i can't implement the interface in your class,because i set controls like this: public string Inbox { get { return hpl_Inbox.NavigateUrl;//hyper link } set { hpl_Inbox.NavigateUrl = value; } } So i implement the interface in the same page public partial class AppMaster : Log, IInfo //My page I can't implement the interface in your class public class JSInfo: IInfo{} cuz i have to implement controls in the page can't be accessed through that classInaccessible
Get the following error : Cannot access a non-static member of outer type 'AppMaster' via nested type 'AppMaster.JSInfo'Inaccessible
Is the JSInfo declared public class? If so, this is odd, but create a class inheriting from interface IInfo (and delete that inner class) and try it again. Maybe the compiler is complaining about the inner class, super odd.Juryman
yeah in c# nested classes are static by default :( https://mcmap.net/q/152274/-nested-type-problemInaccessible
where to put this class , i wanna this class to access my controls on the page.Inaccessible
You can put it anywhere, just create a class .cs with the name JSInfo inheriting from IInfo a store this type of classes inside a Folder called 'JScriptAdapters', or something you like that make logic in your project.Juryman
I have to put this class in the same page class,cuz i want to access some controls like (labels, links) on the page !!Inaccessible
Why don't you initialize the class with Controls Collection of the page then?Juryman
I did you a little example explaining what I meant.Juryman
ControlsCollection unknown !! what's the name space , i can't use the following name space using System.Web.UI.ControlCollection. my framework is 3.5Inaccessible
H
2
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);
}
}

And then

<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);

Referred to @anotherdie. And tell you how to transfer "X"

Howe answered 15/1, 2014 at 4:18 Comment(0)
L
2

In your .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);
            });
}

in your apsx.cs (you can return a string, a list, a bool, an int or a json object //for json use json.net http://james.newtonking.com/json) for this i'll return a bool.

using System.Web.Services;

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

in a interface 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;
   }
Libration answered 15/1, 2014 at 18:34 Comment(0)
I
0

I do the following :

Create New Page and called it : 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 + "~";

        }

and in my main page :

 <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>
Inaccessible answered 16/1, 2014 at 13:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.