Hello Indigo

  Windows IT Pro
Windows IT Library
  - Advertise        
Windows IT Pro Logo

  Home  |   Books  |   Chapters  |   Topics  |   Authors  |   Book Reviews  |   Whitepapers  |   About Us  |   Contact Us  |   ITTV  |   IT Jobs

search for  on    power search   help
 






Hello Indigo
View the book table of contents
Author: Michele L. Bustamante
Published: May 2007
Copyright: 2007
Publisher: O'Reilly Media
 


GENERATING A SERVICE AND CLIENT PROXY

In the previous lab, you created a service and client from scratch without leveraging the tools available to WCF developers. Although this helps you to understand the raw requirements for sending messages between clients and services, in reality, developers need tools to be productive. This time around, I’ll show you how to use several such tools that help you to generate services, access metadata, create configuration settings, and generate proxies. Specifically, you’ll use the following:
  • Visual Studio service templates
  • Service Configuration Editor
  • ServiceModel Metadata Utility (SvcUtil)
The primary goal of the lab in this section will be to improve your productivity for building clients and services, but several other concepts will be discussed in the process. To begin with, you’ll use declarative configuration settings instead of code to configure the service host and client. To enable proxy generation, you’ll access service metadata, which involves enabling a service behavior. In addition, you’ll learn more about service configuration settings for base addresses, endpoints, bindings and behaviors.

After you complete the lab, I’ll spend some time discussing these concepts.

Lab: Using Tools to Generate Clients and Services

In this lab, you will generate service code using two approaches: by adding a service to an existing host and by generating a new service library, both using Visual Studio templates. To configure service endpoint for the host, this time you’ll use the Service Configuration Editor. To generate client proxies and related configuration you’ll use the ServiceModel Metadata Utility (SvcUtil). Both of these tools are available through the Solution Explorer in Visual Studio.


Visual Studio extensions for WCF will be part of the next release of Visual Studio, code-named "Orcas." As such, the user interfaces and features of these extensions may change from the time of this writing.

Using the WCF Service template
In this first section of the lab, you’ll create a new service using the WCF Service template and add it to an existing project. This template will add a sample service contract and service type to the project, along with the required service model assembly references. Since you will be adding the WCF Service to an executable project (the host), the template will also generate some code for hosting the service.
  1. Start by opening an existing Visual Studio solution that contains two projects: a shell console client and host. The solution is located at <YourLearningWCFPath>\Labs\Chapter1\HelloIndigo\HelloIndigo.sln.


  2. First, you will add a new service to the host project. From Solution Explorer, right-click on the Host project node and select Add -> New Item. Select the WCF Service template and name the file HelloIndigoService.cs.


  3. Open HelloIndigoService.cs in the code window and add a namespace qualifier for the service contract, then modify the service operation name and signature to match the following code in bold:
    [ServiceContract(Namespace="http://www.thatindigogirl.com/samples/2006/06")]
    public interface IHelloIndigoService
    {
      [OperationContract]
      string HelloIndigo( );
    }
  4. Modify the service implementation in the same file to implement the correct operation signature. This is how the resulting service type should look:
    public class HelloIndigoService : IHelloIndigoService
    {
      public string HelloIndigo( )
      {
        return "Hello Indigo";
      }
    }
  5. The WCF Service template also generated a helper class for hosting the service, named MyServiceHost, located beneath the service type. You’re going to edit this class and remove the hardcoded base address provided to the ServiceHost instance.

    Locate the StartService( ) method in MyServiceHost and modify it so that a base address is no longer passed to the ServiceHost constructor. The resulting changes are shown here:
    internal static void StartService( )
    {
    
      myServiceHost = new ServiceHost(typeof(HelloIndigoService));
      myServiceHost.Open( );
    }
  6. You’re going to use the hosting helper class to initialize the ServiceHost for the service. Go to the Host project and open Program.cs. Modify the Main( ) entry point so that it looks as follows:
    static void Main(string[] args)
    {
      try
      {
        MyServiceHost.StartService( );
        Console.WriteLine("Press <ENTER> to terminate the host application");
        Console.ReadLine( );
      }
      finally
      {
        MyServiceHost.StopService( );
      }
    }
  7. Compile the Host project.
At this point, you have defined a service inside the Host project and added code to host the service, but the implementation is incomplete. The ServiceHost requires at least one endpoint before clients can invoke the service.

