Tuesday, April 12, 2011

Calling a code-behind function from javascript

Welcome back to my blog!

As the title of this post says, today I want to share how to call a function or method in the code-behind from javascript, our in other words, run some server side code calling from the client, and then update our web page.

Background


I needed to add some functionality to some aspx pages so they would look more responsive, more like a desktop app. The thing is that I did not want to write the functionality in javascript. I wanted to implement something a little bit complex, but, as I already coded it in code-behind, why to rewrite it in javascript if it is possible to call that function or method from it?

Simple Scenario


Lets imagine the following simple scenario, just with the purpose to show how we can achieve our goal today.
Imagine that we have two text boxes: txtName and txtLastName. We want the user to write his Full Name and then greet him with a message when the last Text Box loses focus.

We could easily do this all in javascript, but remember that it is just for the purpose of demonstrating how to call a server side method from our client side and update our web page.

The code


Ok. Lets add three text boxes to our aspx page:


<asp:TextBox ID="txtName" runat="server"></asp:TextBox>
<asp:TextBox ID="txtLastName" runat="server"></asp:TextBox>
<asp:TextBox ID="txtMsg" runat="server"></asp:TextBox>



Now, inside our body tag lets add some javascript:


<script type="text/javascript">
      
        function greet(txtN, txtLastN, txtMsg){
            var ctrlN = document.getElementById(txtN);
            var ctrlLastN = document.getElementById(txtLastN);

            var fullName = ctrlN.value + '  ' + ctrlLastN.value;
            PageMethods.greetUser(fullName, greetSuccess, greetFailed, txtMsg);
        }

        function greetSuccess(res, txtMsg) {
            var ctrlTxtMsg = document.getElementById(txtMsg);
            ctrlTxtMsg.value = res;
        }

        function greetFailed(res, dst) {
            alert(res.get_message());
        }

</script>


We just created three functions.:

  1. Greet. Receives the ClientId of the txtName, txtLastName and txtMsg textboxes. Then it gets the objects for txtName and txtLastName, concats their value and calls our code-behind function "greetUser". We are passing to that function 4 values: the full name we've got by concatenating txtName and txtLastName values, the function wich will be called if everything goes ok, the function which is going to be called if something failes and we can pass whatever we want in the last parameter, in this case, the ClientId of txtMsg text box.Notice that "greetUser" is our code-behind function and that we are using PageMethods to have access to it.
  2. GreetSuccess is the function that is going to be called if everything went ok. Receives the result of the code-behind function and a parameter: the ClientID of the txtMsg text box, so we can get the object itself and assign to it the result of the code-behind function as its value.
  3. GreetFailed. Receives the same 2 parameters than GreetSuccess. In this case, we are just going to show an alert with the error that happened.
Now, lets see our code behind. First in our Page_Load method we'll add:




If Page.IsPostBack = False Then
            txtLastName.Attributes.Add("onblur", "javascript:greet('" & txtName.ClientID & "','" & txtLastName.ClientID & "','" & txtMsg.ClientID & "')")
End If



Why I'm assigning the attribut "onblur" to our txtLastName text box in our code instead of doing it directly in the aspx page? Just for demonstration.You could add this attribute from the aspx page, but if you had a more complex scenario, lets say a GridView, or a DataList with DataTemplates or if you are creating  controls dynamically... then you could for example get the control you need from code in the GridView_DataBound method or in the function you are creating your dynamic layout, and call the javascript function the way is shown above.

Ok, here comes the important part of the article. The code behind function that we are calling from javascript.

<System.Web.Services.WebMethod()> _
    Public Shared Function greetUser(ByVal fullName As String) As String
        Return "Welcome " & fullName & "!"
    End Function



Please notice that we are giving this function the System.Web.Services.WebMethod attribute, this is the reason why we can access this function from javascript using PageMethods. In this function we are receiving the full name that we got joining the values from txtName and txtLastName in our "greet" javascript function.


Final words


I guess that's it. This was a really simple scenario, but you could think of really complex operations inside a gridview for example, or whatever other situation. As ever, please feel free to leave your comments, questions, suggestions or whatever you want to tell. Thanks for reading!

Hope it helps!

6 comments:

  1. This sounds interesting, but I have trouble getting it to work. When you call greetUser in javascript, you are using 4 parameters. But yet, greetUser in code-behind expects only a string. That is where I am stumped. Thanks.

    ReplyDelete
  2. Hi David! First of all, thanks for reading :)
    I wrote this article exactly a year ago so I had to re-read it to remember. I hope I can provide you with the right answer.
    In the point 1. of the explanation it says:
    "We are passing to that function 4 values: the full name we've got by concatenating txtName and txtLastName values, the function wich will be called if everything goes ok, the function which is going to be called if something failes and we can pass whatever we want in the last parameter"
    In other words, first you would specify the parameters that the code-behind function is expecting (fullname in this case), and then you indicate the javascript functions that you want to be raised when everything went fine, and when there was an error. The last one is like a box where you can put whatever you need to reuse later. In this case we are passing the txtMsg ID so, in the greetSuccess method we can use it to show the result of the code-behind function in that text box.

    I hope I made it clear now. If you need more answers or help with your code just comment again or feel free to contact me.

    Best Regards!

    ReplyDelete
  3. You didn't really answer his question. Why do you pass four paramaters if the code-behind method only uses one. If I were to call any method in code-behind from another method in code-behind using the wrong number of parameters, it would throw an error - the code would not even compile. Please explain. By the way I have programming, especially in VB.

    ReplyDelete
  4. This comment has been removed by the author.

    ReplyDelete
  5. you may have forgotten to add scriptmanger with enablePageMethods= true to aspx for above to work

    good article, keep up the good work !

    "

    ReplyDelete
  6. Thanks Chula for the contribution :)

    ReplyDelete