Chapter 16: Integrating with ASP.NET Clients and Enterprise Services Components


image from book Download CD Content

After completing this chapter, you will be able to:

  • Create a WCF service that can interoperate with an ASP.NET client application.

  • Integrate a COM+ application into a WCF solution.

A key feature of WCF is the ability to use it to build heterogeneous solutions, protecting your existing investment in existing components and software. WCF is based on commonly accepted WS-* standards and protocols. This enables you to create services that can communicate with client applications running on platforms other than Microsoft Windows and developed using other technologies, such as Java, as long as they conform to the same WS-* standards and use the same protocols. If you publish the metadata for your WCF service, many Java tools vendors provide utilities that can query this metadata and generate Java proxy classes, in much the same way that svcutil does. The converse situation is also true. You can use WCF to build client applications that connect to Java Web services, again as long as those Java Web services conform to the same WS-* standards and protocols as WCF. If these services publish their metadata, you can use the svcutil utility to generate proxy classes for these services. You may also have a number of components, services, and applications created using Microsoft technologies that predate WCF, such as COM+ and ASP.NET. Again, WCF protects your investment in these technologies by enabling you to integrate components built using them into a WCF solution. This chapter describes two common scenarios. First, you will see how to configure a WCF service to enable interoperability with an ASP.NET Web client application. Then you will learn how to integrate a COM+ application into a WCF solution by exposing it as a WCF service.

Creating a WCF Service that Supports an ASP.NET Client

Microsoft developed ASP.NET as a framework for building Web applications. It includes a large number of components that developers can incorporate into interactive Web pages and a structure for processing requests and generating Web pages in response to those requests. Part of the ASP.NET framework is concerned with building Web services. However, the Web services model implemented by ASP.NET now seems quite primitive, as it does not provide support for many of the WS-* protocols that have emerged in recent years. Consequently, ASP.NET Web services and client applications cannot easily make use of WS-* specifications covering features such as reliable sessions, transactions, or even message level security (ASP.NET provides its own implementation of some of these features, and you can use transport level security over the HTTPS transport to protect messages).

Microsoft subsequently released the Web Services Enhancements (WSE) as an add-on to ASP.NET. WSE includes support for some selected WS-* standards. WSE was really just a temporary solution, and you should consider using WCF for all new development. However, it is probably not feasible for your organization to stop using your existing ASP.NET services and applications while you build new versions using WCF. Furthermore, if your ASP.NET Web services and client applications are functioning perfectly, why should you replace them? You are far more likely to migrate Web services to WCF piecemeal, either as you need to add new features to a specific Web service or as you retire a service and replace it with a Web service implementing new functionality. Additionally, it might not be feasible or desirable to migrate ASP.NET Web client applications to WCF. Consequently, you might have a large number of ASP.NET Web client applications in everyday use in your organization that need to be able to connect to ASP.NET and WCF Web services. It is therefore important to understand how to support existing ASP.NET Web client applications in a WCF service.

Important 

The current release of WCF does not provide support for client applications that use partial trust; client applications (including ASP.NET Web services communicating with a WCF service) must run with full trust. This situation might change in the next release of WCF.

In the following exercise, you will see how to build a WCF service that can be accessed by an ASP.NET Web client application (it can also be accessed by a WCF client application, of course).