Configuring service endpoints using the Service Configuration Editor
In this section, you will provide an endpoint for the ServiceHost—this time using the Service Configuration Editor. Unlike in the previous lab, endpoints will be configured using an external application configuration file. As such, you’ll open the application configuration file for the Host application using the tool to configure ServiceHost endpoints in that file.
  1. Go to the Host project and right-click on the app.config file. Select Edit WCF Configuration. You’ll see the Service Configuration Editor interface shown in Figure 1-21. Go to the Tasks pane and click "Create a New Service"; the New Service Element Wizard will be displayed.

    Follow these instructions as you go through each page in the wizard:

    1. On the first page, you are asked to provide the service type. Browse to <YourLearningWCFPath>\Labs\Chapter1\HelloIndigo\Host\Bin\Debug and select Host.exe. The Type Browser dialog (shown in Figure 1-22) will list Host.HelloIndigoService as the only service available in the assembly. Select it from the list and click Open. Click Next to continue.
    2. Now you will be asked to specify a service contract. There is only one service contract implemented by HelloIndigoService, so the selected service contract should be Host.IHelloIndigoService. Click Next to continue.
    3. Select HTTP as your service communication mode and click Next.
    4. Select Basic Web Services interoperability as your interoperability method and click Next.
    5. Now you’ll be asked to provide an endpoint address. Here you can provide a relative address by clearing the current text and typing "HelloIndigoService." Click Next.
    6. Review the configuration you have chosen for the service, then click Finish.

  2. Go to the Configuration pane in the Service Configuration Editor interface and expand the Endpoints folder beneath Host.HelloIndigoService. Select the only endpoint labeled (Empty Name).

    Go to the Service Endpoint pane, and in the General tab, provide the name basicHttp as shown in Figure 1-23. At this point, you have created a single, relative service endpoint.


  3. In this lab, the client will generate a proxy using SvcUtil. To support this, you’ll enable the metadata exchange behavior by adding a behavior to the service configuration.

    Go to the Configuration section and expand the Advanced folder. Select Service Behaviors and go to the Tasks pane to select New Service Behavior Configuration.

    Go to the Behavior pane and set the configuration name to serviceBehavior. Click the Add button to add a behavior element and select serviceMetadata from the list provided.

    Go to the Configuration pane and you’ll now see a new serviceMetadata node beneath serviceBehavior. Select the node and review the default settings in the General tab.


  4. The behavior must be explicitly associated to the service. Go to the Configuration pane and select the service node, Host.HelloIndigoService. Go to the Service pane and set the BehaviorConfiguration property to serviceBehavior (you can select it from the dropdown list).


  5. Enabling the metadata behavior is a good start, but a new endpoint is also required to support metadata exchange. Go to the Configuration pane, rightclick on the Endpoints folder, and select New Service Endpoint.

    Go to the Service Endpoint pane and set the name to mex. In the Endpoint Properties section, set the Binding to mexHttpBinding. For the Contract property type, select IMetadataExchange.


  6. In order to support metadata exchange, the host must have a base address for the metadata exchange protocol being used. In addition, since you supplied a relative address for the service endpoint, it also requires a base address matching the binding protocol. In this case, an HTTP base address will be used.

    Go to the Configuration pane and select the Host node beneath Host. HelloIndigoService. Go to the Host pane and select New to create a new base address. From the Base Address Editor, supply the following base address: http:// localhost:8000/HelloIndigo.


  7. Save the configuration settings you just generated. Select File . Save followed by File -> Exit. Return to Visual Studio and open the app.config for the Host project. You will see a <system.serviceModel> section like the one shown in Example 1-5.


  8. Compile the Host project and then run it. Leave the host running for the next step.
Example 1-5. Service model configuration generated by Service Configuration Editor
<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior name="serviceBehavior">
        <serviceMetadata />
      </behavior>
    </serviceBehaviors>
</behaviors>
  <services>
    <service behaviorConfiguration="serviceBehavior"
name="Host.HelloIndigoService" >
     <endpoint address="HelloIndigoService" binding="basicHttpBinding"
name="basicHttp" contract="Host.IHelloIndigoService" />
      <endpoint binding="mexHttpBinding" name="mex" contract="IMetadataExchange" />
      <host>
        <baseAddresses>
          <add baseAddress="http://localhost:8000/HelloIndigo" />
        </baseAddresses>
      </host>
    </service>
  </services>
</system.serviceModel>

You just created a declarative configuration for the ServiceHost, instead of programmatically initializing its base addresses and service endpoints. In addition, you enabled the service metadata behavior and created a metadata exchange endpoint so that clients can generate a proxy using SvcUtil. That’s the next step.

Generating a proxy with Add Service Reference
It’s time to generate code for the client to consume the service, starting by generating a client proxy. To achieve this you will use the Add Service Reference functionality exposed by Visual Studio, which uses the ServiceModel Metadata Utility (SvcUtil) to generate a proxy and configuration settings for that proxy.
  1. Go to the Client project and from Solution Explorer, right-click on the Client project node and select Add Service Reference. The dialog presented requires you to provide a valid base address to the service. Supply the base address http://localhost:8000/HelloIndigo and leave the Service reference name as localhost. When you close this dialog, a service proxy and configuration file will be generated for the client application. Stop debugging so you can add code to the client application.

    To see the proxy, go to the Client project and expand the Service References folder. Beneath it you will see localhost.map, and beneath that localhost.cs—the latter of which contains the proxy.

    A new configuration file, app.config, was also added to the project. This contains the service model configuration for the proxy. Later I’ll talk about how these things come together.


  2. Add code to the client application to invoke the service using the generated proxy. Go to the Client project and open Program.cs. Add code to the Main( ) entry point as shown in bold in Example 1-6.


  3. Compile the solution and run the Host project, followed by the Client. The client’s console output should show the result of invoking the service’s HelloIndigo operation.
Example 1.6. Using a generated proxy to invoke a service
static void Main(string[] args)
{
  localhost.HelloIndigoServiceClient proxy = new
Client.localhost.HelloIndigoServiceClient( )
  string s = proxy.HelloIndigo( );
  Console.WriteLine(s);

  Console.WriteLine("Press  to terminate Client.");
  Console.ReadLine( );
}

This concludes one technique for generating a service, ServiceHost configuration, and a client proxy.

Creating a WCF Service Library
In this section, you will generate a service using another technique: adding a new class library that includes a WCF service. The WCF Service Library template is a quick and easy way to generate a new class library with a sample service contract, service type, and the appropriate assembly references.
  1. Go to the Solution Explorer and right-click on the solution node. Select Add -> New Project and select the WCF Service Library template. Name the project HelloIndigo.


  2. Rename the class file from Class1.cs to HelloIndigoService.cs.


  3. Modify the service contract that is supplied by the project template. Open HelloIndigoService.cs in the code window and provide a namespace for the ServiceContractAttribute and change the interface definition to look as follows:
    [ServiceContract(Namespace="http://www.thatindigogirl.com/samples/2006/06")]
    public interface IHelloIndigoService
    {
      [OperationContract]
      string HelloIndigo( );
    }
  4. Now, modify the service implementation so that it implements the new contract. Rename the service to HelloIndigoService and implement IHelloIndigoService as shown here:
    public class HelloIndigoService: IHelloIndigoService
    {
      public string HelloIndigo( ) 
      {
        return "Hello Indigo";
      }
    }
  5. Compile the HelloIndigo project.


    The default data contract created when you used the WCF Service template is not necessary for this lab.

  6. Now you will modify the existing host project so that it hosts this new service. Go to the Host project and open HelloIndigoService.cs. Comment the entire service contract and implementation to avoid collision with the HelloIndigo library you’re about to reference.


  7. Add a reference to the HelloIndigo class library project. Right-click on the Host node and select Add Reference. From the Projects tab, select the HelloIndigo project.


  8. The ServiceHost must be modified to refer to the service type from this project. In the HelloIndigoService.cs file, find the StartService( ) method and modify the ServiceHost constructor to use the fully qualified name of the service, HelloIndigo.HelloIndigoService, as shown here:
    myServiceHost = new ServiceHost(typeof(HelloIndigo.HelloIndigoService));
  9. You’ll also have to edit the service model section of the configuration file to use the correct service and contract types. Go to the Host project and open the app.config file. Change the service type and contract type for the <service> configuration section as shown here in bold:
    <service behaviorConfiguration="serviceBehavior" name="HelloIndigo.
    HelloIndigoService">
      <endpoint address="HelloIndigoService" binding="basicHttpBinding"
    name="basicHttp" contract="HelloIndigo.IHelloIndigoService" />
    
      <!-- other settings -->
    </service>
  10. Test the solution again by compiling and running the Host and then the Client.
Now you have learned how to create a new class library with a sample WCF service and seen the changes required to the service model configuration and ServiceHost to reference a different service type.

Generating a proxy using the Service Model Metadata Utility
In this section, you will generate a client proxy using the SvcUtil directly instead of using Add Service Reference. The purpose of this exercise is to show you how to exercise greater control over the generation of proxies and configuration settings.
  1. First, run the Host project so that the endpoint is available to generate a proxy.
    From the Windows Start menu, find the Microsoft Visual Studio 2005 program group and launch the Visual Studio 2005 Command Prompt. Run the following command to generate a new proxy for the client application and replace the application configuration settings generated previously:
    svcutil /d:<YourLearningWCFPath>\Labs\Chapter1\HelloIndigo\Client /o:
    serviceproxy.cs /config:app.config http://localhost:8000/HelloIndigo
    The output should look similar to Figure 1-24.


    The /d: option for SvcUtil allows you to provide a path where output files will be generated. In the Preface, I explained that I would be using the term <YourLearningWCFPath> to refer to your base path—where you unzipped the file provided with the book. Thus, if your base path is c:\LearningWCF, then your SvcUtil command in this example would be:
    svcutil /d:c:\LearningWCF\Labs\Chapter1\HelloIndigo\Client
    /o:serviceproxy.cs/config:app.config http://localhost:8000/
    HelloIndigo
    If your path includes spaces, such as c:\Learning WCF, then you will have to provide quotes to the path, as shown here:
    svcutil /d:"c\Learning WCF\Labs\Chapter1\HelloIndigo\Client"
    /o:serviceproxy.cs/config:app.config http://locahost:8000/
    HelloIndigo

  2. To use this proxy you’ll have to modify the client application. Go to the Client project. If you select the "Show all files" icon in Solution Explorer, you’ll see a new file beneath the project node. Right-click serviceproxy.cs and select "Include in Project." Right-click localhost.map beneath Service References and select "Exclude from Project."

    Now open Program.cs and modify the code that constructs the service proxy. The proxy that was generated does not belong to a namespace, so you must remove the fully qualified name for HelloIndigoServiceClient. The resulting code is:
    using (HelloIndigoServiceClient proxy = new HelloIndigoServiceClient( ))
  3. Compile and run the solution once again.
Service Templates

This lab introduces several Visual Studio templates for generating service code. In an existing project—no matter whether it is a class library, console application, Windows application, or web site—you can add a new WCF Service. This template generates a sample service contract and service type to get you started. If you add the WCF Service to an executable project, the template also supplies a helper class for hosting the service. When you want to create a class library for your services, you can create a WCF Service Library project. This template creates a new class library, including a sample service contract and service type. In this case, the assumption is that you’ll create a separate host for the service (my personal preference). Using each of these templates also adds the appropriate service model assembly references to save you the trouble.

Service templates for web sites are slightly different from other projects because the hosting environment is slightly different. The overall result is the same—sample code is generated and assembly references are added. The difference is that an additional file is generated with a .svc extension for web hosting. You’ll see this in the next lab.

ServiceModel Metadata Utility

The ServiceModel Metadata Utility is a command-line tool that is installed with the Windows SDK for .NET 3.0—an executable file named svcutil.exe. This tool can be used for two key purposes:
  • To generate code and configuration settings from metadata
  • To generate metadata from code and configuration
With SvcUtil you can export and import metadata, validate services, and manipulate how types are generated and shared between services and clients. Add Service Reference uses SvcUtil to generate proxies and configuration, but from the command line, you can exercise greater control over this process.

This lab illustrates a very simple command-line instruction for generating a proxy and configuration file from a metadata exchange endpoint as follows:
svcutil /d:<YourLearningWCFPath>\Labs\Chapter1\HelloIndigo\Client /o:serviceproxy.cs
/config:app.config http://localhost:8000/HelloIndigo
You can also suppress the generation of configuration output with the following instruction:
svcutil /d:<YourLearningWCFPath>\Labs\Chapter1\HelloIndigo\Client /o:serviceproxy.cs
/config:noconfig http://localhost:8000/HelloIndigo
To see all the options for SvcUtil, from the command line you can type:
svcutil /?
Using Add Service Reference to generate the client configuration and proxy will work for many cases, but there are some cases in which you need to exercise control over things such as how arrays are handled, to make asynchronous calls to the proxy, and to share types with the service. I’ll explore other uses for SvcUtil throughout this book.

Service Configuration Editor

The Service Configuration Editor is another tool that is installed with the Windows SDK for .NET 3.0—an executable file named svcconfigeditor.exe. This tool is a wizard that helps you configure service model settings for WCF clients and services. You can launch the Service Configuration Editor directly from Solution Explorer to edit the <system.serviceModel> section for any client or host application configuration file (as the lab illustrates). The wizard guides you through steps to configure services, bindings, behaviors, and more, which is particularly useful when you are new to WCF since you may not be familiar with each section of the configuration file.

The service model configuration for clients and service are both encapsulated within the <system.serviceModel> configuration section so you can use this tool to edit both sides. When starting from scratch, you can use the tool to add new services or client endpoints, to attach behaviors to services or endpoints, to supply base addresses for the host, to supply metadata exchange endpoints, and even to customize binding configurations (something I’ll talk about in Chapter 3). For existing applications, you may just use the tool to view settings and make minor changes.

As I show you configuration settings throughout this book, I’ll talk about many settings in the <system.serviceModel> section—all of which can be configured using the Service Configuration Editor. But you’ll find that as you gain more experience with <system.serviceModel> settings, it is much more productive to edit the configuration file directly, relying on Intellisense.

ServiceModel Configuration

This lab illustrates the use of declarative configuration settings to configure the ServiceHost and the client proxy—although, in the latter case, you generated the configuration. Both ServiceHost and proxy types rely on programmatic or declarative configuration to initialize endpoints and configure behaviors. The latter technique provides greater deployment flexibility while programmatic settings enable you to enforce certain settings. In this section I’ll focus on the service model configuration settings.

All configuration settings related to the service model are contained within the <system.serviceModel> section new to WCF. Any application configuration file can contain this section, which means app.config for executables, and web.config for web sites. The service model is vast and there are many configuration options, most of which will be explored throughout the book. However, the core elements of this configuration you will repeatedly use are: <services>, <client>, <bindings>, <behaviors>. Table 1-1 provides a brief explanation of each section. Service model configuration settings can also be set at runtime through the proxy or ServiceHost; however, declarative configuration is often preferred to hardcoding settings in code. You can modify configuration files without impacting the compiled service or client code and this supports more flexible deployment scenarios.


Throughout this book, you will see examples that configure the service model in code where there are practical applications for it.

ServiceHost Initialization

The first lab illustrates how to configure the ServiceHost programmatically. This lab illustrates how to configure the ServiceHost declaratively using the service model configuration section. But how does the ServiceHost know which configuration section to use? When the ServiceHost is opened, it reads the <services> section looking for a <service> element that matches its service type. From the lab, consider this ServiceHost constructor:
ServiceHost myServiceHost = new ServiceHost(typeof(HelloIndigo.HelloIndigoService));
The ServiceHost will look for a section using the name HelloIndigo. HelloIndigoService, as shown here:
<service behaviorConfiguration="serviceBehavior"
name="HelloIndigo.HelloIndigoService" >
  <host>...</host>
  <endpoint... />
  <endpoint... />
</service>
The <service> element can include base addresses and service endpoints, as shown previously in Example 1-5. You can supply a base address for any protocol so that you can expose relative service endpoints over that protocol. The following illustrates the <host> section with base addresses for HTTP, TCP, and named pipe protocols:
<host>
  <baseAddresses>
    <add baseAddress="http://localhost:8000/HelloIndigo" />
    <add baseAddress="net.tcp://localhost:9000/HelloIndigo" />
    <add baseAddress="net.pipe://localhost/HelloIndigo" />
  </baseAddresses>
</host>
One or more <endpoint> sections may also be provided. As discussed previously, an endpoint is defined by an address, contract, and binding. If address is omitted altogether, the base address for the related binding protocol is used (and required). If the address omits the full URI, it is appended to the base address matching the binding protocol. However, you can specify a complete address that ignores the base address. The following illustrates these three choices for an endpoint configuration:
<endpoint binding="basicHttpBinding" name="basicHttp" contract="Host.
IHelloIndigoService" />
<endpoint address="HelloIndigoService" binding="basicHttpBinding" name="basicHttp"
contract="Host.IHelloIndigoService" />
<endpoint address="http://localhost:8001/HelloIndigo/HelloIndigoService"
binding="basicHttpBinding" name="basicHttp" contract="Host.IHelloIndigoService" />
Endpoints have to be unique for a particular service. When multiple endpoints are exposed by a service, they must differ in address, contract, or transport protocol.


There are several reasons why a service may expose multiple endpoints, including the following:
  • The service implements multiple contracts, each requiring its own endpoint
  • The same or different service contracts must be accessible over multiple protocols
  • The same or different service contracts must be accessible by clients with different binding requirements, possibly related to security, reliable messaging, message size, or transactions<
  • /ul> These topics will be explored throughout the book.

Enabling Metadata Exchange

A metadata exchange endpoint is required to support the dynamic generation of proxy and configuration for client applications. You must explicitly enable metadata exchange by adding the endpoint and enabling the metadata exchange behavior.

A metadata exchange (mex) endpoint is just like any other service endpoint in that it requires an address, contract, and binding. The address for a metadata exchange endpoint requires a base address for the selected binding protocol. The contract must be IMetadataExchange, a predefined service contract belonging to the System.ServiceModel.Description namespace (see Example 1-7).

Example 1-7. IMetadataExchange contract as defined by the service model
[ServiceContract(ConfigurationName="IMetadataExchange", Name="IMetadataExchange",
Namespace="http://schemas.microsoft.com/2006/04/mex")]

public interface IMetadataExchange
{
  [OperationContract(Action="http://schemas.xmlsoap.org/ws/2004/09/transfer/Get",
ReplyAction="http://schemas.xmlsoap.org/ws/2004/09/transfer/GetResponse",
AsyncPattern=true)]
IAsyncResult BeginGet(Message request, AsyncCallback callback, object state);

  Message EndGet(IAsyncResult result);

[OperationContract(Action="http://schemas.xmlsoap.org/ws/2004/09/transfer/Get",
ReplyAction="http://schemas.xmlsoap.org/ws/2004/09/transfer/GetResponse")]
  Message Get(Message request);
}

As for the binding, there are several predefined mex bindings, including MexHttpBinding, MexHttpsBinding, MexTcpBinding, and MexNamedPipeBinding. That means you can expose a mex endpoint over HTTP, HTTPS, TCP, or named pipes and have SvcUtil consume those endpoints.


Like any other endpoint, metadata exchange endpoints can also be consumed at runtime by clients. Applications can call mex endpoints to dynamically generate proxies or just to request information about the associated service.

The following illustrates a service exposing two TCP endpoints: one for the service, another for metadata exchange:
<service behaviorConfiguration="serviceBehavior"
name="HelloIndigo.HelloIndigoService">
  <endpoint address="HelloIndigoService" binding="netTcpBinding" name="netTcp"
contract="HelloIndigo.IHelloIndigoService" />
  <endpoint binding="mexTcpBinding" name="mex" contract="IMetadataExchange" />
  <host>
    <baseAddresses>
      <add baseAddress="net.tcp://localhost:9000/HelloIndigo" />
    </baseAddresses>
  </host>
</service>
Supplying the endpoint is not sufficient on its own. The service metadata behavior must also be enabled. Example 1-5 shows you how to enable the behavior by associating a service behavior to the service and including the <serviceMetadata> element. Once the behavior is enabled, you can use SvcUtil for proxy generation against any mex endpoint. For example, to generate a service proxy and configuration using the TCP endpoint with SvcUtil, you can type this instruction at the command line:
svcutil /d:<YourLearningWCFPath>\Labs\Chapter1\HelloIndigo\Client /o:serviceproxy.cs
/config:app.config net.tcp://localhost:9000/HelloIndigo/mex
It might seem a little annoying at first that you have to enable metadata exchange before you can generate a client proxy. This opt-in behavior is actually a good thing in the long run. You don’t want your services exposing endpoints of which you aren’t aware or that you don’t want to support.

Working with Behaviors

As you’ve seen, the ServiceHost is initialized by the <service> configuration section associated with its service type. At least one endpoint must be configured for the service to be useful to clients. In this lab, a single service endpoint and a metadata exchange endpoint are exposed—both over HTTP. While endpoints describe where to reach the service, which operations are available at the specified address, and what protocols are required—behaviors affect the service model locally at the client or service. What that means is that behaviors are not exposed as part of metadata, and they are not shared between clients and services. Instead, they locally affect how the service model processes messages.

Behaviors can be defined in configuration or in code. Different behaviors are available to clients and services, since the local affect on the service model also differs.

Service behaviors
Service behaviors are types that implement IServiceBehavior from the System. ServiceModel.Description namespace. There are service behaviors to control debugging, metadata, security features, serialization, and throttling. When enabled, each behavior interacts with the service model to achieve its goal. For example, when the metadata behavior is enabled, the service model will allow requests to a metadata exchange endpoint. Otherwise, it will not.

Service behaviors are configured in the <serviceBehaviors> section. The following example illustrates enabling service debug and service metadata behaviors:
<behaviors>
  <serviceBehaviors>
    <behavior name="serviceBehavior">
      <serviceDebug includeExceptionDetailInFaults="true"/>
      <serviceMetadata />
    </behavior>
  </serviceBehaviors>
</behaviors>
To associate a set of behaviors with a service use the behaviorConfiguration attribute of the <service> section (see Example 1-8).

Example 1-8. Associating a service behavior to a service
<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior name="serviceBehavior">
        <serviceMetadata />
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <services>
    <service behaviorConfiguration="serviceBehavior"
name="Host.HelloIndigoService" >
    ...
    </service>
  </services>
</system.serviceModel>


You may forget to make the association between the service and behavior at least a few times. Don’t forget to double-check your configuration when you aren’t seeing the expected results at runtime!

You can also programmatically configure service behaviors through the ServiceHost instance. The Description property of the ServiceHost has a Behaviors collection. You can see if a behavior exists by calling the Find<T>( ) method on the collection. You can add new behaviors by calling Add( ) on the collection. Example 1-9 shows an example that looks to see if the ServiceMetadataBehavior exists, and if not adds it to the collection and enables browsing.

