23 October 2007

Calling ASMX web services directly from javascript

The AJAX hype is all around us, and Microsoft provided us with the very neat ASP.NET AJAX extensions and the control toolkit to make things easier. The UpdatePanel and its nephews enjoy a lot of time in the spotlight. The workhorse in the background that makes this all possible can also be used 'raw' - that is, you can call web services directly from javascript utilizing the standard structure of ASP.NET Ajax. It is a very efficient way to transfer data to and from the browser because the server transforms it into JSON - so no large chunks of verbose XML are send through the wire and you don't have to write elaborate pieces of XML-parsing javascript.
Follow the steps below to get things up and running.

This example assumes you have ASP.NET Ajax and de Web Applications already installed.

1. Create a new project of type "ASP.NET AJAX-Enabled Web Application"
This will create a new Web Application with a Default.aspx that already has a script manager on in, and a preconfigured web.config. Call this project WebServiceDemo

2. Add a web service
Right-click on your web application, click Add/New Item and then Web Service. Call this web service "DemoService".

3. Make a web service callable from script
Open code file "Default.aspx.cs". Notice your class "DemoService" sits in a namespace "WebServiceDemo". You will need this knowlegde later.
Add to the top:

using System.Web.Script.Services;
decorate the class with the attribute [ScriptService] and modify the standard hello world method so it looks like this:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
[ScriptService]
public class DemoService : System.Web.Services.WebService
{
[WebMethod]
public string HelloWorld( string ToSomeone )
{
return "Hello World" + ToSomeone;
}
}
4. Register the service on the page where you want to call it from
Open Default.aspx in design view and select the ScriptManager1
Select the "Services" property, and click the button that appears
Click "Add", and enter "DemoService.asmx" for the path property
Click OK. The result should look like this:
<asp:ScriptManager ID="ScriptManager1" runat="server" >
  <Services>
    <asp:ServiceReference Path="DemoService.asmx" />
  </Services>
</asp:ScriptManager>
5. Create a client side script to perform the call
Open Default.aspx in source view and enter just before the <head> tag the following code:

<script type="text/javascript">
function CallService()
{
WebServiceDemo.DemoService.HelloWorld( "Yourself",
Callback );
}

function Callback( result )
{
var outDiv = document.getElementById("outputDiv");
outDiv.innerText = result;
}
</script>
6. Create a button to start the web service calling function
Drag a button onto the form
Set the property "OnClientClick" to "CallService();return false;"

7. Create div for the output data
Drag a div (from the HTML tab) onto the form.
Set its id to "outputDiv";

If you did everything correctly, the text "Hello World Yourself" should appear beneath your button, without a visible postback.

Notice the following things:

  • You always need the fully qualified name of the class to call the webservice: WebServiceDemo.DemoService.HelloWorld
  • Calling a webservice from javascript always needs two methods: one to make the actual call, and one to receive the results
  • The callback method is added as an extra parameter to the web service method parameters. In C#, the method has one parameter, so in javascript two.
This sample gives a nice under-the-hood sample of how ASP.NET Ajax transfers data to and from the browser.

Complete code downloadable here.

20 comments:

  1. That's great! Now how can I do this in a user control(ascx file)?
    I tried it, but the in the user control, intellisense does not pick up the webservice (as it would in a regular aspx page). I registered the service with script manager and decorated it with the script services tag, so help me god!

    ReplyDelete
  2. Hello:

    it seems a if the Callback function is not being called. (no message box is shown). Here's my script:


    function logoutCurrentUser()
    {
    if (event.clientY < 0)
    {
    Authentication.LogoutCurrentUser(Callback);
    }
    }
    function Callback(result)
    {
    alert(result);
    }


    onbeforeunload="logoutCurrentUser()"

    ReplyDelete
  3. @joseph @anonymous: you might want to be more specific.

    ReplyDelete
  4. How to call a WebService when using "Web Site Project" and service's .asmx file is part of the same project?

    ReplyDelete
  5. @George: the same way as when using a web application, I guess. Maybe you want to specify a full path, starting with a "~"?

    ReplyDelete
  6. Excellent demo -- thanks a lot! Simple yet comprehensive. Just a quick note about a couple of typos elsewhere in the page: "(and apperantly and avarage of some 90 people per day do)" should read "(and apparently some 90 people per day do on average)". (Feel free to edit this bit out of my comment once you've fixed it!)

    ReplyDelete
  7. When you say 'Open code file "Default.aspx.cs"', you mean to say 'open demoservice.asmx.vb'

    ReplyDelete
  8. @zhi in all my samples I use C#. If you use visual basic, the code behind file will indeed be called demoservice.asmx.vb

    ReplyDelete
  9. Thank you so much... i just spent the last hour pulling my hair out trying to figure out why it wasn't working until i found this article and realized i needed the scriptmanager to initialize it.

    ReplyDelete
  10. Hi, this code works if i have the javascript code in an usercontrol???

    Thanks in advance

    ReplyDelete
  11. @Gera I think it should. Can't think of a reason why it should not.

    ReplyDelete
  12. What if the webservice is developed and hosted by thirdparty? as you said we have to add [ScriptService] tag, we can't do in our case.

    Please advise.

    ReplyDelete
  13. @Rupen: I think you will need to provide a proxy for that. Unless you have control over the remote server, than you might try fiddling with a crossdomain.xml but I don't know if that will work

    ReplyDelete
  14. Hi, I didn't get putting proxy if possible please explained (or any link), secondly, what about creating my own WCF service which will call ASMX web service?

    ReplyDelete
  15. @Rupen, that is exactly what I mean with a proxy - create a WCF service in your own site, that calls the ASMX service in the other site. I don't have any samples of that, sorry

    ReplyDelete
  16. very nice explanation


    Thank allot for in time help :)

    But please disable that comment moderation. It gives so much irritation for posting comment

    ReplyDelete
  17. @PURNA I completely agree with your comment on the comment moderation and captcha - but I suggest you try to run a blog that get moderate attention and weed out a ginormous amount of Chinese and p*rn spam link comments every single day ;-)

    ReplyDelete
  18. Hi,
    its not working in me. i have downloaded your code and run it. when i clicked on the button nothing happens. am i doing any wrong? i can't understand. plz help me to run it. i am a newbie in webservice related work.


    thanks with regards.
    Razib

    ReplyDelete
  19. @Razib, this is very old code. I'd suggest you look at my wcf post. Maybe that works better for you.

    ReplyDelete
  20. I am using Visual Studio 2010 and it has no project of type "ASP.NET AJAX-Enabled Web Application". I'll try to figure out what to do instead but if anyone has gone down this path already an answer would save me some time. TIA.

    ReplyDelete

Note: Only a member of this blog may post a comment.