Examine an existing ASP.NET Web service and client application

  1. Using Visual Studio 2005, open the solution file image from book ASPNETProductsService.sln located in the Microsoft Press\WCF Step By Step\Chapter 16\ASPNETService folder under your \My Documents folder.

    This solution contains an ASP.NET Web site called ASPNETProductsService and a client application that uses this service.

    Note 

    In this exercise, pretend that the ASPNETProductsService Web service is a copy of a production Web service deployed elsewhere in your organization using IIS and transport level security. For ease of testing and configuration, this copy of the Web service executes using the ASP.NET Development Server supplied with Visual Studio 2005 and consequently does not support SSL and the HTTPS protocol. However, the Web client application can be configured to connect to the Web service over an HTTPS connection, and you will provide transport level security when you implement the WCF version of the Web service.

  2. Using Solution Explorer, open the image from book ASPNETProductsService.cs file in the App_Code folder in the C:\\ASPNETProductsService project and examine its contents.

    This Web service should have a familiar look to it; it is an ASP.NET version of the ProductsService service, providing the ListSelectedProducts, GetProduct, CurrentStockLevel, and ChangeStockLevel Web methods.

    The file contains an implementation of the Product class, tagged with the Serializable attribute to enable the ASP.NET runtime to transfer instances back to the ASP.NET client application.

    Notice the namespace and name of the Web service (the ASPNETProductsService class); the WCF version of the Web service will use this same namespace to remain compatible with existing ASP.NET client applications:

     [WebService(Namespace = "http://adventure-works.com/2005/01/01",             Name = "ProductsService")] public class ASPNETProductsService : System.Web.Services.WebService,                                      IProductsService {     … }

    The Web methods use ADO.NET rather than the Microsoft Enterprise Library for accessing the AdventureWorks database (the Web service was created before the Enterprise Library was available). The image from book web.config file contains the connection string that the application uses to connect to the database. If you are not running a local instance of SQL Server Express, you will need to modify the value property of the configuration setting in this file to connect to the correct server.

  3. In the C:\\ASPNETProductsService project, right-click the file image from book ASPNETProductsService.asmx, and then click View in Browser.

    Internet Explorer starts and displays the list of Web methods implemented by the service. Display the WSDL description of the Web service by appending the text “?wsdl” to the end of the address in the Address box, like this:

     http://localhost:7080/ASPNETProductsService/ASPNETProductsService.asmx?wsdl

    In the WSDL document displayed by Internet Explorer, note the following points:

    • The return type of the ListSelectedProducts Web method (List<string>) is serialized as a sequence of strings in a type named ArrayOfString in the http://adventure-works/2005/01/01 schema.

    • The Product type is also in the http://adventure-works/2005/01/01 schema. It has four elements named, in order: Name, ProductNumber, Color, and ListPrice.

    • The SOAP action for the ListSelectedProducts Web method is http://adventure-works/2005/01/01/ListSelectedProducts.

    • The SOAP action for the GetProduct Web method is http://adventure-works/2005/01/01/GetProduct.

    • The SOAP action for the CurrentStockLevel Web method is http://adventure-works/2005/01/01/CurrentStockLevel.

    • The SOAP action for the ChangeStockLevel Web method is http://adventure-works/2005/01/01/ChangeStockLevel.

    Close Internet Explorer when you have finished browsing the WSDL document and return to Visual Studio 2005.

  4. In Solution Explorer, open the image from book Program.cs file in the ASPNETProductsClient project. Again, you should recognize much of the code in this application. It connects to the ASP.NET Web service, and tests each of the Web methods in turn.

    The client application makes use of a Web service proxy generated by Visual Studio 2005 using the Add Web Reference command. You will use this same proxy to connect to the WCF service later.

    Note 

    In the production environment, the Web service uses the ASPNETProductsService certificate to protect communications with the client application (this version of the Web service currently does not use this level of protection because it runs using the ASP.NET Development Server in this exercise). In a subsequent exercise, you will use a test certificate generated by using the makecert utility, so the client application contains code that invokes the Enact method of the PermissiveCertificatePolicy class to bypass certificate verification. Once again, it is worth emphasizing that this code is provided for testing purposes only, and you should never include the PermissiveCertificatePolicy class in a production environment.

  5. Open the image from book app.config file in the ASPNETProductsClient project. This configuration file contains the ASPNETProductsClient_ProductsService_ProductsService setting. This setting was generated by the Add Web Reference command. It specifies the address of the ASP.NET Web service.

  6. Start the solution without debugging. The ASP.NET Development Server starts, and the client application runs. The client application console generates a list of bicycle frames, displays the details of a water bottle, displays the stock level of water bottles, and then updates this stock level.

    Press Enter to close the client application console when the application finished.

