- •Contents at a Glance
- •Table of Contents
- •Acknowledgments
- •Introduction
- •Who This Book Is For
- •Finding Your Best Starting Point in This Book
- •Conventions and Features in This Book
- •Conventions
- •Other Features
- •System Requirements
- •Code Samples
- •Installing the Code Samples
- •Using the Code Samples
- •Support for This Book
- •Questions and Comments
- •Beginning Programming with the Visual Studio 2008 Environment
- •Writing Your First Program
- •Using Namespaces
- •Creating a Graphical Application
- •Chapter 1 Quick Reference
- •Understanding Statements
- •Identifying Keywords
- •Using Variables
- •Naming Variables
- •Declaring Variables
- •Working with Primitive Data Types
- •Displaying Primitive Data Type Values
- •Using Arithmetic Operators
- •Operators and Types
- •Examining Arithmetic Operators
- •Controlling Precedence
- •Using Associativity to Evaluate Expressions
- •Associativity and the Assignment Operator
- •Incrementing and Decrementing Variables
- •Declaring Implicitly Typed Local Variables
- •Chapter 2 Quick Reference
- •Declaring Methods
- •Specifying the Method Declaration Syntax
- •Writing return Statements
- •Calling Methods
- •Specifying the Method Call Syntax
- •Applying Scope
- •Overloading Methods
- •Writing Methods
- •Chapter 3 Quick Reference
- •Declaring Boolean Variables
- •Using Boolean Operators
- •Understanding Equality and Relational Operators
- •Understanding Conditional Logical Operators
- •Summarizing Operator Precedence and Associativity
- •Using if Statements to Make Decisions
- •Understanding if Statement Syntax
- •Using Blocks to Group Statements
- •Cascading if Statements
- •Using switch Statements
- •Understanding switch Statement Syntax
- •Following the switch Statement Rules
- •Chapter 4 Quick Reference
- •Using Compound Assignment Operators
- •Writing while Statements
- •Writing for Statements
- •Understanding for Statement Scope
- •Writing do Statements
- •Chapter 5 Quick Reference
- •Coping with Errors
- •Trying Code and Catching Exceptions
- •Handling an Exception
- •Using Multiple catch Handlers
- •Catching Multiple Exceptions
- •Using Checked and Unchecked Integer Arithmetic
- •Writing Checked Statements
- •Writing Checked Expressions
- •Throwing Exceptions
- •Chapter 6 Quick Reference
- •The Purpose of Encapsulation
- •Controlling Accessibility
- •Working with Constructors
- •Overloading Constructors
- •Understanding static Methods and Data
- •Creating a Shared Field
- •Creating a static Field by Using the const Keyword
- •Chapter 7 Quick Reference
- •Copying Value Type Variables and Classes
- •Understanding Null Values and Nullable Types
- •Using Nullable Types
- •Understanding the Properties of Nullable Types
- •Using ref and out Parameters
- •Creating ref Parameters
- •Creating out Parameters
- •How Computer Memory Is Organized
- •Using the Stack and the Heap
- •The System.Object Class
- •Boxing
- •Unboxing
- •Casting Data Safely
- •The is Operator
- •The as Operator
- •Chapter 8 Quick Reference
- •Working with Enumerations
- •Declaring an Enumeration
- •Using an Enumeration
- •Choosing Enumeration Literal Values
- •Choosing an Enumeration’s Underlying Type
- •Working with Structures
- •Declaring a Structure
- •Understanding Structure and Class Differences
- •Declaring Structure Variables
- •Understanding Structure Initialization
- •Copying Structure Variables
- •Chapter 9 Quick Reference
- •What Is an Array?
- •Declaring Array Variables
- •Creating an Array Instance
- •Initializing Array Variables
- •Creating an Implicitly Typed Array
- •Accessing an Individual Array Element
- •Iterating Through an Array
- •Copying Arrays
- •What Are Collection Classes?
- •The ArrayList Collection Class
- •The Queue Collection Class
- •The Stack Collection Class
- •The Hashtable Collection Class
- •The SortedList Collection Class
- •Using Collection Initializers
- •Comparing Arrays and Collections
- •Using Collection Classes to Play Cards
- •Chapter 10 Quick Reference
- •Using Array Arguments
- •Declaring a params Array
- •Using params object[ ]
- •Using a params Array
- •Chapter 11 Quick Reference
- •What Is Inheritance?
- •Using Inheritance
- •Base Classes and Derived Classes
- •Calling Base Class Constructors
- •Assigning Classes
- •Declaring new Methods
- •Declaring Virtual Methods
- •Declaring override Methods
- •Understanding protected Access
- •Understanding Extension Methods
- •Chapter 12 Quick Reference
- •Understanding Interfaces
- •Interface Syntax
- •Interface Restrictions
- •Implementing an Interface
- •Referencing a Class Through Its Interface
- •Working with Multiple Interfaces
- •Abstract Classes
- •Abstract Methods
- •Sealed Classes
- •Sealed Methods
- •Implementing an Extensible Framework
- •Summarizing Keyword Combinations
- •Chapter 13 Quick Reference
- •The Life and Times of an Object
- •Writing Destructors
- •Why Use the Garbage Collector?
- •How Does the Garbage Collector Work?
- •Recommendations
- •Resource Management
- •Disposal Methods
- •Exception-Safe Disposal
- •The using Statement
- •Calling the Dispose Method from a Destructor
- •Making Code Exception-Safe
- •Chapter 14 Quick Reference
- •Implementing Encapsulation by Using Methods
- •What Are Properties?
- •Using Properties
- •Read-Only Properties
- •Write-Only Properties
- •Property Accessibility
- •Understanding the Property Restrictions
- •Declaring Interface Properties
- •Using Properties in a Windows Application
- •Generating Automatic Properties
- •Initializing Objects by Using Properties
- •Chapter 15 Quick Reference
- •What Is an Indexer?
- •An Example That Doesn’t Use Indexers
- •The Same Example Using Indexers
- •Understanding Indexer Accessors
- •Comparing Indexers and Arrays
- •Indexers in Interfaces
- •Using Indexers in a Windows Application
- •Chapter 16 Quick Reference
- •Declaring and Using Delegates
- •The Automated Factory Scenario
- •Implementing the Factory Without Using Delegates
- •Implementing the Factory by Using a Delegate
- •Using Delegates
- •Lambda Expressions and Delegates
- •Creating a Method Adapter
- •Using a Lambda Expression as an Adapter
- •The Form of Lambda Expressions
- •Declaring an Event
- •Subscribing to an Event
- •Unsubscribing from an Event
- •Raising an Event
- •Understanding WPF User Interface Events
- •Using Events
- •Chapter 17 Quick Reference
- •The Problem with objects
- •The Generics Solution
- •Generics vs. Generalized Classes
- •Generics and Constraints
- •Creating a Generic Class
- •The Theory of Binary Trees
- •Building a Binary Tree Class by Using Generics
- •Creating a Generic Method
- •Chapter 18 Quick Reference
- •Enumerating the Elements in a Collection
- •Manually Implementing an Enumerator
- •Implementing the IEnumerable Interface
- •Implementing an Enumerator by Using an Iterator
- •A Simple Iterator
- •Chapter 19 Quick Reference
- •What Is Language Integrated Query (LINQ)?
- •Using LINQ in a C# Application
- •Selecting Data
- •Filtering Data
- •Ordering, Grouping, and Aggregating Data
- •Joining Data
- •Using Query Operators
- •Querying Data in Tree<TItem> Objects
- •LINQ and Deferred Evaluation
- •Chapter 20 Quick Reference
- •Understanding Operators
- •Operator Constraints
- •Overloaded Operators
- •Creating Symmetric Operators
- •Understanding Compound Assignment
- •Declaring Increment and Decrement Operators
- •Implementing an Operator
- •Understanding Conversion Operators
- •Providing Built-In Conversions
- •Creating Symmetric Operators, Revisited
- •Adding an Implicit Conversion Operator
- •Chapter 21 Quick Reference
- •Creating a WPF Application
- •Creating a Windows Presentation Foundation Application
- •Adding Controls to the Form
- •Using WPF Controls
- •Changing Properties Dynamically
- •Handling Events in a WPF Form
- •Processing Events in Windows Forms
- •Chapter 22 Quick Reference
- •Menu Guidelines and Style
- •Menus and Menu Events
- •Creating a Menu
- •Handling Menu Events
- •Shortcut Menus
- •Creating Shortcut Menus
- •Windows Common Dialog Boxes
- •Using the SaveFileDialog Class
- •Chapter 23 Quick Reference
- •Validating Data
- •Strategies for Validating User Input
- •An Example—Customer Information Maintenance
- •Performing Validation by Using Data Binding
- •Changing the Point at Which Validation Occurs
- •Chapter 24 Quick Reference
- •Querying a Database by Using ADO.NET
- •The Northwind Database
- •Creating the Database
- •Using ADO.NET to Query Order Information
- •Querying a Database by Using DLINQ
- •Creating and Running a DLINQ Query
- •Deferred and Immediate Fetching
- •Joining Tables and Creating Relationships
- •Deferred and Immediate Fetching Revisited
- •Using DLINQ to Query Order Information
- •Chapter 25 Quick Reference
- •Using Data Binding with DLINQ
- •Using DLINQ to Modify Data
- •Updating Existing Data
- •Adding and Deleting Data
- •Chapter 26 Quick Reference
- •Understanding the Internet as an Infrastructure
- •Understanding Web Server Requests and Responses
- •Managing State
- •Understanding ASP.NET
- •Creating Web Applications with ASP.NET
- •Building an ASP.NET Application
- •Understanding Server Controls
- •Creating and Using a Theme
- •Chapter 27 Quick Reference
- •Comparing Server and Client Validations
- •Validating Data at the Web Server
- •Validating Data in the Web Browser
- •Implementing Client Validation
- •Chapter 28 Quick Reference
- •Managing Security
- •Understanding Forms-Based Security
- •Implementing Forms-Based Security
- •Querying and Displaying Data
- •Understanding the Web Forms GridView Control
- •Displaying Customer and Order History Information
- •Paging Data
- •Editing Data
- •Updating Rows Through a GridView Control
- •Navigating Between Forms
- •Chapter 29 Quick Reference
- •What Is a Web Service?
- •The Role of SOAP
- •What Is the Web Services Description Language?
- •Nonfunctional Requirements of Web Services
- •The Role of Windows Communication Foundation
- •Building a Web Service
- •Creating the ProductsService Web Service
- •Web Services, Clients, and Proxies
- •Talking SOAP: The Easy Way
- •Consuming the ProductsService Web Service
- •Chapter 30 Quick Reference
Chapter 30 Creating and Using a Web Service |
627 |
The Role of Windows Communication Foundation
As standardization of Web services security, policy, and addressing became more important, Microsoft provided its own implementation of the WS-Security, WS-Policy, and WSAddressing specifications in its Web Services Enhancements (WSE) package, available as a free download from the Microsoft Web site. What does all this mean if you are developing Web services using Visual Studio 2008? Well, with Visual Studio 2008, you can build Web services by using two technologies—ASP.NET and WCF. Ordinary ASP.NET Web services do not directly support the various WS-* specifications. Instead, you can use Microsoft’s WSE package to provide features such as security.
So, by using Visual Studio, the .NET Framework, and WSE, you can quickly build Web services and client applications that can communicate and interoperate with Web services and client applications running on any operating system. Why then do you need WCF? Well, first, WCF is a more recent technology that emerged as part of version 3.0 of the .NET Framework. It provides its own fully integrated implementation of the common WS-* specifications without requiring you to download, install, and configure additional packages. Second, Web services are just one technology that you can use to create distributed applications for the Windows operating systems. Others include Enterprise Services, .NET Framework Remoting, and Microsoft Message Queue (MSMQ). If you are building a distributed application for Windows, which technology should you use, and how difficult will it be to switch later if you need to? The purpose of WCF is to provide a unified programming model for many of these technologies so that you can build applications that are as independent as possible from the underlying mechanism being used to connect services and applications. (Note that WCF applies as much to services operating in non-Web environments as it does to the World Wide Web.) It is actually very difficult, if not impossible, to completely divorce the programmatic structure of an application or service from its communications infrastructure, but WCF lets you come very close to achieving this aim much of the time. Additionally, by using WCF, you can maintain backward compatibility with many of the earlier technologies. For example, a WCF client application can easily communicate with a Web service that you created by using WSE.
To summarize, if you are considering building distributed applications and services for Windows, you should use WCF. The exercises in this chapter will show you how.
Building a Web Service
In this section, you will create the ProductsService Web service. This Web service exposes two Web methods. The first method enables the user to calculate the cost of buying a specified quantity of a particular product in the Northwind database, and the second method takes the name of a product and returns all the details for that product.
628 Part VI Building Web Applications
Creating the ProductsService Web Service
In the first exercise, you will create the ProductsService Web service and examine the
example code generated by Visual Studio 2008 whenever you create a new WCF service project. In subsequent exercises, you will define and implement the HowMuchWillItCost Web
method and then test the Web method to ensure that it works as expected.
Create the Web service, and examine the example code
1.Start Visual Studio 2008 if it is not already running.
2.If you are using Visual Studio 2008 Professional Edition or Enterprise Edition, on the File menu, point to New, and then click Web Site.
3.If you are using Microsoft Visual Web Developer 2008 Express Edition, on the File menu, click New Web Site.
4.In the New Web Site dialog box, click the WCF Service template. Select File System in the Location drop-down list box, and specify the \Microsoft Press\Visual CSharp Step
By Step\Chapter 30\NorthwindServices folder under your Documents folder. Set the
Language to Visual C#, and then click OK.
Visual Studio 2008 generates a Web site containing folders called App_Code and
App_Data, a file called Service.svc, and a configuration file called Web.config. The code for an example Web service is defined in the Service class, stored in the file Service.cs in the App_Code folder, and displayed in the Code and Text Editor window. The Service class implements an example interface called IService, stored in the file IService.cs in the App_Code folder.
5.Click the C:\...\NorthwindServices\ project. In the Properties window, set the Use dynamic ports property to False, and set the Port number property to 4500.
By default, the Development Web server provided with Visual Studio 2008 picks a port at random to reduce the chances of clashing with any other ports used by other network services running on your computer. This feature is useful if you are building and testing ASP.NET Web sites in a development environment prior to copying them to a production server such as Microsoft Internet Information Services (IIS). However, when building a Web service, it is more useful to use a fixed port number because client applications need to be able to connect to it.
6.Expand the App_Code folder, right-click the Service.cs file, and then click Rename. Change the name of the file to ProductsService.cs.
7.Using the same technique, change the name of the IService.cs file to IProductsService.cs.
8.Double-click the IProductsService.cs file to display it in the Code and Text Editor window.
Chapter 30 Creating and Using a Web Service |
629 |
This file contains the definition of an interface called IService. At the top of the IProductsService.cs file, you will find using statements referencing the System, System. Collections.Generic, and System.Text namespaces (which you have met before), followed by two additional statements referencing the System.ServiceModel and System.Runtime. Serialization namespaces.
The System.ServiceModel namespace contains the classes used by WCF for defining services and their operations. WCF uses the classes in the System.Runtime.Serialization
namespace to convert objects to a stream of data for transmission over the network (a process known as serialization) and to convert a stream of data received from the
network back to objects (deserialization). You will learn a little about how WCF serializes and deserializes objects later in this chapter.
The primary contents of the IProductsService file are an interface called IService and a class called CompositeType. The IService interface is prefixed with the ServiceContract attribute, and the CompositeType class is tagged with the DataContract attribute.
Because of the structure of a WCF service, you can adopt a “contract-first” approach to
development. When performing contract-first development, you define the interfaces, or contracts, that the service will implement, and then you build a service that conforms
to these contracts. This is not a new technique, and you have seen examples of this strategy throughout this book. The point behind using contract-first development is that you can concentrate on the design of your service. If necessary, it can quickly be reviewed to ensure that your design does not introduce any dependencies on specific hardware or software before you perform too much development; remember that in many cases client applications might not be built using WCF and might not even be running on Windows.
The ServiceContract attribute marks an interface as defining methods that the class
implementing the Web service will expose as Web methods. The methods themselves are tagged with the OperationContract attribute. The tools provided with Visual Studio
2008 use these attributes to help generate the appropriate WSDL document for the service. Any methods in the interface not marked with the OperationContract attribute
will not be included in the WSDL document and therefore will not be accessible to client applications using the Web service.
If a Web method takes parameters or returns a value, the data for these parameters and value must be converted to a format that can be transmitted over the network and then converted back again to objects—this is the process known as serialization and deserialization mentioned earlier. The various Web services standards define mechanisms for specifying the serialized format of simple data types, such as numbers and strings, as part of the WSDL description for a Web service. However, you can also define your own complex data types based on classes and structures. If you make use of these
types in a Web service, you must provide information on how to serialize and deserialize them. If you look at the definition of the GetDataUsingDataContract method in the
630 Part VI Building Web Applications
IService interface, you can see that it expects a parameter of the type CompositeType. The CompositeType class is marked with the DataContract attribute, which specifies that
the class must define a type that can be serialized and deserialized as an XML stream
as part of a SOAP request or response message. Each member that you want to include in the serialized stream sent over the network must be tagged with the DataMember
attribute.
9.Double-click the ProductsService.cs file to display it in the Code and Text Editor window.
This file contains a class called Service that implements the IService interface and provides the GetData and GetDataUsingDataContract methods defined by this interface. This class is the Web service. When a client application invokes a Web method in this Web service, it generates a SOAP request message and sends it to the Web server hosting the Web service. The Web server creates an instance of this class and runs the corresponding method. When the method completes, the Web server constructs a SOAP response message, which it sends back to the client application.
10.Double-click the Service.svc file to display it in the Code and Text Editor window.
This is the service file for the Web service; it is used by the host environment (IIS, in this case) to determine which class to load when it receives a request from a client application.
Note If the Error List window is open, you will notice that the Service.svc file appears to contain two errors: “Keyword, identifier, or string expected after verbatim specifier: @” and “A namespace does not directly contain members such as fields or methods.” When you rebuild the solution later, these errors will disappear and you can safely ignore them.
The Service property of the @ ServiceHost directive specifies the name of the Web service class, and the CodeBehind property specifies the location of the source code for
this class.
Tip If you don’t want to deploy the source code for your WCF service to the Web server,
you can provide a compiled assembly instead. You can then specify the name and location of this assembly by using the @ Assembly directive. For more information, search for
“@ Assembly directive” in the documentation provided with Visual Studio 2008.
Now that you have seen the structure of a WCF service, you can define the interface and class that specifies the service and data contracts for the ProductsService Web service and then create a class that implements the service contract.
Chapter 30 Creating and Using a Web Service |
631 |
Define the contracts for the ProductsService Web service
1.Display the IProductsService.cs file in the Code and Text Editor window. Change the name of the IService interface to IProductsService, as shown here in bold type:
[ServiceContract]
public interface IProductsService
{
...
}
2.In the IProductsService interface, remove the definitions of the GetData and
GetDataUsingDataContract methods, and replace them with the HowMuchWillItCost and GetProductInfo methods, shown in the following code. Make sure you retain the OperationContract attribute for each Web method.
[ServiceContract]
public interface IProductsService
{
[OperationContract]
decimal HowMuchWillItCost(int productID, int howMany);
[OperationContract]
ProductInfo GetProductInfo(int productID);
}
The HowMuchWillItCost method takes a product ID and a quantity and returns a decimal value specifying the amount this quantity will cost.
The GetProductInfo method takes a product ID and returns a ProductInfo object containing the details of the specified product. You will define the ProductInfo class in
the next step.
3.Remove the CompositeType class from the IProductsService.cs file, and add the ProductInfo class, including the DataContract attribute, like this:
[DataContract]
public class ProductInfo
{
}
4.Add the following public properties to the ProductInfo class. There is one property for each of the columns in the Products table in the database. Mark each property with the
DataMember attribute:
[DataContract]
public class ProductInfo
{
[DataMember]
public int ProductID {get; set;}
[DataMember]
public string ProductName {get; set;}
632 |
Part VI Building Web Applications |
[DataMember]
public int? SupplierID {get; set;}
[DataMember]
public int? CategoryID {get; set;}
[DataMember]
public string QuantityPerUnit {get; set;}
[DataMember]
public decimal? UnitPrice {get; set;}
[DataMember]
public short? UnitsInStock {get; set;}
[DataMember]
public short? UnitsOnOrder {get; set;}
[DataMember]
public short? ReorderLevel {get; set;}
[DataMember]
public bool? Discontinued {get; set;}
}
Notice that the properties that correspond to columns that allow null values in the database are defined by using nullable types (apart from QuantityPerUnit, which is a reference type that allows null values automatically because it is a string). Also, you
should ensure that all properties support read and write access. The serialization mechanism used by WCF is automatic and largely transparent as long as you follow a few simple rules when defining the class. In particular, serialization can be used only when the runtime transmits objects that contain public fields and properties; private members will not be serialized. Also note that all properties must have both get and set accessors. This is because the XML serialization process must be able to write this data back to the object after it has been transferred. Additionally, the class must provide a default (with no parameters) constructor.
It is common to design classes used for SOAP purely as containers for transmitting data. If necessary, you can define additional functional classes that act as façades, providing the business logic for these data structures. Users and applications can gain access to the data by using these business façades.
Note You can customize the serialization mechanism using the various SOAP attribute classes of the System.Xml.Serialization namespace or define your own XML serialization mechanism by implementing the ISerializable interface of the System.Runtime.Serialization
namespace.
Chapter 30 Creating and Using a Web Service |
633 |
The next stage is to define the ProductsService class that implements the IProductsService interface. The methods in this class will retrieve product information from the Northwind database, so you will start by adding an entity class and data context for retrieving this information.
Implement the IProductsService interface
1.On the Website menu, click Add New Item.
2.In the Add New Item dialog box, click the LINQ to SQL Classes template, type Product. dbml in the Name text box, select Visual C# in the Language drop-down list, and then click Add.
3.If you are using Visual Studio 2008 Professional Edition or Enterprise Edition, on the
View menu, click Server Explorer.
4.If you are using Visual Web Developer 2008 Express Edition, on the View menu, click
Database Explorer.
5.In Server Explorer (if you are using Visual Studio 2008) or Database Explorer (if you are
using Visual Web Developer 2008 Express Edition), expand the data connection for the Northwind database (YourComputer\sqlexpress.Northwind.dbo or Northwind.mdf), and then expand Tables.
6.Click the Products table, and drag it onto the Object Relational Designer window.
7.On the File menu, click Save All.
8.Display the ProductsService.cs file in the Code and Text Editor window. Remove the Service class from this file.
9.Add the ProductsService class to the file, and specify that it should implement the IProductsService interface, as shown here:
public class ProductsService : IProductsService
{
}
10. Add the HowMuchWillItCost method to the Service class, as follows:
public class ProductsService : IProductsService
{
public decimal HowMuchWillItCost(int productID, int howMany)
{
ProductDataContext pdc = new ProductDataContext(); decimal? cost = pdc.Products.Single(
p => p.ProductID == productID).UnitPrice;
decimal totalCost = 0; if (cost.HasValue)
634 |
Part VI Building Web Applications |
{
totalCost = cost.Value * howMany;
}
return totalCost;
}
}
This method connects to the database and executes a DLINQ query to retrieve the cost of the product matching the supplied product ID from the Northwind database. If the cost returned is not null, the method calculates the total cost of the request and returns it; otherwise, the method returns the value 0.
Note This method performs no validation of the input parameters. For example, you can specify a negative value for the howMany parameter. In a production Web service, you
would trap errors such as this, log them, and return an exception. However, transmitting meaningful reasons for an exception back to a client application has security implications
in a WCF service. The details are beyond the scope of this book. For more information, see
Microsoft Windows Communication Foundation Step by Step.
11. Add the GetProductInfo method shown below in bold type to the Service class:
public class ProductsService : IProductsService
...
public ProductInfo GetProductInfo(int productID)
{
ProductDataContext pdc = new ProductDataContext();
Product product = pdc.Products.Single(p => p.ProductID == productID);
ProductInfo prodInfo = null; if (product != null)
{
prodInfo = new ProductInfo(); prodInfo.CategoryID = product.CategoryID; prodInfo.Discontinued = product.Discontinued; prodInfo.ProductID = product.ProductID; prodInfo.ProductName = product.ProductName;
prodInfo.QuantityPerUnit = product.QuantityPerUnit; prodInfo.ReorderLevel = product.ReorderLevel; prodInfo.SupplierID = product.SupplierID; prodInfo.UnitPrice = product.UnitPrice; prodInfo.UnitsInStock = product.UnitsInStock; prodInfo.UnitsOnOrder = product.UnitsOnOrder;
}
return prodInfo;
}
}
These statements use DLINQ to connect to the Northwind Traders database and
retrieve the details for the specified product from the database. Note that like the HowMuchWillItCost method, this method does not handle exceptions.
Chapter 30 Creating and Using a Web Service |
635 |
Before you can use the Web service, you must update the configuration in the Service.svc file to refer to the ProductsService class in the ProductsService.cs file. You must also modify the
Web.config file to reflect the new name of the Web service.
Configure the Web service
1.In Solution Explorer, double-click the Service.svc file to display it in the Code and Text Editor window. Update the Service and CodeBehind attributes of the ServiceHost directive, as shown here in bold type:
<%@ ServiceHost Language=”C#” Debug=”true” Service=”ProductsService” CodeBehind=”~/App_Code/ProductsService.cs” %>
Note The Error List window for the Service.svc file might display the same errors as before. Again, these errors should disappear when you rebuild the application, so you can safely ignore them.
2.In Solution Explorer, double-click the Web.config file. In the Code and Text Editor window, locate the <system.serviceModel> element. This element contains the following <services> element, specifying the endpoint binding information for the Web
service implemented by this solution. (You can ignore the service that implements the IMetadataExchange contract in this chapter.)
<system.serviceModel>
<services>
<service name=”Service” behaviorConfiguration=”ServiceBehavior”> <!-- Service Endpoints -->
<endpoint address=”” binding=”wsHttpBinding” contract=”IService”/>
...
</service>
</services>
<behaviors>
...
</behaviors>
</system.serviceModel>
WCF uses the notion of endpoints to associate a network address with a specific Web
service. If you are hosting a Web service by using IIS or the ASP.NET Development Server, you should leave the address property of your endpoint blank because IIS listens
for incoming requests on an address specified by its own configuration information.
Note You can build your own custom host applications if you don’t want to use IIS or the ASP.NET Development Server. In these situations, you must specify an address for the ser-
vice as part of the endpoint definition. For more information about endpoints and custom hosts, see Microsoft Windows Communication Foundation Step by Step.
636 |
Part VI Building Web Applications |
3.In the Web.config file, change the name attribute of the Service element and the contract attribute of the endpoint element to refer to the ProductsService service and the IProductsService contract, as shown here in bold type:
<system.serviceModel>
<services>
<service name=”ProductsService” behaviorConfiguration=”ServiceBehavior”> <!-- Service Endpoints -->
<endpoint address=”” binding=”wsHttpBinding” contract=”IProductsService”/>
...
</service>
</services>
<behaviors>
...
</behaviors>
</system.serviceModel>
4.On the File menu, click Save All.
5.In Solution Explorer, right-click Service.svc, and then click View in Browser.
Internet Explorer starts and displays the following page, confirming that you have successfully created and deployed the Web service and providing helpful information describing how to create a simple client application that can access the Web service.
Note If you click the link shown on the Web page (http://localhost:4500/ NorthwindServices/Service.svc?wsdl), Internet Explorer displays a page containing the
WSDL description of the Web service. This is a long and complicated piece of XML, but Visual Studio 2008 can take the information in this description and use it to generate a class that a client application can use to communicate with the Web service.
6. Close Internet Explorer, and return to Visual Studio 2008.
