Creating and Using a Web Service in Managed C++

From Kate Gregory's Codeguru column, "Using Visual C++ .NET".

Web Services are a really exciting part of the .NET initiative - but they are bigger than .NET itself. The concept behind them is simple. Almost any web server you can name has some mechanism for executing server-side code: you type a URL into your browser, and something runs on the server and then writes out HTML in response to your request. It might be ASP, ASP.NET, servlets, even a five-year-old Perl script triggered through CGI. So imagine that the running code returns XML instead of HTML, and that it's called not because a user typed a URL into a browser, but because some code somewhere did a GET over HTTP to ask the web server for that URL. Now you've got an application-to-application connection happening. Just about every programming language has a class library that makes it easy to do a GET request over HTTP and some easy way of parsing XML, so this approach gives you a cross-platform, cross-programming-language, cross-vendor, cross-everything way to have code in one application call code on a completely different machine, as long as they're both on the Internet or otherwise connected.

That's the basic concept behind Web Services. But thinking of that code as a function instead of a page, how do you pass parameters to the function? What if it returns a complex data type? What if a web server has more than one web service on it? How can you find out the names, specify which service you want, and so on? This is where the capital letters are earned. There are standards being developed with names like Web Services Description Language (say wizdle to sound ultra-cool) that cover these technical issues for you. If you build a Web Service with Visual Studio.NET, it will meet these standards. And if you consume a Web Service, no matter how it was built, with Visual Studio.NET, you'll see how amazingly easy it can be to leverage someone else's code.

Writing a Web Service

To write a Web Service, you write a class with at least one method. The class is marked with a [WebService] attribute, and the method with a [WebMethod] attribute. A class might represent a customer, for example, and have a method to get the customer's shipping information, or to add a new order to the customer's order list. Web methods can take and return any variable type, including instances of objects you define. And they can do anything: persist data to and from a database, make any kind of calculation, even call another web method to help get the job done. For this example, I'm going to write a CalculatorService class with a method called Add that - you guessed it - adds two numbers and returns the total.

In Visual Studio.NET, I created a new project. From the Visual C++ project templates, I chose Managed C++ Web Service. I named the project Calculator. The code that is generated includes a class with the exciting name of Class1 - the first thing I did was change this name to CalculatorService in both the .cpp and .h files by hand, though I could have clicked on it in Class View and changed the name in the Properties Window. (I try to avoid having my class name and namespace name be the same, it can confuse Intellisense.) Whichever way I change the class name, I must also change it by hand in the file called Calculator.asmx, which I edit by double-clicking it in Solution Explorer. The edited Calculator.asmx looks like this:

<%@ WebService Class=Calculator.CalculatorService %>

I was given a method called HelloWorld() and it's simple enough to edit it into Add() - I just changed the name in both the .cpp and .h file, changed the signature so that it takes two floating-point numbers, and added code to return the total.

The class declaration ends up looking like this:

using <System.Web.Services.dll>

using namespace System;
using namespace System::Web;
using namespace System::Web::Services;

namespace Calculator
{
    public __gc 
        class CalculatorService : public WebService
    {
    public:
        [System::Web::Services::WebMethod] 
        double  Add(double x, double y);
    };
}

The implementation looks like this:

#include "stdafx.h"
#include "Calculator.h"
#include "Global.asax.h"

namespace Calculator
{
    double CalculatorService::Add(double x, double y)
    {
        return x + y;
    }
};

If you've been following along, you can test the code by choosing Start, Debug. You can't really run a web service, but this starts a web browser and loads Calculator.asmx into it. This is the runs-on-the-web-server file that actually uses your class and methods. If you prefer, open a browser and enter the URL yourself:

http://localhost/Calculator/Calculator.asmx

If you have any trouble, make sure that your web server is started, and that your browser isn't going through a proxy server. On the proxy server, localhost is the proxy server, not your machine. You can follow the link for Add to see some generated documentation for the method, and even test it by entering numbers in the edit boxes and clicking the Invoke button. When you do that, another browser window opens with the result of your call, wrapped up in XML. For example I entered 3 and 2 in the edit boxes, and got this XML:

