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:

Anonymous said...

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!

Joey said...

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()"

Joost van Schaik said...

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

George Kostov said...

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

Joost van Schaik said...

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

Ed Graham said...

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

zhi said...

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

Joost van Schaik said...

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

Bluesthue said...

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.

Gera Elem said...

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

Thanks in advance

Joost van Schaik said...

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

RGA said...

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.

Joost van Schaik said...

@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

RGA said...

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?

Joost van Schaik said...

@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

PURNA MAGUM said...

very nice explanation


Thank allot for in time help :)

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

Joost van Schaik said...

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

Sk. Razibul Islam said...

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

Joost van Schaik said...

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

Randy Stimpson said...

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.