Example 1-9. Adding the metadata service behavior programmatically
ServiceHost host = new ServiceHost(typeof(HelloIndigo.HelloIndigoService);

ServiceMetadataBehavior mexBehavior =
host.Description.Behaviors.Find<ServiceMetadataBehavior>( );

if (mexBehavior == null)
{
  mexBehavior = new ServiceMetadataBehavior( );
  mexBehavior.HttpGetEnabled = true;
  host.Description.Behaviors.Add(mexBehavior);
}

host.Open( );

Client behaviors
Client behaviors implement IEndpointBehavior, also from the System.ServiceModel. Description namespace. There are client behaviors to control debugging, security, serialization, timeouts, and routing. Endpoint behaviors interact with the service model at the client. Endpoint behaviors are configured in the <endpointBehaviors> section. The following example enables exception debugging for callbacks:
<behaviors>
  <endpointBehaviors>
    <behavior>
      <callbackDebug includeExceptionDetailInFaults="true"/>
    </behavior>
  </endpointBehaviors>
</behaviors>
Endpoint behaviors are associated with client endpoints using the behaviorConfiguration attribute of the <endpoint> section (see Example 1-10).

Example 1-10. Associating an endpoint behavior to a client endpoint
<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior name="clientBehavior">
        ...
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <client>
    <endpoint address="net.tcp://localhost:9000/" binding="netTcpBinding"
contract="Client.localhost.IHelloIndigoService"
behaviorConfiguration="clientBehavior">
    </endpoint>
  </client>
</system.serviceModel>

To programmatically configure endpoint behaviors, you can use the object model of the client proxy. The Endpoint property of the client proxy has a Behaviors collection through which you can search for existing behaviors and add behaviors—similar to the way you would for the ServiceHost. Example 1-11 shows an example that looks to see if the ServiceDebugBehavior exists, and if not adds it to the collection.

Example 1-11. Adding the debug service behavior programmatically
HelloIndigoServiceClient proxy = new HelloIndigoServiceClient( );

ServiceDebugBehavior debugBehavior =
proxy.Endpoint.Behaviors.Find<ServiceDebugBehavior>( );

if (debugBehavior == null)
{
  debugBehavior = new ServiceDebugBehavior( );
debugBehavior.IncludeExceptionDetailInFaults = true; proxy.Endpoint.Behaviors.Add(debugBehavior); }


I will explore other behaviors for the client and service throughout this book as I review features related to each behavior. At this point, I want you to understand how services and client endpoints are related to behaviors.

Proxy Initialization

For a client to invoke service operations, it must open a communication channel to a particular service endpoint. This channel is bound to a particular endpoint—its address, binding, and contract. This is done by creating a proxy.

In the first lab, a proxy is created directly by using the channel factory:
IHelloIndigoService proxy =
ChannelFactory<IHelloIndigoService>.CreateChannel(new BasicHttpBinding( ), new
EndpointAddress("http://localhost:8000/HelloIndigo/HelloIndigoService"));
This approach assumes that:
  • You have prior knowledge of the endpoint address.
  • A copy of the service contract definition is locally available.
  • You have prior knowledge of the required protocols or binding configuration.
If you own both sides (client and service), it is feasible to share an assembly that contains service metadata and to separately communicate the address and binding requirements. When you don’t own both sides, generating the proxy is a more effective way to import the metadata necessary to construct the client channel. In this lab, the proxy is generated with SvcUtil. This proxy includes a generated copy of the service contract and a channel wrapper to simplify the client code necessary to consume the service. SvcUtil also generates the service model configuration necessary to initialize the proxy.

The service contract generated by SvcUtil looks similar to the contract at the service with the exception of additional details specified in the ServiceContractAttribute and OperationContractAttribute, shown in Example 1-12.

Example 1-12. Service contract generated by SvcUtil
[System.ServiceModel.ServiceContractAttribute(Namespace=
"http://www.thatindigogirl.com/samples/2006/06",
ConfigurationName="Client.localhost.IHelloIndigoService")]
public interface IHelloIndigoService
{
  [System.ServiceModel.OperationContractAttribute(Action=
"http://www.thatindigogirl.com/samples/2006/06/IHelloIndigoService/HelloIndigo", ReplyAction= "http://www.thatindigogirl.com/samples/2006/06 /IHelloIndigoService/HelloIndigoResponse")] string HelloIndigo( ); }

The namespace specified by the ServiceContractAttribute is the same as at the service. This is critical to compatible message serialization.

The SvcUtil that generated the client-side service contract also generated a proxy type. The proxy type is a partial class that inherits ClientBase<T> from the System. ServiceModel namespace (T is the service contract type). As shown in bold in Example 1-13, the proxy exposes service contract operations and internally uses its reference to the client communication channel to invoke each service operation. In fact, this inner channel reference is like the one you previously created with the channel factory.

Example 1-13. Proxy type generated by SvcUtil
public partial class HelloIndigoServiceClient :
System.ServiceModel.ClientBase<Client.localhost.IHelloIndigoService>,
Client.localhost.IHelloIndigoService
{
  ...overloaded constructors

public string HelloIndigo( )
  {
    return base.Channel.HelloIndigo( );
  }
}

When the first operation is invoked on this proxy, the inner channel is created based on the endpoint configuration for the proxy. Since in this lab only one endpoint is available, the construction of the proxy looks something like this:
HelloIndigoServiceClient proxy = new HelloIndigoServiceClient( );
If there are several endpoints to choose from in the <client> configuration section, you are required to provide an endpoint configuration name to the proxy constructor:
// Proxy construction

HelloIndigoServiceClient proxy = new HelloIndigoServiceClient("basicHttp");
// Endpoint configuration
<endpoint address="http://localhost:8001/HelloIndigo/HelloIndigoService"
binding="basicHttpBinding" name="basicHttp" contract="Host.IHelloIndigoService" />
Once the client channel has been used (by invoking an operation), the proxy is bound to the endpoint configuration that initialized it. The same proxy instance cannot be used to invoke another service endpoint, and no changes to protocols or behaviors are allowed. A new proxy (channel) must be constructed if such changes are required.

Hosting a Service in IIS

How messages reach a service endpoint is a matter of protocols and hosting. IIS can host services over HTTP protocol, the Windows Activation Service (WAS) can support others such as TCP and named pipes, and self-hosting can support many protocols and includes several deployment options such as console or Windows Forms applications and Windows services. Selecting a hosting environment has nothing to do with service implementation, but everything to do with service deployment and overall system design.

This lab will show you how to host an existing service type as part of a web site hosted in IIS. In the process, I’ll also be illustrating other extended concepts such as:
  • The WCF Service web site template
  • Message-based activation
  • Additional metadata behavior settings
  • Exporting service descriptions
  • Consuming service description documents to generate client code
As always, after the lab I’ll describe some of these features in greater detail.

Lab: Creating an IIS Host and Browsing Metadata

For this lab, you will work with an existing solution that contains a completed service library and shell client application. Using Visual Studio templates, you’ll create a new IIS web site project that contains a service and modify it to host a preexisting service. To consume the service, you’ll generate a client proxy from static service documentation exported using SvcUtil.

Creating a WCF Service web site
The first thing to do is create a WCF-enabled web site using the WCF Service template, which is new to WCF. When services are added to a web site, the supplied sample service is accompanied by a .svc file, the web server endpoint.
  1. Open the startup solution for the lab, located at <YourLearningWCFPath>\Labs\Chapter1\IISHostedService\IISHostedService.sln. This solution contains a copy of the HelloIndigo project from earlier labs and a shell client application.


  2. You are going to create a new web site to host the service. Go to Solution Explorer, right-click the solution node and select Add -> New Web Site. Select the WCF Service template and make sure the location type for the new web site is HTTP (see Figure 1-25). Set the location value to http://localhost/IISHostedService.

    When Visual Studio creates a new HTTP web site, a virtual application is created in IIS pointing to a directory beneath c:\inetpub\ wwwroot (or wherever your Default Web Site is pointing). In Figure 1-25, the path to the IISHostedService project might be c:\inetpub\wwwroot\IISHostedService.

  3. The WCF Service template generates a new web site with a default service implementation. You can delete the service implementation since you will be hosting an existing service. Go to Solution Explorer and expand the App_Code folder for the web site (see Figure 1-26). There you’ll see the file Service.cs. Delete it from the project.


  4. Go to the web site project and add a reference to the HelloIndigo project, which contains the service you’re about to host.


  5. You now can modify the web endpoint for the service so that it is associated with the correct service type. Open Service.svc in the code window and modify the @ServiceHost directive to associate the web endpoint with the service type HelloIndigo.HelloIndigoService, as shown here:
    <%@ ServiceHost Service="HelloIndigo.HelloIndigoService" %>

    Now, when a request arrives to Service.svc, the service model will activate a new ServiceHost instance associated with the HelloIndigoService type.

  6. The WCF Service template also generated configuration settings for the host, but these settings are based on the service supplied by the template. You must modify these settings to reflect the correct service contract and service type.

    Open the web.config file and find the <service> section. Change the name attribute of the <service> section to HelloIndigo.HelloIndigoService and change the contract attribute of the <endpoint> section to HelloIndigo.IHelloIndigoService. While you’re at it, change the binding to basicHttpBinding instead of wsHttpBinding. The result is shown here:
    <service type="HelloIndigo.HelloIndigoService"
    behaviorConfiguration="returnFaults">
      <endpoint contract="HelloIndigo.IHelloIndigoService"
    binding="basicHttpBinding"/>
    </service>
You now have a web site that will expose an endpoint to reach HelloIndigoService. Before generating the client proxy, I’ll show you some useful metadata features.

Browsing service metadata
In this part of the lab, you’ll make changes to the configuration file so that metadata can be viewed in a browser.
  1. 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.


  2. 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 Example 1-14.


  3. Example 1-14. Adding metadata browsing support to the web host
    <system.serviceModel>
      <services>
       <service name="HelloIndigo.HelloIndigoService"
    behaviorConfiguration="returnFaults">
          <endpoint contract="HelloIndigo.IHelloIndigoService"
    binding="basicHttpBinding"/>
          <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex"
    />
        </service>
      </services>
      <behaviors>
        <serviceBehaviors>
          <behavior name="returnFaults">
            <serviceDebug includeExceptionDetailInFaults="true"/>
            <serviceMetadata/>
          </behavior>
        &\lt;/serviceBehaviors>
      </behaviors>
    </system.serviceModel>

  4. 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.


  5. 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 set httpGetEnabled to true for the <serviceMetadata> behavior:
    <behavior name="serviceBehavior">
    <serviceMetadata httpGetEnabled="true"/>
    </behavior>
    Save this change and return to the browser instance showing the service help page.


  6. 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).