<?xml version="1.0" encoding="utf-8" ?> 
<double xmlns="http://tempuri.org/">5</double>

Since 3 plus 2 does equal 5, the web service appears to be working.

Using a Web Service

Writing a web service was pretty easy: you just needed an attribute on the class, an attribute on the method, and the calculator.asmx file, and all three were generated for you by Visual Studio. But using one is even easier. I created a Managed C++ application called CalcTest to get started. Before you can use a web service, you need to teach your project where to find it. I right-clicked the CalcTest project in Solution Explorer and chose Add Web Reference. The Add Web Reference dialog has an edit box where you can type a URL. You can also use the UDDI directories to find Web Services throughout the Internet or test web services on your own machine. The simplest thing to do is to enter the URL to Calculator.asmx and press Enter. You will be shown the same documentation you saw when you ran the web service project: click Add Reference to complete the process.

Once the reference has been added, calling a web service is just like using any C++ class. Adding the reference creates a header file that you can include wherever you want to use the web service. I replaced the line that printed Hello World with a line to create the object that represents my web service and another to use it. The edited CalcTest.cpp looks like this:

#include "stdafx.h"

#using <mscorlib.dll>
#include <tchar.h>
#include "WebService.h"

using namespace System;

// This is the entry point for this application
int _tmain(void)
{
    CalculatorService * Calc = new CalculatorService;
    System::Console::WriteLine("1 plus 1 is {0}", 
                               __box(Calc->Add(1,1)));
    return 0;
}

(If the __box keyword doesn't ring a bell, check my previous column on boxing and unboxing fundamental types.) When this application runs, it prints out, not surprisingly I hope:

1 plus 1 is 2

And that's how simple it is to use a web method from within your own code. If you're wondering what happened to the XML and why you didn't have to parse the number out from inside it - that's just one of the cool things that Visual Studio took care of for your when you added the web reference.

The possibilities for this are endless. Any code that can run on your server can, if you want, be accessed by other code through the Internet. Security, authentication, encryption and so on are all available to you and supported by SOAP, one of the standards involved in web services. Since those .asmx files are in fact part of ASP.NET, everything you know about ASP.NET pages applies to web services in .NET as well. Why not try your hand at a little application-to-application integration today?

About the Author

Kate Gregory is a founding partner of Gregory Consulting Limited (www.gregcons.com). In January 2002, she was appointed MSDN Regional Director for Toronto, Canada. Her experience with C++ stretches back to before Visual C++ existed. She is a well-known speaker and lecturer at colleges and Microsoft events on subjects such as .NET, Visual Studio, XML, UML, C++, Java, and the Internet. Kate and her colleagues at Gregory Consulting specialize in combining software develoment with Web site development to create active sites. They build quality custom and off-the-shelf software components for Web pages and other applications. Kate is the author of numerous books for Que, including Special Edition Using Visual C++ .NET.



Comments

  • Visual Studio 2005

    Posted by joeller on 12/19/2006 01:18pm

    Since the project created by the VS 2005 IDE differs so greatly from that created by VS.Net (2002) i would like to see this article re-done using the new IDE with new explanations (particularly about changing the default Class name).

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • The rapid evolution of enterprise storage technologies, combined with external forces, like the explosion of big data, can cause Linux® and server administrators to play catch-up when it comes to storage. Running a bunch of monolithic storage devices and proprietary, disconnected technologies forces administrators to spend valuable time creating and managing complex solutions. To reduce complexity and enable rapid deployment of new technologies and applications, server administrators need a single open …

  • Confused by all the agile advice? Relax! With the Agile for Dummies eBook by your side you'll learn the fundamentals of agile and how to increase the productivity of your software teams while enabling them to produce higher-quality solutions that better fulfill customer needs much faster.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds