In this part of the lab, you'll make changes to the configuration file so that metadata can be viewed in a browser.
Figure 1-25.Creating a new web site with the WCF Service template
Figure 1-26. Solution Explorer view of a new web site based on the WCF Service template
Before making any changes, test the web endpoint in a browser. Go to Solution Explorer and right-click on the web site project node; select "Set as Startup Project." Run the web site from within Visual Studio (F5). This launches the service endpoint located at http://localhost/IISHostedService/Service.svc in a browser. What you should see is a web page indicating that metadata publishing has been disabled for the service.
Add metadata support to the service model configuration for the web site. Open the web.config file and modify the previously generated service behavior to add the<serviceMetadata>behavior. You will also add a metadata exchange endpoint for the service. The changes are shown in bold in Example1-14.
Example 1-14. Adding metadata browsing support to the web host
Run the web site again (F5). This time you should see the service help page in the browser, providing some instructions for SvcUtil. Leave the browser running and return to Visual Studio.
Without restarting the host, you're going to make a change that enables HTTP GET access to the service metadata. Open the web.config file and sethttpGetEnabledtotrue for the<serviceMetadata>behavior:
Save this change and return to the browser instance showing the service help page.
Refresh the browser (F5) to see what has changed. This time, you should observe the SvcUtil instruction has an active link with a ?wsdl suffix after the service endpoint (see Figure 1-27). Click the link, and you'll be taken to the WSDL document for the service (see Figure 1-28).
In this part of the lab, you will export the service metadata to a set of files that can later be distributed and used to generate a proxy, offline. The files exported will be WSDL documents.
Launch the Visual Studio 2005 Command Prompt. Run the following command to instruct SvcUtil to export the service metadata and its associated schemas for theHelloIndigoService:
This will generate two .wsdl files and two .xsd files in the solution directory.
Figure 1-27. Browsing to the service help page with metadata browsing enabled
Use these files to generate the application configuration and proxy required for clients to consume the service. In the same command window, execute the following command:
The result of this command will be serviceproxy.cs and app.config files generated for the client application.
Add the two files just generated to the client project. The proxy and configuration will be used to invoke the service hosted in IIS. Go to theClientproject and refresh the file list in Solution Explorer. You should see the two new files appear; include them in the project.
Invoke the service using the generated proxy. Open Program.cs in the code window and modify theMain()entry point adding code to create a proxy and invoke theHelloIndigo()operation. The resulting additions are shown in bold in Example1-15.
Compile and run theClientproject. The output should be similar to that in earlier labs.
Figure 1-28.Browsing to the dynamically generated WSDL document
Example 1-15. Invoking a service hosted in IIS through its proxy
static void Main(string[] args) { HelloIndigoServiceClient proxy = new HelloIndigoServiceClient() string s = proxy.HelloIndigo(); Console.WriteLine(s); Console.WriteLine("Press <ENTER> to terminate Client."); Console.ReadLine(); }
Many web site templates exist for creating new ASP.NET applications, so it shouldn't surprise you that there is a template to get you started with WCF. The new WCF Service template can be used to create a new web site that is file-based or hosted in IIS. This lab illustrates how to create an IIS-hosted site--the preferred way to test your services if you want an accurate depiction of security-related behavior. Regardless, if you create an IIS- or file-based web site, the files generated are the same:
A sample service contract and implementation
A .svc endpoint for the sample service
A web.config file with service model configuration settings for the sample service
@ServiceHost Declarations
IIS hosting requires a file-based endpoint with a .svc extension. That's because it relies on file-extension mappings to determine how incoming requests should be delegated. The .svc extension is a new extension specific to WCF, and IIS knows to pass those requests to the service model for processing (via ASP.NET). In this hosting environment, each unique service must have a .svc endpoint. Chapter 4 discusses hosting in detail.
The .svc endpoint has one job to do--help the service model find the correct service type to host. The@ServiceHostdirective is the link between the incoming request and the service model. In theory this directive can point to a service type declared with inline code based on a source file or belonging to a compiled assembly.
Similar to inline ASMX web services, .svc files can contain the actual source code for the service contract and type. This makes it possible to deploy just the .svc file without any accompanying source, as shown in Example 1-16. In this case, theServiceattribute refers to the inline service type, and you can even enable inline debugging by setting theDebugattribute totrue. Although ASP.NET 2.0 introduced the possibility of compiling this inline code into an application assembly to protect the source, I still consider this a tight coupling of the service implementation to the hosting environment--and that doesn't promote reuse or deployment flexibility.
[ServiceContract()] public interface IMyService { [OperationContract] string SomeOperation(string myValue); }
public class MyService: IMyService { public string SomeOperation(string myValue) { return "Hello: " + myValue; } }
Another approach is to associate the .svc file with a code file in the web site as the original sample service did in this lab. For ASP.NET 2.0 web sites this means placing the source in the \App_Code directory. In this case, theServiceattribute still refers to the service type, but theCodeBehindattribute is present to indicate the location of its source file:
This approach still couples the source to the host and lacks autonomous version control over services apart from their host.
Ultimately, the preferred way to associate a service type with its .svc endpoint is to add an assembly reference to the project and specify the fully qualified service type in theServiceattribute:
This approach gives you the desired autonomy and reuse for the service.
Message-Based Activation
One of the benefits of using a fully featured host such as IIS or WAS is that it handles service activation on your behalf as messages arrive to the service. In the first and second labs in this chapter, you hosted a service in a console application. In all such self-hosting environments, you must explicitly run the host process before clients can invoke the service. The ServiceHost instance is constructed and opened explicitly, and its lifetime is tied to the lifetime of the host process.
IIS and WAS, on the other hand, are system services that are equipped to process incoming messages even if theServiceHosthas not yet been constructed. For example, when a request arrives for a particular .svc endpoint, the request is ultimately forwarded to the service model. The service model looks at the@ServiceHostdeclaration to find the associated service type. It then instantiates theServiceHost instance for that type on your behalf, within an ASP.NET worker process. The web.config settings are used to initialize theServiceHostand thenOpen()is called--at which point the first request is forwarded to the appropriate channel listener. Once theServiceHost has been constructed and opened, subsequent requests for the same service are directed to it. Simply put, with IIS or WAS hosting, you needn't manually create theServiceHostinstance--this is handled for you by the host process. This is called message-based activation. The details of hosting are discussed in Chapter4 .
Another convenience of IIS and WAS hosting is that you can modify web.config settings for a service and the changes are reflected in subsequent calls without restarting IIS or WAS. That's because changes to configuration files are detected, and if necessary, a new application domain is constructed to service requests. For example, if changes to the service model configuration require that a newServiceHost instance be constructed to reflect the changes. In a self-hosting environment, new settings are not known to the host process and thus are not reflected until you restart. You could optionally build logic into the host to detect changes and recycle anyServiceHostinstances. With IIS and WAS, configuration changes are detected and a newServiceHostis created to handle subsequent requests.
To consume a service, clients require access to service metadata, including the service contract, any custom data types, and binding requirements. Earlier in this chapter, you learned how to enable the service metadata behavior and how to expose a metadata exchange endpoint to support proxy generation using SvcUtil. This lab illustrates how to view metadata in the browser and how to export that metadata to files for offline consumption. This capability is useful for a few reasons:
For debugging purposes, it can be helpful to view the WSDL document, for example when trying to solve interoperability issues between platforms.
Allowing client developers to eat up web server resources by browsing to dynamically created metadata is suboptimal. Instead, once the contract is stable, you should export it and allow developers to browse static files.
It may be helpful to send developers the WSDL document via some other delivery mechanism such as email. This way they can generate proxies while offline.
Browsing metadata
Services may expose one or more endpoints, all of which are included in the service metadata. When a WSDL document is generated, for example, this document describes the contracts exposed across all endpoints. In other words, the WSDL document is one-to-one with the service. You can browse to any service if they have an HTTP base address. In the case of self-hosting environments, the <host> section of the service configuration can supply the base address.
For services hosted in IIS, the base address is the application directory in IIS with the .svc endpoint. For example, in this lab you would browse to http://localhost/IISHostedService/Service.svc.
When you browse to a service's base address you are presented with the service help page. The service model dynamically generates this for you. If you haven't enabled the metadata behavior, the help page will still be presented with instructions on how to do this. If you have enabled the metadata behavior but have forgotten to enable browsing, you'll receive the same instructions. In configuration, if you sethttpGetEnabledtotrue, the help page will produce a link to the WSDL document (Figures 1-27 and 1-28):
The service metadata behavior is required if you expose a metadata exchange endpoint for generating proxies, but you may want to explicitly disable both the help page and metadata browsing by adding the service debug behavior withhttpHelpPageEnabledset tofalseand by settinghttpGetEnabledtofalse:
The WSDL document is dynamically generated each time metadata is accessed. During development this is a useful feature to have, but once you publish your service to production, it may be desirable to suppress dynamic generation to reduce overhead on the web server. But what if you want to provide a link to static metadata? An alternative is to leave metadata browsing enabled and provide a static file where the WSDL document can be retrieved. This is achieved by providing a value for theexternalMetadataLocationattribute:
To produce a static WSDL document, you can export service metadata using SvcUtil, as illustrated in this lab. SvcUtil uses the mex endpoint to retrieve service metadata and save it to a WSDL document that can be stored on the filesystem.
The command switch for SvcUtil to export metadata is/t:metadata. This command dumps the service metadata to several .wsdl and .xsd files in the specified directory:
The service model spreads the service description across multiple files. These files have a hierarchical relationship where a root .wsdl imports child .wsdl and .xsd files. In reality they are all one service description if you denormalize the output. With this output, you can still use SvcUtil to generate code for client applications as this lab illustrates.
Please check back next week for the continuation of this series.