Exporting metadata for proxy generation
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.
  1. Launch the Visual Studio 2005 Command Prompt. Run the following command to instruct SvcUtil to export the service metadata and its associated schemas for the HelloIndigoService:
    svcutil /d:<YourLearningWCFPath>\Labs\Chapter1\IISHostedService /t:metadata http:
    //localhost/IISHostedService/service.svc
    This will generate two .wsdl files and two .xsd files in the solution directory.


  2. 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:
    svcutil /d:<YourLearningWCFPath>\Labs\Chapter1\IISHostedService\Client /o:
    serviceproxy.cs /config:app.config <YourLearningWCFPath>\Labs\Chapter1\
    IISHostedService\*.wsdl <YourLearningWCFPath>\Labs\Chapter1\IISHostedService\*.
    xsd
    The result of this command will be serviceproxy.cs and app.config files generated for the client application.


  3. 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 the Client project and refresh the file list in Solution Explorer. You should see the two new files appear; include them in the project.


  4. Invoke the service using the generated proxy. Open Program.cs in the code window and modify the Main( ) entry point adding code to create a proxy and invoke the HelloIndigo( ) operation. The resulting additions are shown in bold in Example 1-15.


  5. Compile and run the Client project. The output should be similar to that in earlier labs.
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( );
}

Web Site Templates

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
Example 1-27. Client endpoints generated for ServiceA and ServiceB
<client>
  <endpoint address="net.tcp://localhost:9000/Admin" binding="netTcpBinding"
