Thursday, September 01, 2005 7:36 PM bart

Introducing Indigo

Introduction

The Indigo Windows Communication Foundation wave is around for a couple of years now, so I thought it was about time to dedicate some blog posts to this technology. In this first technical development-related post on the Indigo technology (I'll use the code-name further on instead of the new WCF name) we'll cover the basis of the technology and service orientation and will go through some simple low-level samples.

 

Service Orientation

Indigo is all about services. Not web services or Windows services but services. With the advent of the internet several decades ago, the need to have more distributed software is growing day by day. Service Orientation (abbreviated as - originally - SO) is a methodology for software design and development that puts connectivity of software components in the center of the universe, building software on top of services that interact with each other to fulfill business-related needs. An SO solution consists of a series of service that serve as building blocks for an application. Indigo is Microsoft's translation of this Service Oriented software design/development wave, enabling developers to write and build services also concentrating on the communication aspect for services and clients.

Note: You should not think of SO as a replacement for other development paradigms such as object-orientation (OO) or aspect orientation (AOP). Services is about creating facades that encapsulate the inner implementation of a service and expose the functionality of the service to the outside world. The way these services themselves are created can be OO or whatever paradigm you like to use.

SO (or SOA = Software Oriented Architecture) is based on a total of four tenets as proposed by Don Box:

  1. Explicitness of boundaries meaning that messages are sent between services across formal and explicit boundaries. Look at these boundaries as a kind of interfaces, hiding what's behind the boundary itself. Because of the explicitness, crossing a boundary is explicitly visible in code and saves you from boobytraps that are present in technologies such as DCOM, .NET Remoting, RMI, CORBA that make remote objects look as local objects.
  2. Autonomy of services makes it possible to update services independently from each other, without having to redeploy the entire solution as a whole. Loosely coupling is the keyword that makes this possible.
  3. Services share schemas and contracts. Services are not sharing types and classes but schemas and contracts instead. A schema defines data that is sent between endpoints, whileas a contract defines behavior of the service. In web services parlance, a schema can be built in XSD and a contract in WSDL. The use of schemas and contracts ensures more stability (= remain unchanged over time) than their types and classes equivalents in the distributed world.
  4. Compatibility based upon policy states that services agree on how they interact based on policies, describing the capabilities and requirements of the service (e.g. for communication with the service, encryption of data is required). Because of this, the operations (behavior, contract) is separated from contraints that should be enforced on these operations.

Mike Gilbert has a nice post on SOA over here. In the end, services can be seen as "super web services", meaning that limitations of web services are removed in the SO world. Samples include the strong binding to the HTTP protocol and the request/response model but also the removal of limitations on the field of reliability, transactions, policy expression, etc.

 

Indigo from a 10,000 foot view

Simply stated: SO is the specification, Indigo is Microsoft's implementation of SO. To kick off, we'll jump into some marketing talk on Indigo:

  • Indigo is a .NET-based technology to build service-oriented solutions. Exactly what we've been describing above.
  • Indigo provides unification of both the programming model and the runtime. In the past, several technologies existed to create distributed applications. An overview:
    • DCOM and .NET Remoting concentrate on remote objects and suffer from the "remote objects are transparent to the client" boobytrap. .NET Remoting is all about communication across application domains and is very extensible (channels, sinks, etc). The technology is fully object-oriented and works with various transport mechnanisms and protocols (e.g. binary of TCP, SOAP over HTTP, etc).
    • ASP.NET XML Web Services (.asmx) is Microsoft's first implementation of webservices on the .NET platform. As part of .NET's message, XML Web Services provide interoperability with other platforms and offers a service-oriented design. However, it lacks built-in support for new WS-* standards and can only work with HTTP.
    • Web Service Enhancements (WSE) extend the .asmx model and provide support for WS-* standards and other protocols and communication patterns than the plain vanilla HTTP response/request model. WSE is fully .NET-based and uses the power of managed code to deliver its functionality (e.g. attribute-based development). However, it lacks support for transactions, reliable messaging, etc.
    • MSMQ and System.Messaging concentrate on reliable messaging with queues as the communication mechanism. System.Messaging makes the use of MSMQ easier in the managed world. However, MSMQ is not available to services directly and is only usable in .NET-to-.NET scenarios.
    • COM+ Enterprise Services and System.EnterpriseServices are based on the notion of components that are decorated with .NET attributes to provide several services such as security and transactions. COM+ is component-based and built on the OO paradigm. However, it's a .NET-only story and lacks interoperability.
  • Indigo is scale-invariant. In more detail:
    • Scales down to devices such as printers, cameras, etc with support for WS protocols. On longer term, you can expect to see Indigo support on smart devices using the Compact Framework.
    • Scales in meaning that inter-process (or inter-appdomain) communication is damn fast (greater than or equal to .NET Remoting and/or Enterprise Services).
    • Scales up on large systems with high throughput and scalability which is mission-critical to systems with high workload and tons of consumers. Compared to existing technologies, Indigo wants to be superior.
    • Scales out by adding machines, e.g. in farms or on the routing-level (cf. WS-Routing and WS-Addressing). Information on these protocols applied to WSE 2.0 can be found on MSDN.
    • Scales away across organizations and geographies, referring to the use of interoperable protocols, reliable messaging and transmission fault tolerance and federation of security (cf. the former "TrustBridge" project and ADFS).
  • Indigo puts interoperability in the spotlight. Examples include:

Note: Also search on MSDN for more information about all of the aforementioned technologies and specifications.

 

Basic architecture of Indigo

Time for some illustrations. The picture below shows the basic layered architecture of Indigo.

Let's go through this picture from top to bottom:

  • At the uppermost layer, we have our application (a service) that's using the Indigo stack below.
  • Next, we have a series of messaging services that provide functionality to the application above. Samples include queuing, routing, eventing and discovery of services.
  • The service model provides the basic service-related functionality. This layer is all about behavior, such as error behavior, instance behavior, activation behavior, concurrency and transactions, etc.
  • The messaging layer delivers all functionality to the service model to create channels and to transport the messages between services. It also provides "side-services" such as security, reliability, policy and encoding. For transport channels such as HTTP, TCP, MSMQ, cross-process are supported.
  • Last but not least, the Indigo application is hosted in e.g. IIS, Avalon, an executable, a Windows Service or COM+.

I'll dive deeper into these in more detail further on and in upcoming posts on Indigo.

 

Some crucial concepts

Right, we know what Indigo does and we know the basic layered architecture. Time for some concepts that will be crucial for further understanding of Indigo stuff. Concentrate on the following simple sentence:

Services interact by exchanging messages.

This simple statement implies a lot of questions. Some samples: How are messages exchanged physically? Who send and who recieves messages? How does such a message look like? Are there different interaction patterns possible? Now the answers:

  • The key players in messaging are clients that initiate communication, the services that accept these messages and respond to them and possible intermediaries that route messages to their destination and inspect/manipulate the messages optionally. Notice that services themselves can also act as clients, resulting in a chain of services that are linked to each other.
  • The message structure in Indigo is based on SOAP, which is on its turn XML-based. From a macroscopic point of view, a message contains a series of headers as well as a body. Together, this forms a so-called SOAP Envelope. However, the encoding of the message and the transport protocols are configurable.
  • Channels are the pipelines over which information flows. The function of channels is twofold. First, channels are used for physical delivery of messages over various transport protocols such as HTTP, TCP, MSMQ and cross-proc, also providing reliability and/or session services if desired. Second, messages are manipulated by channels for encoding (binary, MTOM, etc) and decoration of messages to provide security features (e.g. Windows authentication).
  • Various interaction patterns exist in the world of Indigo. Starting with one-way simplex communication, over two-way duplex communication to request/reply based patterns.

Now look at a service as a black box. What should the service expose? Two seconds left for the answer :-). Right, first of all we need a description of the service because of the loosely coupling. This means it should be possible to discover information about what the service provides (behavior, operations, policy) and how to interact with it (message contracts). The discovery and description aspect of services is accomplished by WSDL, XSD, WS-Policy and WS-Metadata Exchange. Getting to know each other is one thing, working with each other is another thing. So, we also need endpoints for communication (as described by the obtained description) using SOAP.

Apart from the service's logic there should be other things inside a service as well. First, it needs to be able to provide its metadata to describe itself and the message contracts. That's the service description part of the inside story. Next, the consumer of the service needs to be able to get in through an endpoint. Therefore, we need a description of the way the service interacts with the outside world, which is called a binding. Such a binding encapsulates the transport mechanism (e.g. HTTP, TCP, named pipe, MSMQ), encoding (text, binary, MTOM) and requirements on the field of security, sessions, reliablity and transactions as well as available messaging patterns. The endpoint on the other hand is all about where the service is (an address) associated to a service contract and a binding. This brings is us the missing piece of the puzzle, being the contracts. Indigo knows three kinds of contracts:

  • Service contracts define the operations the service provides and its behavior. Compare such a contract with an interface from the OO world and you should have a pretty good understanding of such a contract. Of course, the service needs to implement the control to be useful (a class).
  • Data contracts specify data structures that are used to pass data to/from the service. The big idea of data contracts is to decouple internal class representations from the messaging format, which can be described in XSD for interoperability reasons and loose coupling.
  • Message contracts allow to manipulate the message structure and format of messages that are sent between services and consumers.

A little illustration can make things more clear I believe. Assume you have a service contract called IWeatherService that allows to report the weather using an operation that accepts a location (postal code, state, country in a data contract) and returns a weather report (temperature, air pressure in another data contract). The functionality of the service can be exposed through an endpoint consisting of an address (http://blabla/WeatherService or net.tcp://blabla:port/WeatherService or net.pipe://blabla/WeatherService or net.msmq://localhost/queue/WeatherService) and a binding mapping the address to the contract and enriching it with e.g. security. Thus, as a little rule of the Indigo thumb, remember the following:

endpoint = address + binding + contract

Services expose functionality but also have intrinsic runtime behavior. Indigo provides support for the following:

  • Concurrency - If multiple consumers use your service, how does it work with threading? Possible answers are: one single thread can access the service instance, multiple threads can access the service instance or reentrancy support meaning that threads can call into one another.
  • Error handling - Who will handle errors in the service? The developer himself, the Indigo framework or the client of the service (i.e. sending a fault to the client).
  • Instancing - People who've been working with .NET Remoting will know concepts such as singleton and singlecall. Indigo supports four mode: singleton (one instance serving all consumers), per call (used in stateless scenarios, such as classic web services), private session (each client session has its own service instance) and shared session (groups of clients can share a single session).
  • Lifetime - When using stateful sessions (e.g. a private session), there needs to be a session start en session end 'event'. The service itself can control the lifetime of the session if operations on the service are marked as session initiators and/or session terminators.
  • Metadata - This answers the question: "how can the service present itself to (possible) consumers?". By enabling metadata to be requested on demand through a request, a service is made self-describing using WSDL, WS-Policy, WS-Metadata Exchange.
  • Security - Service security is composed of various aspects, including message integrity and confidentiality, user authentication and authorization, DoS and replay (attack) detection, auditing. Indigo has support for PKI using X.509 but also supports Kerberos, plain old username/password mechanisms and more recent standards such as SAML.
  • Throttling - Used to limit the total number of service instances, concurrent threads, exchanged or accepted messages, etc. Using throttling, one can control resource consumption of the service, aiding with scalability measurement and planning.
  • Transactions - Indigo has support for transactions across services using WS-Atomic Transaction and other WS-* standards. This allows clients to start a transaction and flow it to one or more services that can then participate in that transaction. The service behavior for transactions is used to indicate whether the service will accept a transaction, requires a (new) transaction, etc.

 

Getting started

Enough theory for now, let's jump onto the Indigo wagon with a little sample. But first, some information on how to set up the stuff needed to bring our sample to a good end.

Download each of the following on either Windows XP (+ SP2) or Windows Server 2003 (+ SP1):

  1. .NET Framework Version 2.0 Redistributable Package Beta 2 (x86) - the .NET runtime on which Indigo is built
  2. Visual Studio 2005 Beta 2 - can be obtained via beta programmes (e.g. Microsoft EMEA's TheBetaExperience) or on MSDN Subscriptions
  3. "Indigo" Beta 1 MSMQ Support Package - needed for MSMQ support for queued channels (only needed for beta 1 currently)
  4. COM+ Hotfix for "Indigo" - contains WS-AtomicTransaction support for MSDTC and allows COM+ apps to be exposed using Indigo
  5. Microsoft Pre-Release Software WinFX Runtime Components Beta 1 - package with beta 1 of both Indigo (Windows Communication Foundation) and Avalon (Windows Presentation Foundation)
  6. Microsoft WinFX Software Development Kit for Microsoft Pre-Release Windows Operating System Code-Named "Longhorn", Beta 1 Web Setup - WinFX SDK with documentation and samples for Indigo and Avalon development (despite the naming of the download also supported on Windows XP and Windows Server 2003)
  7. Microsoft Visual Studio Extensions for WinFX Beta 1 - Visual Studio 2005 Beta 2 support for WinFX components and the WinFX SDK documentation

and install each of these in ascending order.

 

Your first Indigo application

As I don't want to be banned from the demo writing community I should start with the mandatory "Hello World" demo :-). The following instructions will guide you through the process of creating both an Indigo service and client:

  1. Start Visual Studio 2005 and create a new Project in C# and choose a Console Application as the template. Call it IndigoDemo.
  2. In the Solution Explorer, right-click on References and choose "Add Reference...". Select System.ServiceModel from the list and click OK.
  3. Add the following namespace import to the top of the Program.cs file:

    using System.ServiceModel;

  4. In the IndigoDemo namespace, we'll first create the service contract. We'll choose for a contract named IHello with two members, SendMeGreeting and HelloIndigo, as shown below. Notice the use of an interface and the ServiceContract and OperationContract attributes:

    [ServiceContract]
    public interface
    IHello
    {
        [
    OperationContract
    ]
        string SendMeGreetings(string
    name);
        [
    OperationContract
    ]
        string
    HelloIndigo();
    }

  5. To the same IndigoDemo namespace, add a class called HelloService that implements IHello, as shown below:

    public class HelloService : IHello
    {
        #region
    IHello Members

        public string SendMeGreetings(string
    name)
        {
            return string.Format("Hello {0}"
    , name);
        }

        public string
    HelloIndigo()
        {
           
    return "Hello Indigo"
    ;
        }

       
    #endregion
    }

  6. Now it's time to create the "service host" that will run the service. ServiceHost is the class you need to do this. The following Main method contains the Indigo hosting code for our service:

    static void Main(string[] args)
    {
         //
         //Host the service in a simple console application
         //
         using (ServiceHost<HelloService> svc = new ServiceHost<HelloService
    >())
         {
              //
              //Add endpoint for the IHello contract, with a default WS-Profile binding on the specified address
              //
             
    svc.AddEndpoint(
                  
    typeof(IHello
    ),
                  
    new WSProfileBinding
    (),
                  
    "http://localhost:1234/HelloService"
             
    );

             
    //
             
    //Launch the service
             
    //
             
    svc.Open();

             
    Console.WriteLine("Service is running. Press <ENTER> to stop."
    );
             
    Console
    .ReadLine();

             
    //
             
    //Stop the service
             
    //
             
    svc.Close();
         }
    }

    In this code, we create a (generic) instance of a ServiceHost for our HelloService. Next, an endpoint is added, which consists of an address, a binding and a service contract, being the interface IHello which was annotated with the ServiceContract tag earlier. Starting the service is as simply as calling Open, and stopping it can be done using Close.

  7. So far so good. The service is ready, now we'll jump to the client-side piece of our demo. In the Visual Studio 2005 IndigoDemo solution, add a new C# Console Application project called IndigoDemoClient.

  8. In the Solution Explorer under IndigoDemoClient, right-click on References and choose "Add Reference...". Select System.ServiceModel from the list and click OK.

  9. In order to make our client aware of the service contract of our service, we need to copy the IHello interface over here as well. We'll see a sample with discovery later on. For now, just copy the IHello interface to the IndigoDemoClient namespace:

    [ServiceContract]
    public interface
    IHello
    {
        [
    OperationContract
    ]
        string SendMeGreetings(string
    name);
        [
    OperationContract
    ]
        string
    HelloIndigo();
    }

  10. Time for the client. As you might expect, we need a proxy. How to obtain that proxy? Using the generic ChannelFactory.CreateChannel static factory method, as shown below:

    static void Main(string[] args)
    {
       
    //
       
    //Ask the user for input
       
    //
       
    Console.WriteLine("Client is running. Enter your name and press <ENTER> to talk to the service."
    );
       
    string name = Console
    .ReadLine();

        //
        //Create a proxy for the service
        //
        IHello proxy = ChannelFactory.CreateChannel<IHello
    >(
           
    new Uri("http://localhost:1234/HelloService"
    ),
           
    new WSProfileBinding
    ()
        );

        //
        //Call the service to send a greeting
       
    //
        string
    greeting = proxy.SendMeGreetings(name);

       
    //
       
    //Housekeeping
       
    //
       
    ((IChannel
    ) proxy).Close();
        ((
    IChannel
    ) proxy).Dispose();

       
    //
       
    //Output to the user
        //
       
    Console.WriteLine("The server answered: {0}"
    , greeting);
       
    Console.WriteLine("Press <ENTER> to quit."
    );
       
    Console
    .ReadLine();
    }


    This code should be pretty self-explanatory in my very opinion. As you can see, the use of generics makes creation of a proxy easier but also introduces some plumbing (see the housekeeping part). You can avoid this plumbing however by applying the following trick to IHello:

    [ServiceContract]
    public interface
    IHello : IChannel
    {
        [
    OperationContract
    ]
        string SendMeGreetings(string
    name);
        [
    OperationContract
    ]
        string
    HelloIndigo();
    }


    and changing Main like this:

    static void Main(string[] args)
    {
        //
        //Ask the user for input
        //
        Console.WriteLine("Client is running. Enter your name and press <ENTER> to talk to the service."
    );
        string name = Console
    .ReadLine();

        //
        //Placeholder for the answer
        //
        string
    greeting;

        //
        //Create a proxy for the service
        //
        using (IHello proxy = ChannelFactory.CreateChannel<IHello
    >(
            new Uri("http://localhost:1234/HelloService"
    ),
            new WSProfileBinding
    ()))
        {
            //
            //Call the service to send a greeting
            //
            greeting = proxy.SendMeGreetings(name);

            //
            //Close connection to the service
            //
            proxy.Close();
        }

        //
        //Output to the user
        //
        Console.WriteLine("The server answered: {0}"
    , greeting);
        Console.WriteLine("Press <ENTER> to quit."
    );
        Console
    .ReadLine();
    }

  11. Time to run it. Right-click the IndigoDemo solution on top of the Solution Explorer and choose Properties. In Common Properties, Startup Project select Multiple startup projects and set the action for both the IndigoDemo and IndigoDemoClient application to 'Start'. Click OK.

  12. Now hit F5 to run the application. Once the service console prints "Service is running. Press <ENTER> to stop." switch to the client console and type you name. Output similar to the following should be displayed:

    Client is running. Enter your name and press <ENTER> to talk to the service.
    Bart
    The server answered: Hello Bart
    Press <ENTER> to quit.

  13. Exit the client by pressing <ENTER> but leave the service host console window running.

In this first sample you saw how to create both a service and a client without the use of a configuration file, just by writing plain code. I chose to use the WSProfileBinding which is well-suited for HTTP (or HTTPS) services with the well-known Request-Response (or Simplex) message pattern style. One of the things we saw was how to create a proxy using the ChannelFactory class of Indigo. Now I want to take you to the next step of discovering a running service:

  1. Assuming you followed the steps above correctly, the service should still be running now. If it's not, restart the Visual Studio 2005 debugger using F5 and wait for the service to come alive.
  2. Open an instance of Internet Explorer and go to http://localhost:1234/HelloService. You should see a page "Indigo Service" that tells you "You have created an Indigo service." If you didn't realize this yet, it's time to awake now :-). The page also contains a link to the well-known WSDL discovery address on http://localhost:1234/HelloService?wsdl, just like this was the case with classic web services.
  3. Indigo provides a command-line utility called svcutil.exe which is accessible through the Visual Studio 2005 Command Prompt. Call svcutil.exe /? to see the functionality it provides:

    C:\temp>svcutil
    Microsoft (R) Service Model Metadata Tool
    [Microsoft(R) .NET Framework, Version 2.0.50215.0]
    Copyright (C) Microsoft Corporation. All rights reserved.

    svcutil.exe: Utility to generate ServiceModel code from Metadata documents, and
    vice versa.

        - USAGE -
    svcutil.exe [options] [metadataPath* | assemblyPath* | metadataUrl*]


    svcutil.exe differs from wsdl.exe on quite some fields. One notable difference is the support to work in two ways: metadata-to-assembly and assembly-to-metadata.
  4. Time to experiment with it. Execute svcutil.exe http://localhost:1234/HelloService?wsdl as mentioned on the web page from step 2. The result should look like this:

    C:\temp>svcutil.exe http://localhost:1234/HelloService?wsdl
    Microsoft (R) Service Model Metadata Tool
    [Microsoft(R) .NET Framework, Version 2.0.50215.0]
    Copyright (C) Microsoft Corporation. All rights reserved.

    Generating files...
    C:\temp\tempuri.org.Bindings.cs
    C:\temp\output.config


    Two files have been generated. Take a look at both of these using Notepad
    .
  5. In the first file, the tempuri.org.Bindings.cs file, you should find three members. First of all, there's a IHello interface that looks the same as the original one you wrote yourself in the service's code. The second interface is the IHelloChannel which derives from IHello and IProxyChannel. And last the most important class, HelloProxy. This class both derives from the IHello contract interface and the ProxyBase generic class. Notice that the address of the endpoint is not in the code, in contrast to the output of wsdl.exe in the (near) past. This variable information lives in the output.config file.
  6. Open the output.config file and notice the following sections (marked in red):

    <?xml version="1.0" encoding="utf-8"?>
    <configuration xmlns="
    http://schemas.microsoft.com/.NetConfiguration/v2.0">
        <system.serviceModel>
            <client>
                <endpoint address="
    http://localhost:1234/HelloService" bindingConfiguration="IHello"
                    bindingSectionName="customBinding" contractType="IHello">
                    <addressProperties actingAs="
    http://localhost:1234/HelloService"
                        identityData="" identityType="None" isAddressPrivate="false" />
                </endpoint>
            </client>
            <bindings>
                <customBinding>
                    <binding configurationName="IHello">
                        <contextFlow transactions="Ignore" transactionHeaderFormat="OleTx"
                            logicalThreadId="Ignore" locale="Ignore" />
                        <security algorithmSuite="Default" authenticationMode="SspiNegotiated"
                            contextMode="Session" defaultProtectionLevel="EncryptAndSign"
                            enableKeyDerivation="true" includeTimestamp="true" messageProtectionOrder="SignBeforeEncrypt"
                            securityVersion="WSSecurityXXX2005" secureConversationVersion="WSSecureConversationFeb2005"
                            trustVersion="WSTrustFeb2005" generateRequestSignatureConfirmation="false" />
                        <httpTransport manualAddressing="false" maxMessageSize="65536"
                            authenticationScheme="Anonymous" bypassProxyOnLocal="false"
                            hostnameComparisonMode="StrongWildcard" mapAddressingHeadersToHttpHeaders="false"
                            proxyAuthenticationScheme="Anonymous" realm="" transferTimeout="00:01:00"
                            useSystemWebProxy="true" />
                        <textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
                            messageVersion="Default" encoding="utf-8" />
                    </binding>
                </customBinding>
            </bindings>
        </system.serviceModel>
    </configuration>


    All of the marked sections should be easy to understand right now. There's an endpoint which consist of - remember? - an address, a binding and a contract. Remember that these three go hand-in-hand all the time. I won't cover the other stuff of the config file for now, but most of the generated stuff is related to the WS-Profile binding that was specified concerning security, sessions, transport protocol and encoding.
  7. Let's create a simple client now, at the command line. In the folder where the tempuri.org.Bindings.cs file was dropped, create a new file called demo.cs and add the following code to it:

    class Test
    {
        static void Main(string[] args)
        {
            HelloProxy proxy = new HelloProxy();
            string result = proxy.SendMeGreetings(args[0]);
            System.Console.WriteLine("The Hello service returned '" + result + "'");
            proxy.Close();
        }
    }

  8. Now compile the tempuri.org.Bindings.cs file first, as follows:

    C:\temp>csc -r:System.ServiceModel.dll -t:library tempuri.org.Bindings.cs
    Microsoft (R) Visual C# 2005 Compiler version 8.00.50215.44
    for Microsoft (R) Windows (R) 2005 Framework version 2.0.50215
    Copyright (C) Microsoft Corporation 2001-2005. All rights reserved.
  9. Next, build the demo.cs file, referencing both the System.ServiceModel.dll and tempuri.org.Bindings.dll assemblies:

    C:\temp>csc -r:tempuri.org.Bindings.dll,System.ServiceModel.dll demo.cs
    Microsoft (R) Visual C# 2005 Compiler version 8.00.50215.44
    for Microsoft (R) Windows (R) 2005 Framework version 2.0.50215
    Copyright (C) Microsoft Corporation 2001-2005. All rights reserved.
  10. Last but not least, rename output.config to demo.exe.config:

    ren output.config demo.exe.config
  11. Now run demo.exe with one parameter, specifying your name:

    C:\temp>demo Bart
    The Hello service returned 'Hello Bart'

Works great. So far, we've been hosting our service in a console application. However, you can host the service in IIS as well (or in other hosts). Let me show how (assuming you have IIS 5.1 or 6.0 up and running and you installed .NET v2.0 and WinFX afterwards):

  1. Stop your Visual Studio 2005 debugger if it's still running. Add a C# Type Library project to the solution and give it the name "IndigoDemoLibrary".
  2. In the Solution Explorer under IndigoDemoLibrary, right-click on References and choose "Add Reference...". Select System.ServiceModel from the list and click OK.

  3. Add the IHello interface and the HelloService class of the earlier IndigoDemo service project to the Class1.cs file. Save the file and compile the solution.

  4. Open Windows Explorer and create a folder somewhere on your system. I'll be using c:\temp\HelloService. In this new folder, create a subfolder called bin.

  5. Open the bin-folder of the IndigoDemoLibrary project, in my case C:\Documents and Settings\...\My Documents\Visual Studio 2005\Projects\IndigoDemo\IndigoDemoLibrary\bin\Debug, and copy the IndigoDemoLibrary.dll file to the bin folder (c:\temp\HelloService\bin) created in step 4 above.

  6. In the (root) folder created in step 4 above (c:\temp\HelloService), create a file called service.svc, with the following code:

    <%@Service Language="C#" class="IndigoDemoLibrary.HelloService" %>
    <%@Assembly Name="IndigoDemoLibrary" %>

  7. In the same folder, create a web.config file containing:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration xmlns="
    http://schemas.microsoft.com/.NetConfiguration/v2.0">
        <system.serviceModel>
            <services>
                <service serviceType="IndigoDemoLibrary.HelloService">
                    <endpoint address="" bindingSectionName="wsProfileBinding" contractType="IndigoDemoLibrary.IHello, IndigoDemoLibrary" />
                </service>
            </services>
        </system.serviceModel>
    </configuration>

  8. Now it's time to configure the Indigo service virtual directory in IIS. Go to Start, Run, enter "inetmgr" (without quotes) and click OK. Locate the "Default Web Site" under <computername>\Web Sites. Right-click and choose New, Virtual Directory. Click Next. In the field Alias specify "HelloService" (wtihout quotes) and click Next again. Now specify the folder you created in step 3 (c:\temp\HelloService). Click Next. On the "Access Permissions" wizard screen make sure both Read and Run scripts are enabled and click Next. Finally, click on Finish.

  9. If you have both .NET v1.x and v2.0 on the machine, right click on the HelloService virtual directory you just created and go to the Properties. On the ASP.NET tab in the first dropdownlist select version 2.0.50215.0 and click OK.

  10. Open an Internet Explorer instance and navigate to http://localhost/helloservice/service.svc. You should get to see the same page as you saw earlier with our console-hosted Indigo service.

  11. I guess you'll be able to figure out for yourself how to adapt the demo.exe.config file from the previous demo in order to use the IIS-hosted Indigo service instead. Small tip: you need to change an address on two places, somewhere in the neighborhood of the <endpoint> tag :-). In case you're not seeing clear enough, an alternative configuration file is listed below:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
        <system.serviceModel>
            <client>
                <endpoint
                    address="http://localhost/HelloService/service.svc"
                    bindingConfiguration="IHello"
                    bindingSectionName="wsProfileBinding"
                    contractType="IHello" />
            </client>
            <bindings>
                <wsProfileBinding>
                    <binding configurationName="IHello" />
                </customBinding>
            </bindings>
        </system.serviceModel>
    </configuration>

 

What's coming next?

In my next Indigo-related posts, I'll cover data and message contracts, other types of addresses and binding and much more. Stay tuned once again ... you ain't see nothing yet :-).

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Filed under:

Comments

No Comments