The Windows Communication Foundation (WCF) provides a unified API for messaging. Chapter 6, “Legacy Integration,” shows how to use the WCF to integrate with Microsoft technologies such as MSMQ and COM+. In addition to integration, the Windows Communication Foundation also provides significant benefits when it comes to interoperability. This chapter examines how to interoperate with other systems using Web services.
WCF is part of WinFX and has a dependency on the .NET Framework 2.0. For scenarios in which a client is running an earlier version of the framework, using a non-.NET language, and/or running on another platform, interoperability becomes critical.
This chapter demonstrates interoperability in several varieties seen in the real world. The first example involves creating a WCF client that connects to an existing ASMX Web service. Next, you will create a simple WCF service, and then create both a WCF client and an ASMX client to consume it.
One of the key values of SOAP is that it is platform agnostic. Regardless of the platform a system may be on, there is potential to readily interoperate with others.
Through the .NET Framework and the SOAP Toolkit, Microsoft provided the capability to create Web services hosted within Internet Information Server (IIS). The more common .NET Web services were stored in files with an extension of .ASMX
and are commonly referred to as ASMX Web Services. Other software companies created their own Web service implementations, and subtle differences among the implementations caused some challenges when they attempted to interoperate using other tools, languages, and/or platforms.
The Web Services Interoperability Organization (http://www.ws-i.org) creates, promotes, and supports generic protocols for the interoperable exchange of messages between Web services. The WS-I has published a profile of what must be supported for basic interoperability.
To facilitate interoperability, the WS-I established a working group for a basic profile that could be implemented to support interoperability across implementations and platforms. The Basic Profile 1.1 (BP1.1) consists of implementation guidelines recommending how a set of core Web services specifications should be used together to develop interoperable Web services. The guidelines address technologies that cover the following areas:
Messaging. —The exchange of protocol elements, usually over a network, to affect a Web service
Description. —The enumeration of the messages associated with a Web service, along with implementation details
Discovery. —Metadata that enables the advertisement of a Web service’s capabilities
Security. —Mechanisms that provide integrity and privacy
BP 1.1 covers the following core Web services standards and provides constraints and clarifications to these base specifications, along with conventions about how to use them together, with the goal of promoting interoperability:
SOAP 1.1
WSDL 1.1
UDDI 2.0
XML 1.0 (Second Edition)
XML Schema Part 1: Structures
XML Schema Part 2: Data types
RFC2246: The Transport Layer Security Protocol Version 1.0
RFC2459: Internet X.509 Public Key Infrastructure Certificate and CRL Profile
RFC2616: Hypertext Transfer Protocol 1.1
RFC2818: HTTP over TLS Transport Layer Security
RFC2965: HTTP State Management Mechanism
The Secure Sockets Layer Protocol Version 3.0
To provide Basic Profile support in WCF is very straightforward, just specify the basicHttpBinding
.
Although having Basic Profile 1.1 is important, as the name implies, it is for basic interoperability. The functionality provided by the BP 1.1 does not address many of the needs critical to many real-world scenarios, particularly around security and reliability.
Much of what is supported by the Basic Profile is designed for services that have direct connections with their clients. In the emerging world of service-oriented Enterprises, messages no longer go strictly from a service at Point A to a client at Point B; instead a message may make multiple “hops” en route to its destination. This requires involvement not at the transport level, but at the message level.
When examining security in the Basic Profile, the channel between the server and its clients can be secured using SSL. Both server and client authenticity can be validated using certificates. This is typically acceptable when you’re interacting in a scenario in which there is a 1:1 connection. But what about when you send a message, that message is then routed, and eventually it reaches its recipient? There could be any number of hops in between client and service, and the path is likely to vary based on various criteria (traffic, SLAs, and so on). Although setting up transport security with BP 1.1 could be done, this process now introduces a number of intermediaries and introduces the potential risk that messages could be modified en route. There was a need for standards around key areas in this space, with major focuses on security, transactions, and reliability. OASIS has been the leader in driving these standards.
OASIS (Organization for the Advancement of Structured Information Standards) is a not-for-profit, international consortium that drives the development, convergence, and adoption of e-business standards. Microsoft, IBM, SAP AG, Nokia, Oracle, and BEA Systems are among the 600 organizations that participate in OASIS.
The participants in OASIS have put forward a number of standards for advanced Web services, referred to collectively as the WS-* specifications. In WCF, WS-* interoperability includes platform-agnostic support of reliable sessions, transactions, transport security, and SOAP security.
To provide WS-* support to your services, use the wsHttpBinding
.
In addition to the bindings provided with Windows Communication Foundation out of the box, WCF provides the capability to create custom bindings in the configuration file. This allows tremendous flexibility when interoperating with business partners, legacy systems, third-party products, and commercial Web services when the standard bindings provided do not meet the requirements of your service. Custom binding elements could be used, for example, to enable the use of new transports or encoders at a service endpoint. Custom bindings are used to define a binding from a set of binding elements.
To facilitate the creation of client proxies, Windows Communication Foundation includes the Service MetaData Utility tool (SvcUtil.exe
). This tool generates service model code from metadata documents and metadata documents from service model code.
In this chapter, we’ll use the tool to generate proxy code to be used in interop scenarios. At least up until the February CPT release, it does not automatically map the preconfigured bindings by name. Instead, custom bindings will be created that map to the requirements of the service.
SvcUtil.exe
is called using the command line and parameters found in Table 7.1.
Svcutil [options] [metadataPath* | assemblyPath* | metadataUrl*]
Table 7.1. Parameters for SvcUtil.exe
Argument | Description |
---|---|
| Path to metadata document that contains the contract to import into code ( |
| Path to the assembly file that contains service contracts to export to metadata. |
| URL to the running Web service that provides metadata for download through WS-Metadata Exchange or Http-Get. |
| Description. |
| Directory to create files in. Default: The current directory. Short form: |
| File name for the generated code. Default: Derived from the service name or target namespace of the schema document. Short form: |
| Specifies the output to be generated by the tool. Default: Inferred from input. Short form: |
| Instructs the tool to validate all service endpoints in associated config files. (A config file is loaded when an exe for the config file is passed to the tool.) Short form: |
| Instructs the tool to generate a configuration file. If only one filename is given, that is the name of the output file. If two filenames are given, the first file is an input configuration file whose contents are merged with the generated configuration and written out into the second file. |
| Do not create a config file. |
| Custom configuration file to use in place of the app config file. Allows the user to change metadata configuration without altering global app config settings. |
| Specifies the programming language to use for code generation. Values: Short form: |
| Compiles generated code into an assembly. Short form: |
| Specifies the CLR namespace to associate with a schema target |
| namespace. Default: Derived from the target namespace of the schema document. Short form: |
| References the specified assembly files. Short form: |
| Do not reference standard library ( |
| Fully qualified or assembly-qualified type name to exclude from referenced types. Short form: |
| Fully qualified or assembly-qualified type name to exclude from referenced types. Short form: |
| Generate asynchronous method signatures. Short form: |
| Generate classes marked internal (default: generate public classes). Short form: |
| Instructs the tool to generate code that uses typed messages. Short form: |
| Instructs the tool to generate code that uses Short form: |
| Import non-Data Contract types as Short form: |
| Implement Short form: |
| Instructs the tool to operate on Data Contract types only. Service Contracts will not be processed. Short form: |
| Suppress the copyright and banner message. |
| Displays command syntax and options for the tool. Short form: |
The following exercise creates a client for a very simple ASMX Web service with one web method, InteropHelloWorld
. As you can see in the Listing 7.1, this method for that service receives a string parameter, Name
, and returns a string value.
Example 7.1. ASMX Service Code
using System; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class Service : System.Web.Services.WebService { public Service () { } [WebMethod] public string InteropHelloWorld(string Name) { return "Hello " + Name + ", you've just interop'd."; } }
This service was deployed using the setup script available at the publisher’s website.
Validate that the service is online and create the proxy for the client:
Test that the service is online and available.
Open Internet Explorer, and navigate to the following URL:
http://localhost/WCFHandsOn/InteropHelloWorld/Service.asmx
This should display a page that lists the operations supported by this service. If this does not display, validate that the virtual directory exists and is pointing to C:AppsWCFHandsOnChapter7PartIAfterInteropHelloWorld
.
In the open solution, add a new project.
Create a new Windows Console application in C:WCFHandsOnChapter7BeforePartIWCFClient
.
Add a reference to System.ServiceModel
.
Now you will create the proxy for the ASMX service.
Open a Visual Studio command prompt and navigate to the directory C:WCFHandsOnChapter7BeforePartIWCFClient
.
Enter the following at the command prompt:
"C:Program FilesMicrosoft SDKsWindowsv1.0BinSvcUtil.exe " http://localhost/
WCFHandsOn/InteropHelloWorld/Service.asmx?wsdl/out:proxy.cs
SvcfUtil.exe
generates two files, proxy.cs
and output.config
.
Proxy.cs
contains a generated proxy class for the ASMX Web service. Output.config
contains the configuration information for the service that can be inserted into the application configuration file (App.config
).
Within Visual Studio, add both of these files to the WCFClient project.
Rename output.config
to App.config
.
Using Solution Explorer, open the App.config
file and examine its contents:
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.serviceModel> <client> <endpoint address="http://localhost/WCFHandsOn/InteropHelloWorld/Service .asmx" bindingConfiguration="ServiceSoap" binding="customBinding" name="ServiceSoap" contract="ServiceSoap" /> <endpoint address="http://localhost/WCFHandsOn/InteropHelloWorld/Service .asmx" bindingConfiguration="ServiceSoap12" binding="customBinding" name="ServiceSoap1" contract="ServiceSoap" /> </client> <bindings> <customBinding> <binding name="ServiceSoap"> <textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16" messageVersion="Soap11Addressing1" writeEncoding="utf-8 /> <httpTransport manualAddressing="false" maxBufferPoolSize="524288" maxMessageSize="65536" allowCookies="false" authenticationScheme="Anonymous" bypassProxyOnLocal="false" ostNameComparisonMode="StrongWildcard" mapAddressingHeadersToHttpHeaders="true" proxyAuthenticationScheme="Anonymous" realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false" useDefaultWebProxy="true" /> </binding> <binding name="ServiceSoap12"> <textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16" messageVersion="Default" writeEncoding="utf-8" /> <httpTransport manualAddressing="false" maxBufferPoolSize="524288"maxMessageSize="65536" allowCookies="false" authenticationScheme="Anonymous" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" mapAddressingHeadersToHttpHeaders="true" proxyAuthenticationScheme="Anonymous" realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false" useDefaultWebProxy="true" /> </binding> </customBinding> </bindings> </system.serviceModel> </configuration>
Notice that SvcUtil has created the two endpoints ServiceSoap
and ServiceSoap1
for InteropHelloWorldService
.
If you look at the WSDL document exposed by our ASMX service, you’ll notice that these endpoints were created from the port information in that document:
<wsdl:service name="Service"> <wsdl:port name="ServiceSoap" binding="tns:ServiceSoap"> <soap:address location="http://localhost:8000/WCFHandsOn/InteropHelloWorld/Service.asmx" /> </wsdl:port> <wsdl:port name="ServiceSoap12" binding="tns:ServiceSoap12"> <soap12:address location="http://localhost:8000/WCFHandsOn/InteropHelloWorld/Service.asmx" /> </wsdl:port> </wsdl:service>
Also note that SvcUtil.exe
creates custom bindings for each of these. Each of these displays a number of the configurable attributes that can be set, highlighting the flexibility available for interoperability.
From Solution Explorer, open proxy.cs
.
This is the proxy class created by SvcUtil.exe
. Notice that the ServiceSoap
interface was defined, containing a single operation that was in our service.
In addition, a ServiceSoapProxy
class was created. Note that in addition to several constructors for the class, the class also implements the ServiceSoap
interface. When InteropHelloWorld
is called on the proxy, it will call the operation on our ASMX service:
[System.ServiceModel.ServiceContractAttribute(Namespace="http://Samples.Microsoft.Com/")] public interface ServiceSoap { [System.ServiceModel.OperationContractAttribute(Action="http://Samples.Microsoft.Com /InteropHelloWorld", ReplyAction="http://Samples.Microsoft.Com/InteropHelloWorld")] string InteropHelloWorld(string Name); } public interface ServiceSoapChannel : ServiceSoap, System.ServiceModel.IClientChannel { } public partial class ServiceSoapProxy : System.ServiceModel.ClientBase<ServiceSoap>, ServiceSoap { public ServiceSoapProxy() { } public ServiceSoapProxy(string endpointConfigurationName) : base(endpointConfigurationName) { } public ServiceSoapProxy(string endpointConfigurationName, string remoteAddress) : base(endpointConfigurationName, remoteAddress) { } public ServiceSoapProxy(string endpointConfigurationName, System.ServiceModel .EndpointAddress remoteAddress) : base(endpointConfigurationName, remoteAddress) { } public ServiceSoapProxy(System.ServiceModel.Binding binding, System.ServiceModel .EndpointAddress remoteAddress) : base(binding, remoteAddress) { } public string InteropHelloWorld(string Name) { return base.InnerProxy.InteropHelloWorld(Name); } }
Now that we have a proxy class and a configuration file, let’s write the code to call the service.
Using Solution Explorer, open the file Program.cs
.
Add using System.ServiceModel;
to the top of the Program.cs
file:
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
Modify the Main method in Program.cs
to include the lines listed in bold in the following code:
static void Main(string[] args) { ServiceSoapProxy proxy = new ServiceSoapProxy("ServiceSoap"); Console.WriteLine("What's your name?"); string name = Console.ReadLine().ToString(); Console.WriteLine(proxy.InteropHelloWorld(name)); Console.WriteLine("------------------------"); Console.WriteLine("Press Any Key To Exit"); Console.ReadLine(); }
Note that we chose to reference the constructor that takes a configurationName as a parameter. At runtime, the name provided will be used to reference the appropriate endpoint, bindings, and contract in the App.config
file.
Using Solution Explorer, right-click the WCFClient project and select Set as Startup Project.
From the Debug menu, select Start Debugging.
After you’ve entered your name at the prompt, the client will call out to the ASMX service and display the result.
In this next example, we’ll look at interoperability from the other direction. Here we’ll create a WCF service and then create ASMX and WCF clients that utilize it.
To create the new service project, follow these steps:
Open Visual Studio and add a new project. Create a new Windows Console application in C:WCFHandsOnChapter7BeforePartIIInteropHelloWorld2
.
Add a Reference to System.ServiceModel
.
Using Solution Explorer, open the file Program.cs
.
Add using System.ServiceModel;
to the top of the Program.cs
file:
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
This service will expose one operation, InteropHelloWorld
. First, add the interface IInteropHelloWorld
to the Program.cs
file.
Enter the following interface code:
namespace Samples.Microsoft.Com { [ServiceContract] public interface IInteropHelloWorld { [OperationContract] string InteropHelloWorld(string Name); }
With the interface defined, we can now add the class for our service that implements it.
Enter the following code for the class:
public class InteropHelloWorld2 : IInteropHelloWorld { public string InteropHelloWorld(string Name) { return "Hello " + Name + ", you've just interop'd."; } }
For this exercise, the service will not be be hosted within IIS, but is instead hosted inside of a Windows Console application.
This requires the creation of a ServiceHost
object to instantiate the service. When a new ServiceHost
is being created, information regarding the service is provided in the constructor. In this case, we specify the serviceType
that maps to the name of the class:
static void Main(string[] args) { ServiceHost service = new ServiceHost(typeof(InteropHelloWorld2)); service.Open(); Console.WriteLine("Service is available."); Console.ReadLine(); }
Now we can create the App.config
file and configure the service.
Add a new application configuration file to the project and accept the default name of App.config
.
Open the configuration file and enter the information for the service’s abc’s (address, binding, contract) as seen here:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <!-- use appSetting to configure base address provided by host --> <add key="baseAddress" value="http://localhost:8080/WCFHandsOn/InteropHelloWorld2" /> </appSettings> <system.serviceModel> <services> <service type="Samples.Microsoft.Com.InteropHelloWorld2"> <endpoint address="" binding="basicHttpBinding" contract="Samples .Microsoft.Com.IInteropHelloWorld"/> </service> </services> </system.serviceModel> </configuration>
Our base address is specified in the appSettings
setting, because we’ll be setting this value inside of the code. Also note that the endpoint for this service is being made available on port 8000 of the local server. Because this is running in a console application and is not hosted within Internet Information Server, we’ve specified a separate port. Note that we are using the basicHttpBinding
, and the service will be compliant with BP 1.0. Finally, note that the contract consists of the concatenation of the namespace and the interface for the service.
With the application configuration file populated, the project is now ready to be compiled.
Build the project.
Using Windows Explorer, navigate to the InteropHelloWorld2.exe
just created and run the InteropHelloWorld2
service. The full path to the file is C:WCFHandsOnChapter7PartIIBeforeInteropHelloWorld2InteropHelloWorld2inDebugInteropHelloWorld2.exe
.
With the service now running, it is available for clients to query it for metadata and interact with it.
Creating the WCF client for our WCF service will be virtually identical to how we created the WCF client for the ASMX service in the initial example, using SvcUtil.exe:
Create a new Windows Console project in C:WCFHandsOnChapter7PartIIBeforeWCFClient
.
Add a Reference to System.ServiceModel
.
Open Visual Studio.NET Command Window.
Execute the SvcUtil.exe
utility, pointing it at the WCF Service. This creates both a proxy and a configuration file to be used by the client:
"c:Program FilesMicrosoft SDKsWindowsv1.0BinSvcUtil.exe" http://localhost:8000 /WCFHandsOn/InteropHelloWorld2 /out:proxy.cs
Using Solution Explorer, add proxy.cs
to the WCFClient project.
Using Solution Explorer, add output.config
to the WCFClient project.
Rename output.config
to App.config
.
Place the following code in the Main method in the Program.cs
file:
static void Main(string[] args) { Console.WriteLine("Please enter your name"); string Name = Console.ReadLine(); InteropHelloWorldProxy hello = new InteropHelloWorldProxy(); Console.WriteLine("This is the message from the WCF Web Service:"); Console.WriteLine(hello.InteropHelloWorld(Name)); Console.ReadLine(); }
In Solution Explorer, right-click the project and select Debug, Start New Instance.
The client will prompt you for your name. It will then call the InteropHelloWorld
service and write the response to the console.
There are very straightforward ways to enable ASMX clients to access your Windows Communication Foundation service. For projects in which clients will have both the .NET Framework 2.0 and WinFX installed, SvcUtil.exe
can be used, as it was in the preceding example. In that environment, the proxy.cs
and output.config
files generated by SvcUtil.exe
could be added to an ASMX Web service project without modification.
If your service consumers do not have WinFX installed and/or are unfamiliar with SvcUtil.exe
, they can consume your BP 1.1 Web service as they would any other Web service, using the Add Web Reference functionality built into Visual Studio. The WCF service exposes both WSDL and MEX metadata, which can be used by programmers and development tools to consume the service on any platform.
This example looks at creating an ASMX client for the WCF Service created earlier.
Rather than using SvcUtil.exe
, which requires the .NET Framework 2.0, as mentioned earlier, we’ll use the Add Web Reference facility that’s been available since the initial release of VisualStudio.NET. It is important to note that while WCF requires the .NET Framework 2.0, clients for BP 1.1 services can be created using earlier versions of the framework and Visual Studio.NET:
Within VisualStudio.NET, create a new website at C:WCFHandsOnChapter7PartIIBefore
.
Name the website ASMXClient
.
In Solution Explorer, add a web reference to the project.
When prompted in the Add Web Reference dialog, enter the following URL: http://localhost:8000/WCFHandsOn/InteropHelloWorld2?wsdl
With the web reference set, the ASMX client will now utilize the service within its own service. When the project was created, a file Service.cs
was added to the project in the project’s App_Code
directory.
Open this file now and add the code for the WebMethod:
using System; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; [WebService(Namespace = "http://Samples.Microsoft.Com/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class Service : System.Web.Services.WebService { public Service () { } [WebMethod] public string HelloWorldAsmx(string Name) { localhost.InteropHelloWorld2 hello = new localhost.InteropHelloWorld2(); return "This is the message from the WCF Web Service" + hello.InteropHelloWorld(Name); ; } }
Using the Internet Information Services Manager, create a new virtual directory. The new directory should use the alias WCFHandsOn_ASMXClient
and the local path for the virtual directory should point to the location of the project, C: WCFHandsOnChapter7PartIIBeforeASMXClient
.
Using VisualStudio.NET, build the project.
Finally, test the “client” ASMX service by opening Internet Explorer and entering the URL for the service, http://localhost/WCFHandsOn/ASMXClient/Service.asmx.
Lotus Notes is a popular messaging and collaboration tool sold by IBM. Lotus Notes Domino is a Web server designed to publish information from the Notes data stores. Domino currently provides the capability to expose BP 1.1 services for use in client applications and scenarios such as B2B. Although Lotus does have client development tools, Enterprises that utilize notes and the consumers of Domino-published content may want to develop clients using Visual Studio.NET. This is particularly desirable for many companies looking to take advantage of technologies such as the Windows Presentation Foundation (WPF) for a rich user experience, the Workflow Foundation (WF) for workflow, and the Windows Communication Foundation (WCF) for secure, reliable, transacted services.
Fortunately, it’s very easy to do this using the same SvcUtil.exe
utility that we used in the preceding exercise.
Microsoft has a licensed copy of Domino Server running the site http://www.msdomino.net that is populated with content by our colleague Gary Devendorf. Gary is a Technical Evangelist at Microsoft, and he helps customers interoperate between Lotus and Microsoft technologies, or migrate over from Lotus to Microsoft solutions.
On this site, Gary has created a Web service for placing orders over the web that are deposited in a Lotus Notes database. This Web service provides operations that allow you to place an order, change the status of an order, and check the status of an order.
In this exercise, you will create a console application that places an order and immediately checks the status of that order. It then calls the service to change the status to Approved and check the status once more. As part of testing the service, we’ll go to a Domino web page to validate that the order has been received and has been approved.
Creating the WCF client for our WCF service will be virtually identical to how we created the WCF client for the ASMX and WCF services in the earlier example, using SvcUtil.exe
. In this case, we’re using the same approach to interoperate with a non-Microsoft Web server:
Create a new Windows Console project in C:WCFHandsOnChapter7PartIIIBeforeDominoClient
.
Add a Reference to System.ServiceModel
.
Add using System.ServiceModel;
to the top of the Program.cs
file:
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
Open Visual Studio.NET Command Window.
Execute the SvcUtil.exe
utility with a reference to the service to create a proxy and configuration file to be used by the client.
"c:Program FilesMicrosoft SDKsWindowsv1.0BinSvcUtil.exe " http://www.msdomino.net /msorders.nsf/create_order?WSDL/out:proxy.cs
Using Solution Explorer, add proxy.cs
to the DominoClient project.
Using Solution Explorer, add output.config
to the DominoClient project.
Rename output.config
to App.config
.
Open the App.config
file.
In the client section, add a name for our endpoint that we will use when calling the service by adding the text name=”DominoOrders”:
<client>
<endpoint name=”DominoOrders” address= http://www.msdomino.net:80/msorders.nsf/
create_order?OpenWebService bindingConfiguration=”DominoSoapBinding”
binding=”customBinding” contract=”Update” />
</client>
You will now enter the core information for the client. Although there are sample values in the following code for the parameters (such as weight, shipAddress, shipCity
), feel free to modify these.
Place the following code in the Main
method in the Program.cs
file:
static void Main(string[] args) { using (UpdateProxy proxy = new UpdateProxy("DominoOrders")) { string customerID = "1"; string orderDate = "10/25/2006"; string weight = "50"; string freight = "100"; string shipAddress = "1 main street"; string shipCity = "Redmond"; string shipCountry = "USA"; string amount = "500.00"; //PLACE THE ORDER int orderID = proxy.NEWORDER(customerID,orderDate,amount,freight, weight, shipAddress, shipCity, shipCountry); System.Console.WriteLine("Your order was placed. Your order ID for future reference is " + orderID.ToString()); //CHECK THE STATUS OF THE ORDER System.Console.WriteLine ("----------------------------------------------------------------------------"); string status = proxy.CHECKSTATUS(orderID); System.Console.WriteLine(); System.Console.WriteLine("Your order status is: " + status); //APPROVE THE ORDER System.Console.WriteLine ("----------------------------------------------------------------------------"); System.Console.WriteLine("Cancelling order#" + orderID.ToString()); proxy.CHANGESTATUS(orderID, "Approved"); // CHECK THE ORDER STATUS, TO SEE IF IT'S APPROVED System.Console.WriteLine ("----------------------------------------------------------------------------"); status = proxy.CHECKSTATUS(orderID); System.Console.WriteLine(); System.Console.WriteLine("Your order status is: " + status); System.Console.ReadLine(); } }
In Solution Explorer, right-click the project and select Debug, Start New Instance.
The client will then print out several messages in the console window, identifying that the order has been placed, the order ID assigned by the server, and that the order has been approved. Make a note of the order ID, because we will now validate that this was accepted on the server.
Go to the page on Domino to view the results.
Open your web browser and navigate to http://www.msdomino.net/msorders.nsf.
You should see a web page with several links on it, as shown in Figure 7.1.
Click on the Approved Orders link. This will display a list of all the orders that have been approved (see Figure 7.2).
To complete the exercise, validate that your order ID is included in the list of approved orders.
We’ve just done interop with a product from IBM; now let’s continue down the path by creating test clients for two other major players, Oracle and Sun Microsystems. From a technology perspective, we’ll be revisiting what we’ve done earlier in the chapter. So why include this in the book? To underscore the value that standards—and a tool such as WCF that is built on standards—provide to the Enterprise. The SvcUtil.exe
utility reads platform-agnostic WSDL files, and we’re up and interoperating in minutes.
Sun Microsystems has a public-facing Web service that can be used for interoperability testing. This service is provided solely for interoperability tests, so its operations are limited to “echoes.” These operations will receive a value of a particular type, such as a string, and will return that same value to the caller:
Create a new Windows Console project in C:WCFHandsOnChapter7PartIVBeforeSunClient
.
Add a Reference to System.ServiceModel
.
Add using System.ServiceModel;
to the top of the Program.cs
file:
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
Open Visual Studio.NET Command Window.
Execute the SvcUtil.exe
utility with a reference to the service to create a proxy and configuration file to be used by the client.
"c:Program FilesMicrosoft SDKsWindowsv1.0BinSvcUtil.exe " http://soapinterop.java .sun.com/round2/base?WSDL /out:proxy.cs
Using Solution Explorer, add proxy.cs
to the SunClient project.
Using Solution Explorer, add output.config
to the SunClient project.
Rename output.config
to App.config
.
Open App.config
and add a name for the endpoint. Add the text name=“SunInterop”
to the endpoint element in the client section of the config file:
<client>
<endpoint name="SunInterop" address="http://soapinterop.java.sun.com:80/round2/base"
bindingConfiguration="RIBaseBinding" binding="customBinding"
contract="RIBaseIF" />
</client>
Place the following code in the Main method in the Program.cs
file:
static void Main(string[] args) { RIBaseIFProxy proxy = new RIBaseIFProxy("SunInterop"); System.Console.WriteLine("Enter in the phrase to tell Sun"); String repeatText = System.Console.ReadLine(); System.Console.WriteLine(); System.Console.WriteLine("Sun – if you can understand me, repeat after me:" + repeatText); System.Console.WriteLine("Sun says:" + proxy.echoString(repeatText)); System.Console.ReadKey(); }
In Solution Explorer, right-click the project and select Debug, Start New Instance.
The client will prompt you for some text to send to Sun. It will then contact the Sun Web service, which will return that same text.
Oracle has a public-facing website and services for its Oracle Application Server 10g. There is a public-facing Web service attached to the product. This service has several username and password controlled services; however, we’re interested only in testing interop. In this exercise, we’ll create a client that tests the GetVersion
operation, which does not require a username or password:
Create a new Windows Console project in C:WCFHandsOnChapter7PartIVBeforeOracleClient
.
Add a Reference to System.ServiceModel
.
Add using System.ServiceModel;
to the top of the Program.cs
file:
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
Open Visual Studio.NET Command Window.
Execute the SvcUtil.exe
utility with a reference to the service to create a proxy and configuration file to be used by the client.
"C:Program FilesMicrosoft SDKsWindowsv1.0BinSvcutil.exe " /out:proxy.cs http:/ /messenger.oracle.com/xms/webservices?WSDL
Using Solution Explorer, add proxy.cs
to the OracleClient project.
Using Solution Explorer, add output.config
to the OracleClient project.
Rename output.config
to App.config
Open App.config
and add a name for the endpoint. Add the text name=”OracleInterop”
to the endpoint element in the client section of the config file:
<client>
<endpoint name="OracleInterop" address= "http://notify.multimodeinc.com/xms/webservices"
bindingConfiguration="XMSServerBinding" binding="customBinding"
contract="XMSServerPortType" />
</client>
Place the following code in the Main
method in the Program.cs
file:
static void Main(string[] args) { //ORACLE XMSServerPortTypeProxy proxy = new XMSServerPortTypeProxy("OracleInterop"); string version = proxy.getVersion(); System.Console.WriteLine("The version of Oracle currently running is:" + version); System.Console.ReadLine(); }
In Solution Explorer, right-click the project and select Debug, Start New Instance.
The client will connect to the Oracle service, return the current version, and display it in the console.
In this chapter we saw the power of Windows Communication Foundation to interoperate. WCF on the server provides the capability to interoperate with various systems, and this chapter showed how to interoperate with ASMX services in client and service scenarios. In addition, we saw examples for how to interoperate with existing technologies from Microsoft, Oracle, IBM, and Sun.