You have now seen the existing ASP.NET Web service and client application. Your next task is to implement a WCF service that provides the same functionality. The ASP.NET client application must be able to connect to the WCF service and run unchanged (apart from modifying the configuration file to refer to the new service).

Implement a WCF service to replace the ASP.NET Web service

  1. Add a new project to the solution, using the WCF Service Library template in the Visual C# .NET Framework 3.0 project types. Name the project WCFProductsService and save it in the Microsoft Press\WCF Step By Step\Chapter 16\WCFService folder under your \My Documents folder.

  2. In Solution Explorer, rename the file Class1.cs as image from book ProductsService.cs.

  3. Edit the image from book ProductsService.cs file, and remove all comments and code apart from the using statements at the top of the file.

  4. Add a reference to the System.Configuration assembly to the WCFProductsService project.

  5. Add the following using statements to the image from book ProductsService.cs file:

     using System.Data; using System.Data.SqlClient; using System.Configuration;

  6. Copy the code for the Product class, the IProductsService interface, and the ASPNETProductsService class from the image from book ASPNETProductsService.cs file in the App_Code file in the C:\\ASPNETProductsService project to the image from book ProductsService.cs file.

  7. In the image from book ProductsService.cs file, modify the definition of the Product class as follows:

    • Replace the Serializable attribute for the Product class with the DataContract attribute.

    • Set the Namespace property of this attribute to the namespace expected by the ASP.NET client application.

    • Tag each member of the Product class with a DataMember attribute ensuring that the members are serialized in the order in which they appear in the class and that they have the correct names in the serialization stream.

    The Product class should look like this (the new additions are shown in bold):

     // Data contract describing the details of a product [DataContract (Namespace="http://adventure-works.com/2005/01/01")] public class Product {      [DataMember(Order=0, Name="Name")]      public string Name;      [DataMember(Order = 1, Name = "ProductNumber")]      public string ProductNumber;      [DataMember(Order = 2, Name = "Color")]      public string Color;      [DataMember(Order=3, Name="ListPrice")]      public decimal ListPrice; }

  8. By default, the WCF service will serialize the List<string> value returned by the ListSelectedProducts operation using a different type and schema from that expected by the ASP.NET client application, which expects an ArrayOfString type in the http://adventure-works.com/2005/01/01 namespace. Add the following class to the image from book ProductsService.cs file underneath the Product class:

     // Data contract for seralizing a list of strings // using the same schema as the ASP.NET Web service [CollectionDataContract(Namespace = "http://adventure-works.com/2005/01/01")] public class ArrayOfString : List<string> { }

  9. Make the following modification to the IProductsService interface:

    • Add the ServiceContract attribute shown below in bold. In this attribute, specify the appropriate namespace and name.

    • Mark each operation with an OperationContract interface explicitly specifying the names of the Action and ReplyAction messages.

    • Change the return type of the ListSelectedProducts operation to ArrayOfString.

    The IProductsService interface should look like this (the new additions are shown in bold):

     // ASP.NET compatible version of the service contract [ServiceContract(Namespace = "http://adventure-works.com/2005/01/01",                  Name = "ProductsService",                  SessionMode = SessionMode.Allowed)] public interface IProductsService {     // Get the product number of selected products     [OperationContract(         Action = "http://adventure-works.com/2005/01/01/ListSelectedProducts",         ReplyAction = "http://adventure-works.com/2005/01/01/ListSelectedProducts         Response")]     [TransactionFlow(TransactionFlowOption.Allowed)]     ArrayOfString ListSelectedProducts(string match);     // Get the details of a single product     [OperationContract(         Action = "http://adventure-works.com/2005/01/01/GetProduct",         ReplyAction = "http://adventure-works.com/2005/01/01/GetProductResponse")]     [TransactionFlow(TransactionFlowOption.Allowed)]     Product GetProduct(string productNumber);     // Get the current stock level for a product     [OperationContract(         Action = "http://adventure-works.com/2005/01/01/CurrentStockLevel",         ReplyAction = "http://adventure-works.com/2005/01/01/CurrentStockLevel         Response")]     [TransactionFlow(TransactionFlowOption.Allowed)]     int CurrentStockLevel(string productNumber);     // Change the stock level for a product     [OperationContract(         Action = "http://adventure-works.com/2005/01/01/ChangeStockLevel",         ReplyAction = "http://adventure-works.com/2005/01/01/ChangeStockLevel         Response")]     [TransactionFlow(TransactionFlowOption.Allowed)]     bool ChangeStockLevel(string productNumber, int newStockLevel,                           string shelf, int bin); }

    Note 

    WCF can automatically generate names for the Action and ReplyAction messages based on the namespace and name properties of the service contract, but it is better to be explicit in this case. Additionally, WCF includes the name of the service contract when it generates message names, whereas the ASP.NET client application only expects the messages to be named after the namespace. For example, the default message name generated by WCF for the action for the ListSelectedProducts operation would be http://adventure-works.com/2005/01/01/ProductsService/ListSelectedProducts. However, the ASP.NET client application is expecting the action message to be named http://adventure-works.com/2005/01/01/ListSelectedProducts.

  10. Make the following changes to the definition of the ASPNETProductsService class:

    • Replace the WebService attribute with the ServiceBehavior attribute, retaining existing values for the Namespace and Name properties.

    • Do not inherit from the System.Web.Services.WebService class. This is the base class used by ASP.NET Web services only.

    The definitions of the ASPNETProductsService class should look like this:

     // WCF service class that implements the service contract [ServiceBehavior(Namespace = "http://adventure-works.com/2005/01/01",                  Name = "ProductsService")] public class ASPNETProductsService : IProductsService {      }

  11. Make the following changes to the ListSelectedProducts method in the ASPNETProductsService class:

    • Remove the WebMethod attribute.

    • Change the return type of this method to ArrayOfString.

    • In the body of this method, amend the statement that returns an empty List<string> object to return an ArrayOfString object instead.

    • Modify the statement that declares the productsList local variable. This variable must be an ArrayOfString rather than a List<string>.

     public ArrayOfString ListSelectedProducts(string match) {     // Check for potential SQL Injection attack     if (IsPotentialSqlInjectionAttack(match))     {         return new ArrayOfString();     }     // Read the configuration information for connecting to the          // Create and populate a list of products     ArrayOfString productsList = new ArrayOfString();      }

  1. Remove the WebMethod attribute from the remaining operations–GetProduct, CurrentStockLevel, and ChangeStockLevel.

  2. In Solution Explorer, remove the C:\\ASPNETProductsService project from the solution, and then build the WCFProductsService project.

You will use the familiar WPF application to host the WCF service. This will enable you to implement transport level security for testing purposes.

Configure the WCF host application and service

  1. Add the ProductsServiceHost project located in the Microsoft Press\WCF Step By Step\Chapter 16\ProjectsServiceHost folder under your \My Documents folder to the solution.

  2. Add a reference to the WCFProductsService project to the ProductsServiceHost project.

  3. Open the image from book App.config file in the ProductsServiceHost project.

    The configuration file defines a single service endpoint with an address of https://localhost:8040/ProductsService/ProductsService.svc. The binding this endpoint uses is basicHttpBinding. The BasicHttpBinding binding is designed for maximum interoperability with Web services and client applications that do not make use of any WS-* standards, such as ASP.NET client applications.

    At the end of the configuration file you will find the <appSettings> section. This section contains a single key setting called AdventureWorksConnection, with the value for the connection string for accessing the AdventureWorks database. If you are not using a local instance of SQL Server Express to host the database, you will need to modify this string.

  4. Build the solution.

  5. Open a Windows SDK CMD Shell prompt. Type the following command to create and install the certificate for the ASPNETProductsService service (refer back to Chapter 4, “Protecting an Enterprise WCF Service,” for a detailed explanation of using certificates to provide transport level security):

     makecert -sr LocalMachine -ss My -n CN=ASPNETProductsService -sky exchange

    Tip 

    To open a Windows SDK CMD Shell prompt, on the Windows Start menu point to All Programs, point to Microsoft Windows SDK, and then CMD Shell.

  6. Using the Certificates snap-in in the Microsoft Management Console, retrieve the thumbprint for the ASPNETProductsService service from the Personal certificates store for the local computer (refer back to the section “Configure the WCF HTTP endpoint with an SSL certificate” in Chapter 4 for a detailed description of how to do this).

  7. In the CMD Shell prompt, type the following command to associate the certificate with port 8040 (the port used by the WCF service), replacing the string of digits after the –h flag with the thumbprint of your certificate:

     httpcfg set ssl -i 0.0.0.0:8040 -h cf60efed47ae63d73005c6cfa5807b3673176e98

    Note 

    Under Windows Vista, use the following netsh command, replacing the digits for the certhash parameter with the thumbprint of your certificate:

     netsh http add sslcert ipport=0.0.0.0:8000 certhash= cf60efed47ae63d73005c6cfa5807b3673176e98 appid={}

  8. Close the CMD Shell prompt.

Test the ASP.NET client application

  1. In Solution Explorer, right-click the ProductsServiceHost project, point to Debug, and then click Start new instance. In the ProductsServiceHost form, click Start.

  2. Using Windows Explorer, move to the Microsoft Press\WCF Step By Step\Chapter 16\ASPNETService\ASPNETProductsClient\bin\Debug folder under your \My Documents folder. This folder contains the compiled assembly and configuration file for the ASP.NET client application.

  3. Edit the configuration file ASPNETProductsClient.exe.config by using Notepad. In the <applicationSettings> section of this file, set the ASPNETProductsClient_Products Service_ProductsService setting to https://localhost:8040/ProductsService/ProductsService.svc. This is the URL of the WCF service. Save the file, and then close Notepad.

  4. In Windows Explorer, double-click the file ASPNETProductsClient.exe to start the ASP.NET client application.

    The client application runs exactly as before, except this time it is connecting to the WCF service rather than the ASP.NET Web service. You can verify this if you stop the WCF service and run the ASP.NET client application again; it should fail with the message “Exception: Unable to connect to the remote server.”

The key to building a WCF service that can be accessed by applications created using other technologies is interoperability. You have seen throughout this book how WCF implements many of the standard WS-* standards and protocols, making it compatible with applications and services that adhere to these standards and protocols. To provide connectivity to older applications, like those created by using ASP.NET, you must ensure that you provide a binding that is compatible with the limited functionality available to these applications. For maximum interoperability, you should supply a binding that is compatible with applications that conform to the WS-I Basic Profile. When you are building a WCF service, this essentially means using the BasicHttpBinding binding and not mandating the use of message level security, transactions, or reliable messaging. However, there is nothing to stop you adding further bindings for other capable client applications to use that do enable these features.

image from book
The WS-I Basic Profile and WCF Services

The WS-I Basic Profile constitutes a set of recommendations for building interoperable Web services. It was defined by the Web Services Interoperability Organization and describes how a Web service should apply many of the core Web services specifications that are not covered by the WS-* specifications, such as the SOAP messaging format, generating a WSDL description of a Web service, and defining the metadata to enable Web service discovery using Universal Description, Discovery, and Integration (UDDI). The WS-I Basic Profile essentially describes the lowest common denominator for features that a Web service must provide and remain useful. Web services that conform to the WS-I Basic Profile will be interoperable with client applications and other Web services that also conform to the WS-I Basic Profile. (Web services that implement the WS-* specifications are only interoperable with other Web services that implement the same WS-* specifications.)

You can use the WCF BasicHttpBinding binding to configure and expose endpoints that the service can use to communicate with client applications and services that conform to the WS-I Basic Profile 1.1, including ASP.NET Web client applications.

You can download the specification for the WS-I Basic Profile 1.1 from the WS-I Web site at http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html.

image from book




Microsoft Windows Communication Foundation Step by Step
Microsoft Windows Communication Foundation Step by Step (Step By Step Developer Series)
ISBN: 0735623368
EAN: 2147483647
Year: 2007
Pages: 105
Authors: John Sharp

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net