Writing a Web Service in Unmanaged C++
Can you write a Web Service in unmanaged C++? Yes, you can. A tool called ATL server supports very high-performance Web Services. It shouldn't be your first choice for ordinary Web Services, because it's a little harder to work with than the techniques shown earlier in this chapter. For example, strings are handled as BSTR types, and memory is not managed for you.
Implementing the Factor() Web method of the Utilities Web Service in ATL Server can serve two purposes in this chapter: demonstrating how to use ATL Server to write a Web Service, and demonstrating how a Web Service client ( UseUtilities ) can switch Web references and still access the Web Service in the same way, although the implementation might change dramatically.
In Visual Studio .NET 2003, create a new project. Choose ATL Server Web Service for the project type, and name it ATLUtilities . Click Finish to create the solution with all the default options. Two projects are created: ATLUtilities and ATLUtilitiesIsapi . The ATLUtilities project defines the ATLUtilitiesService namespace, and within that, a class, CATLUtilitiesService , and an interface, IATLUtilitiesService . The interface defines the Web methods and the class implements them. A HelloWorld() method has already been created for you.
In ATLUtilities.h, find the interface definition, which starts with __interface . Further down the file, find the code for the class. You can see the way that methods are implemented, and the use of attributes to reduce the coding required.
To add the Factor method to the project, right-click IATLUtilitiesService in Class View, and choose Add, Add Method. Fill out the Add Method Wizard dialog box as follows :
Visual Studio will add the method to the interface and class, and open the implementation file, ATLUtilities.cpp, for you to fill in the skeleton method that was generated for you. Add this code:
int j = (int)( i / d); *result = (j*d == i); return S_OK;
Add the [ soap_method ] attribute to ATLUtilities.h, before the declaration of Factor() in the ATLUtilitiesService class. This ensures that Factor() is exposed as a Web method.
Now, change UseUtilities so that it uses ATLUtilities for the Factor method. In the UseUtilities project, add a Web reference. Click the link to browse Web Services on your machine. You'll see a new category now, Discovery Documents, with ATLUtilities listed there. ATL Server doesn't generate an .asmx file, but it makes a discovery file that can be used to add the reference. Click ATLUtilities to select it, and click View Service to see the methods that are offered . You should see Factor() listed along with HelloWorld() .
Change the name of the reference from the machine name to ATLUtilities , and click Add Reference. In the click handler for the Factor button, find this line:
Utilities::UtilitiesClass* ws = new Utilities::UtilitiesClass();
Change it to this:
ATLUtilities::ATLUtilitiesService* ws = new ATLUtilities::ATLUtilitiesService();
Make no other changes to the application. Build it and run it, and it will work just as beforeeven though it is now using a version of the Factor Web method that was built with a completely different tool. The client application is insulated from details like the implementation of the Web Service.
Because client applications aren't affected by your choice of development tool, you're free to choose the tool that's best for you. Comparing the managed C++ and ATL Server version of Factor() , the ATL Server version is clearly more difficult to write and maintain. It works with COM types such as BSTR and VARIANT_BOOL , and returns an HRESULT instead of using exceptions. You should be comfortable writing COM applications in unmanaged C++ using other ATL tools in order to work in ATL Server. The bottom line is that you should use ATL Server only when you have already implemented your Web Service in managed C++ and found that it doesn't meet your required performance levels. You can then re-implement it in unmanaged C++ for maximum speed, and know that your clients need only change the Web reference, and not any of the other code in the client.