5 Jul 2007

Of ASP.NET Ajax PageMethods and Men

[11 Feb 2010] Since I wrote this, I would use the following method to call PageMethods from JavaScript: http://encosia.com/2008/05/29/using-jquery-to-directly-call-aspnet-ajax-page-methods/





I've been having fun with ad-hoc AJAX calls using ASP.NET Ajax recently. And when I say fun, I mean in the sense of "no fun at all". Partly due to crap documentation and a million blog posts with example code based on obsolete beta Atlas functionality.

So here's a little tipfest about PageMethods.

You can call .NET methods of your ASPX page via client-side Javascript. But first you have to jump through some hoops:

1. The ASP.NET Ajax ScriptManager control in your .aspx or MasterPage needs to be set with: EnablePageMethods="true"

2. The .NET method you wish to expose to AJAX must be public and static and marked with the [System.Web.Services.WebMethod] attribute

Once that's done you can call your method from javascript after the AJAX script libraries have finished loading (with Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded() or something).

So, given a WebMethod like so:
[WebMethod]
public static string HelloWorld()
{
return "Hello World!";
}
You call it in JavaScript with:
PageMethods.HelloWorld(MyCallbackHandler);
And natch you have to provide that callback handler function e.g.
function MyCallbackHandler(Result)
{
alert(Result);
}
That's right my friends, the PageMethod takes the original argument list, plus one extra for the mandatory callback function, and then there are some optional extra callback arguments you can provide regarding error handling etc. Check out the docs for more info.

One extra thing to note - I read a few blogs bitching that the WebMethod had to be declared in the .aspx page, not the code-behind code. That's not true anymore, it works fine both ways.

4 comments:

  1. Zotius
    excellent blog and the code works with one exception: when I put the page into a master page file it ceases working.

    Code is as follows:
    The HTML Page:
    %@ Page Language="C#" MasterPageFile="~/Master/MasterPage.master"AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %

    asp:Content ContentPlaceHolderID="ContentPlaceHolderTop" ID="ContentHolder" runat="server"

    script language="javascript" type="text/javascript"


    // Javascript function
    function CallSum()
    {
    alert("CallSum()");
    //Get the controls
    var txt1 = $get("txt1");
    var txt2 = $get("txt2");
    var txtresult = $get("txtSum");

    //Call server side function
    PageMethods.Sum(txt1.value,txt2.value,OnCallSumComplete,OnCallSumError,txtresult);

    /*Server side function get the 2 arguments arg1 and arg2. We are passing txt1.value and txt2.value
    for that. OnCallSumComplete is callback function for complete successfully. OnCallSumError is callback
    function on error. txtresult is usercontext parameter.

    OnCallSumComplete,OnCallSumError,txtresult are optional parameters.

    If server side code executed successfully then OnCallSumComplete will call.
    If server side code do not executed successfully then OnCallSumError will call.

    */
    alert("CallSum2");
    }

    // Callback function on complete
    // First argument is always "result" if server side code returns void then this value will be null
    // Second argument is usercontext control pass at the time of call
    // Third argument is methodName (server side function name) In this example the methodName will be "Sum"
    function OnCallSumComplete(result,txtresult,methodName)
    {
    alert("OnCallSumComplete()");
    //Show the result in txtresult
    txtresult.value = result;
    }

    // Callback function on error
    // Callback function on complete
    // First argument is always "error" if server side code throws any exception
    // Second argument is usercontext control pass at the time of call
    // Third argument is methodName (server side function name) In this example the methodName will be "Sum"
    function OnCallSumError(error,userContext,methodName)
    {
    alert("OnCallSumError");
    if(error !== null)
    {
    alert(error.get_message());
    }
    }

    // -->
    /script

    body

    div
    table
    tr
    td
    Number1:/td
    td
    asp:TextBox ID="txt1" runat="server" /asp:TextBox
    /td
    /tr
    tr
    td
    Number2:/td
    td
    asp:TextBox ID="txt2" runat="server" /asp:TextBox
    /td
    /tr
    tr
    td
    Sum:/td
    td
    asp:TextBox ID="txtSum" runat="server" /asp:TextBox
    /td
    /tr
    tr
    td
    asp:Button ID="btnSum" runat="server" Text="Sum" OnClientClick="CallSum();return false;" /
    /td
    /tr
    /table
    /div
    /body
    /asp:Content

    my code behind:
    using System;
    using System.Data;
    using System.Configuration;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;

    public partial class _Default : System.Web.UI.Page
    {
    protected void Page_Load(object sender, EventArgs e)
    {
    if (!Page.IsPostBack)
    {
    Page.Title = "test";
    }
    }


    /// summary
    /// Server side function Sum
    /// /summary
    /// param name="arg1" arg1 /param
    /// param name="arg2" arg2 /param
    /// returns result(sum)/returns
    [System.Web.Services.WebMethod]
    public static int Sum(int arg1, int arg2)
    {

    /* On server side we can do any thing. Like we can access the Session.
    * We can do database access operation. Without postback.
    */
    try
    {
    return arg1 + arg2;
    }
    catch(Exception ex)
    {
    throw ex;
    }
    }
    }


    Why does it not work?
    (Ihave had to strip out angle brackets for the post to be allowed)
    Adrian (In Harrogate)

    ReplyDelete
  2. Interesting, I'll check it out at work in the morning. It ought to work cos my current project uses MasterPages and the PageMethods seem to work fine.

    One avenue to consider is your browser's caching of the javascript files that ASP.NET AJAX creates for the PageMethod stubs. Think that caught me out at one point.

    ReplyDelete
  3. Anonymous7:37 am

    how to pass argument to on success function from javascript function ?

    ReplyDelete
  4. How to not get question answered ?

    Besides, I'd do this in jQuery these days, like so: http://encosia.com/2008/05/29/using-jquery-to-directly-call-aspnet-ajax-page-methods/

    ReplyDelete

Comments are very welcome unless you're a spammer, in which case you should probably kill yourself.

If I helped you out today, you can buy me a beer below. Cheers!