Calling WCF Services with jQuery…Stripped Down

Years ago, when I created my first ASMX Web Service and called it from an application, it was easy and it was fun. I was able to call functions on a server, from a client, with little effort. What a great and powerful tool!

Then WCF came out and was deemed the 'best practice' and the 'preferred' method. Developers were encouraged to use it. Sadly, it was a nightmare of complexity. Rube Goldberg would have been proud.

I recently began investigating calling WCF Services with jQuery. There aren't many articles or working samples that are simple enough to be a good starting point for development or proof of concept. I gathered what I learned and decided to cut out as much superfluous details from the paradigm as possible: I tried to make it palatable.

This is the smallest working example of jQuery calling a WCF Service anywhere (as far as I know).

Caveats:

WCF services are fragile. Use a good source control system or some substitute. If you make a change and everything is still working, check it in and label it. That way, when you break your code (and you will) and can't figure out what happened, you can revert to a known good version.

Normally the cache is your friend. When developing, the cache is your enemy. When your code changes don't seem to be having any effect, clear the cache and/or restart the web server. Sometimes I put message boxes or log strings in the code to see if it actually being executed.

We Don't Need No Stinking Interface:

I've got nothing against interfaces; I even blogged about them here. But I'm going to guess that less than one percent of web services require the use of an interface—maybe less than one in a thousand—maybe less than that.

The default template for WCF services uses an interface for a contract—an inexplicably stupid decision.

Here is how I removed the unneeded complexity.

In the interface file, the generated class looks something like this:

[ServiceContract]
public interface IService1
{
    [OperationContract]
    string GetData(int value);

 

  • I moved the contract attributes into the implementation class.
  • I added a WebInvoke attribute to the functions.
  • I removed the interface inheritance from the service implementation class.
  • I deleted (yes deleted!) the interface file.
  • In the config file, I changed the contract to be the implementation class, NOT the interface class.

Then I deleted all but one function in the implementation class…to get it really lean and mean.

Here is the final WCF Service CS code:

using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
 
[ServiceContract]
public class MyService
{
    [OperationContract]
    [WebInvoke(Method = "POST",
               BodyStyle = WebMessageBodyStyle.Wrapped,
               ResponseFormat = WebMessageFormat.Json)]
    public string MyFunction(string Count)
    {
        return "The Count you passed in is: " + Count.ToString();
    }
}

Here is the HTML/JavaScript/jQuery code file.

<!DOCTYPE html>
<html>
<head>
    <title>Call WCF</title>
    <script src="Scripts/jquery.js" type="text/javascript"></script>
    <script type="text/javascript">
 
        var counter = 0;
        function CallMyService()
        {
            counter++;
 
            $.ajax({
                type: "POST",              
                url: "MyService.svc/MyFunction",
                data: '{"Count": "' + counter + '"}', 
                contentType: "application/json", // content type sent to server
                success: ServiceSucceeded,
                error: ServiceFailed
            });
        }
 
        // ---- WCF Service call backs -------------------
 
        function ServiceFailed(result)
        {
            Log('Service call failed: ' + result.status + '  ' + result.statusText);
        }
 
        function ServiceSucceeded(result)
        {
            var resultObject = result.MyFunctionResult;
            Log("Success: " + resultObject);
        }
 
        // ---- Log ----------------------------------------
        // utility function to output messages
 
        function Log(msg)
        {
            $("#logdiv").append(msg + "<br />");
        }
    </script>
 
</head>
<body>
    <input id="Button1" type="button" value="Execute" onclick="CallMyService();" />
 
    <div id="logdiv"></div>  <!--For messages-->
</body>
</html>

 

Note I am using a simple HTML page to call the service. It's my way of showing, "There's nothing up my sleeve." You can download the full project here. I recompiled it to .NET 4.5.

  • There is no project or solution file, open it as a Web Site.
  • Run/Browse the CallWCF.html file.
  • Click the Execute button.

You should see this:

I hope someone finds this useful.

Steve Wellens

9 Comments

  • Hi Steve,

    This is a real gem of an example, couple of questions though

    1. Do we need to remove the interface for a technical reason?

    2. Have you attempted to call a wcf method which has message contracts, I've hard time calling a wcf method with message contracts from query

    Appreciate your responses

  • A more complete example: http://weblogs.asp.net/ricardoperes/archive/2011/03/29/calling-wcf-web-services-from-javascript.aspx

  • @Pavan Boddapati

    1. Do we need to remove the interface for a technical reason?

    No. I choose to remove it because it is excess baggage.

    2. Have you attempted to call a wcf method which has message contracts, I've hard time calling a wcf method with message contracts from query

    No. But now that you have a simple template to start from, maybe you'll find it easier to deal with.

  • "Microsoft created the Web API framework "

    Too bad they insist you create a routing table adding more complexity and layers.

  • Thankssssssssssssssssssssssssssssssssssss a LOT !!!!!!

    I was banging my head against wall since last 4 days for this one little ****ing ajax call !!!!!

  • "I was banging my head against wall since last 4 days "

    I call that entering 'learning mode'. It is how you become an expert at something.

  • Consider using the JSON.stringify method for creating the ajax data param instead of creating it by hand.

  • "Consider using the JSON.stringify method for creating the ajax data param instead of creating it by hand. "

    OK, I'll consider it......rejected. I want the example to be as simple as possible.

  • Thanks a lot for this. Works like a gem.

Add a Comment

As it will appear on the website

Not displayed

Your website