bindingConfiguration="NetTcpBinding_IAdmin"
contract="ExternalClient.ServiceA.IAdmin"
name="NetTcpBinding_IAdmin" />
  <endpoint address="http://localhost:8000/ServiceA" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IServiceA"
contract="ExternalClient.ServiceA.IServiceA"
name="BasicHttpBinding_IServiceA" />
  <endpoint address="net.tcp://localhost:9000/ServiceA" binding="netTcpBinding"
bindingConfiguration="NetTcpBinding_IServiceA"

@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 @ServiceHost directive 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, the Service attribute refers to the inline service type, and you can even enable inline debugging by setting the Debug attribute to true. 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.

Example 1-16. Inline service code
<% @ServiceHost Language="C#" Debug="true" Service="MyService" %>

using System;
using System.ServiceModel;

[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, the Service attribute still refers to the service type, but the CodeBehind attribute is present to indicate the location of its source file:
<% @ServiceHost Language=C# Debug="false" Service="MyService"
CodeBehind="~/App_Code/MyService.cs" %>
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 the Service attribute:
<% @ServiceHost Service="MyNamespace.MyService" %>
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 the ServiceHost has 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 @ServiceHost declaration to find the associated service type. It then instantiates the ServiceHost instance for that type on your behalf, within an ASP.NET worker process. The web.config settings are used to initialize the ServiceHost and then Open( ) is called—at which point the first request is forwarded to the appropriate channel listener. Once the ServiceHost 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 the ServiceHost instance—this is handled for you by the host process. This is called message-based activation. The details of hosting are discussed in Chapter 4.

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 new ServiceHost 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 any ServiceHost instances. With IIS and WAS, configuration changes are detected and a new ServiceHost is created to handle subsequent requests.

Browsing and Exporting Metadata

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 set httpGetEnabled to true, the help page will produce a link to the WSDL document (Figure 1-27 and Figure 1-28):
<behavior name="serviceBehavior">
  <serviceMetadata httpGetEnabled="true" />
</behavior>
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 with httpHelpPageEnabled set to false and by setting httpGetEnabled to false:
<behavior name="serviceBehavior">
  <serviceDebug httpHelpPageEnabled="false" />
  <serviceMetadata httpGetEnabled="false" />
</behavior>
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 the externalMetadataLocation attribute:
<behavior name="serviceBehavior">
  <serviceDebug httpHelpPageEnabled="false" />
  <serviceMetadata httpGetEnabled="false" />
</behavior>
<behavior name="serviceBehavior">
  <serviceDebug httpHelpPageEnabled="false" />
  <serviceMetadata httpGetEnabled="true" externalMetadataLocation="http://localhost/
IISHostedService/www.thatindigogirl.com.2006.06.wsdl"/>
</behavior>
font class="docsubhead2"> Exporting metadata

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:
svcutil /d:<YourLearningWCFPath>\Labs\Chapter1\IISHostedService /t:metadata http://
localhost/IISHostedService/service.svc
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.



Page: 1, 2, 3,



ADS BY GOOGLE SPONSORED LINKS FEATURED LINKS

Maximize your SharePoint Investment – 8 Cities
Discover best practices and tips for both architecting and administering SharePoint. Early Bird Price of $99 through Sept 15th.

Find a new job now on the all new IT Job Hound!
Search jobs, post your resume, and set up job e-mail alerts!

Master SharePoint with 3 eLearning Seminars
Learn how to build a better SharePoint infrastructure and enable powerful collaboration with MVPs Dan Holme and Michael Noel. Register today!

Top Tools for Virtualization Disaster Recovery & Replication
View this web seminar on August 14th to learn about two tools that will result in faster backup and restore with P2V disaster recovery.

SharePointConnections Conference Fall 2008
Don’t miss the premier event for Microsoft IT Professionals in Las Vegas, November 10-13. Register and book your room by August 25 and receive a FREE room night (based on a three night minimum stay).

VMworld 2008 - Sign Up Today!
Join your peers on September 15-18 at The Venetian Hotel in Las Vegas as VMware hosts VMworld 2008, the leading Virtualization event.



Entrust Unified Communications Certs
Secure Exchange 2007 and save 20%. Now through Sept. 2008.

Increase Application Performance
Free White Paper by Editor's Best winner, Texas Memory Systems.

Need to convert between XML, DBs, EDI, and Excel? Try MapForce free!
Drag & drop to transform between popular data formats – get results instantly or generate code.

Microsoft® Tech•Ed EMEA 2008 IT Professionals
Advance your thinking with new ideas and practical real-world solutions at Microsoft’s FIVE day technical infrastructure conference 3-7 Nov., 2008. Register before 26 September 2008 to save €300.

Order Your SQL Fundamentals CD Today!
Learn how to use SQL Server, understand Office integration techniques and dive into the essentials of SQL Express and Visual Basic with this free SQL Fundamentals CD.

Are You Really Compliant with Software Regulations?
View this web seminar that will help you with compliance best practices and check out a management solution to assure that you won’t be in jeopardy of an audit.

Virtualization Congress Oct. 14-16 in London
Don't miss Virtualization Congress, the premiere EMEA conference dedicated to hardware, OS and application virtualization. Oct. 14-16.
Windows IT Pro Home Register FAQ for Windows WinInfo News
Europe Edition About Us Contact Us/Customer Service Media Kit Affiliates / Licensing  
SQL Server Magazine Office & SharePoint Pro Windows Dev Pro IT Job Hound ITTV
IT Library Technical Resources Directory Connected Home Windows Excavator Windows SuperSite 
 
 Windows IT Pro is a Division of Penton Media Inc.
 Copyright © 2008 Penton Media, Inc., All rights reserved. Terms and Use | Privacy Statement | Reprints and Licensing