Pages

Wednesday, September 15, 2010

How to create a WCF service without Visual Studio

WCF is the first step in building a truly service oriented application for you. It is the most important when working with distributed architecture. The sophisticated design of WCF made me think of using it always when I need any Web service to be installed in the server. Visual Studio is capable of creating its own configuration settings that helps in developing our application with ease. But what if you don’t have Visual Studio? In this post I am going to implement one of the most basic WCF service without using Visual Studio and show you how to interact with the service. Lets do it step by step:

Server Side

Steps to create the Service definition (Contract):

  1. Open Notepad and add namespace System and System.ServiceModel. We need ServiceModel to specify a WCF service
  2. For WCF service we need to create an interface which will act as a proxy to the client.  From the client, we need to replicate the proxy object and build the same interface again. After we declare the Interface we mark the Interface with ServiceContract, and the method to be exposed to outside using OperationContract.
  3. Next we create a concrete class for the same to define the class implementing the interface.
So our server is Ready.

[ServiceContract]
public interface IOperationSimpleWCF
{
    [OperationContract]
    string MySimpleMethod(string inputText);
}

public class OperationSampleWCF : IOperationSimpleWCF
{
    public string MySimpleMethod(string inputText)
    {
        Console.WriteLine("Message Received : {0}", inputText);
        Console.WriteLine(OperationContext.Current.RequestContext.RequestMessage.ToString());
        return string.Format("Message from Server {0}", inputText);
    }
}


Steps to host the service (Address , Binding):

To host the service in the server you need to know three inputs:

  1. Binding : This indicates how the service will be hosted.  For  basic soap operation with no security we need HttpBinding. We can also use other bindings as well.
  2. Address : Represents the location to host the service. When the service is hosted you can specify the qualified service path where the service will be hosted.
  3. Host the service using ServiceHost and Open the connection.
Download Sample Code - 47KB



static void Main(string[] args)
{

    BasicHttpBinding binding = new BasicHttpBinding();
            
    Uri serviceUri = new Uri("http://localhost:8000");
    ServiceHost host = new ServiceHost(typeof(OperationSampleWCF), serviceUri);
    host.AddServiceEndpoint(typeof(IOperationSimpleWCF), binding, "OperationService");


    host.Open();

    Console.WriteLine("Service is hosted to the Server");
    Console.ReadLine();

    host.Close();
            
}

So the uri where the service is hosted is http://localhost:8000/OperationService. You should notice the call AddServiceEndpoint is used to give the qualified address for the service. If you don’t specify AddServiceEndpoint the service will be posted to root path of Uri specified.

To Compile the Server application : 

  1. Open Command prompt and navigate to the location where you save the File with code.
  2. To compile the program use csc with /r: to reference the System.ServiceModel.dll using (Say the file we save for code is ServerProgram.cs)
    csc /r:” C:\windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\System.ServiceModel.dll” ServerProgram.cs
  3. You will get the program compiled, and produce the Executable. Run the program.
 After you run the program it will show the following screen :

Hence the service is running and waiting for the client to receive request.

Now its time to create our client application.

Client Side

Steps to create Client Application :

  1. First you need to mimic the ServiceContract interface in the client. If you want to check the Request Body you can use OperationContext.Current.RequestContext.RequestMessage, Or you can directly parse the soap contract using and create the Contract class yourself. 
  2. Once we have created the Contract, we create an object of ChannelFactory which actually creates the interface between the client and the server.  The ChannelFactory requires the Binding, and EndPointAddress. The endpoint address for our client will be http://localhost:8000/OperationService
  3. Finally we call CreateChannel to get the actual proxy object which is capable of calling the Remote server. 
  4. Compile the Client 
 Hence when we call the server, the output will be shown on the client.



    static void Main(string[] args)
    {
        Console.WriteLine("Press Enter to call Server");
        Console.ReadLine();
    
    
        BasicHttpBinding binding = new BasicHttpBinding();
        ChannelFactory<IOperationSimpleWCF> factory = new ChannelFactory<IOperationSimpleWCF>(binding,
                                                                    new EndpointAddress("http://localhost:8000/OperationService"));
    
        IOperationSimpleWCF proxy = factory.CreateChannel();
        string methodFromServer = proxy.MySimpleMethod("Hello");
                
        Console.WriteLine(methodFromServer);
    
        Console.ReadLine();
    }
    
    [ServiceContract]
    public interface IOperationSimpleWCF
    {
        [OperationContract]
        string MySimpleMethod(string inputText);
    }

    Once we are done we need to compile the client again using csc.
    csc /r:” C:\windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\System.ServiceModel.dll” ClientProgram.cs

    Now open the two console side by side, and when you call the server from Client console, it updates the server console. Hence the server been called properly.






    If you open the call to OperationContext.Current.RequestContext.RequestMessage.ToString() you can see the Soap envelope that is passed as request to the server from the client. It will look like :

    <s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">
     <s:Header>
        <To s:mustUnderstand=\"1\" xmlns=\"http://schemas.microsoft.com/ws/2005/05/addressing/none\">http://localhost:8000/OperationService</To>
        <Action s:mustUnderstand=\"1\" xmlns=\"http://schemas.microsoft.com/ws/2005/05/addressing/none\">http://tempuri.org/IOperationSimpleWCF/MySimpleMethod</Action>
      </s:Header>
      <s:Body>
        <MySimpleMethod xmlns=\"http://tempuri.org/\">
          <inputText>Hello</inputText>
        </MySimpleMethod>
      </s:Body>
    </s:Envelope>

    Now if you change the Binding from BasicHttpBinding to WSHttpBinding the program outputs the same while the Request body changes with all the support of security features and the message passed within the Soap envelope will automatically been encrypted.

    <s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:a=\"http://www.w3.org/2005/08/addressing\" xmlns:u=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">
      <s:Header>
        <a:Action s:mustUnderstand=\"1\" u:Id=\"_2\">http://tempuri.org/IOperationSimpleWCF/MySimpleMethod</a:Action>
        <a:MessageID u:Id=\"_3\">urn:uuid:b3edb9bc-6043-4c05-b540-794e5d61d505</a:MessageID>
        <a:ReplyTo u:Id=\"_4\">
          <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
        </a:ReplyTo>
        <a:To s:mustUnderstand=\"1\" u:Id=\"_5\">http://localhost:8000/OperationService</a:To>
        <o:Security s:mustUnderstand=\"1\" xmlns:o=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\">
          <u:Timestamp u:Id=\"uuid-ce693b53-159f-492e-b79a-f904abb878d8-11\">
            <u:Created>2010-09-14T23:26:22.015Z</u:Created>
            <u:Expires>2010-09-14T23:31:22.015Z</u:Expires>
          </u:Timestamp>
          <
    c:SecurityContextToken u:Id=\"uuid-ff9818d2-87c0-4daa-ba54-ce07e283ca38-4\" xmlns:c=\"http://schemas.xmlsoap.org/ws/2005/02/sc\">
            <c:Identifier>urn:uuid:2a3567f3-73e7-4f8d-9a5d-f2be8defae2f</c:Identifier>
          </c:SecurityContextToken>
          <c:DerivedKeyToken u:Id=\"uuid-ce693b53-159f-492e-b79a-f904abb878d8-9\" xmlns:c=\"http://schemas.xmlsoap.org/ws/2005/02/sc\">
            <o:SecurityTokenReference>
              <o:Reference ValueType=\"http://schemas.xmlsoap.org/ws/2005/02/sc/sct\" URI=\"#uuid-ff9818d2-87c0-4daa-ba54-ce07e283ca38-4\" />
            </o:SecurityTokenReference>
            <c:Offset>0</c:Offset>
            <c:Length>24</c:Length>
            <c:Nonce>zIN3JJx6Ce3YudbqTPApWQ==</c:Nonce>
          </c:DerivedKeyToken>
          <c:DerivedKeyToken u:Id=\"uuid-ce693b53-159f-492e-b79a-f904abb878d8-10\" xmlns:c=\"http://schemas.xmlsoap.org/ws/2005/02/sc\">
            <o:SecurityTokenReference>
              <o:Reference ValueType=\"http://schemas.xmlsoap.org/ws/2005/02/sc/sct\" URI=\"#u
    uid-ff9818d2-87c0-4daa-ba54-ce07e283ca38-4\" />
            </o:SecurityTokenReference>
            <c:Nonce>+ie7ja4mY4bPB5iwgiZHCg==</c:Nonce>
          </c:DerivedKeyToken>
          <e:ReferenceList xmlns:e=\"http://www.w3.org/2001/04/xmlenc#\">
            <e:DataReference URI=\"#_1\" />
            <e:DataReference URI=\"#_6\" />
          </e:ReferenceList>
          <e:EncryptedData Id=\"_6\" Type=\"http://www.w3.org/2001/04/xmlenc#Element\" xmlns:e=\"http://www.w3.org/2001/04/xmlenc#\">
            <e:EncryptionMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#aes256-cbc\" />
            <KeyInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\">
              <o:SecurityTokenReference>
                <o:Reference ValueType=\"http://schemas.xmlsoap.org/ws/2005/02/sc/dk\" URI=\"#uuid-ce693b53-159f-492e-b79a-f904abb878d8-10\" />
              </o:SecurityTokenReference>
            </KeyInfo>
            <e:CipherData>
              <e:CipherValue>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</e:CipherValue>
            </e:CipherData>
          </e:EncryptedData>
        </o:Security>
      </s:Header>
      <s:Body u:Id=\"_0\">
        <MySimpleMethod xmlns=\"http://tempuri.org/\">
          <inputText>Hello</inputText>
        </MySimpleMethod>
      </s:Body>
    </s:Envelope>

    Similar to it, if you have just changed the Binding and the address to NetTcpBinding and net:tcp://localhost:8000 it will work very similarly.

    By this way you can create your own WCF service and call it from the client without even using Visual Studio.

    Download Sample Code - 47KB

    I hope this will help you. Thanks for reading.

    3 comments:

    1. I found this from google. Thanks for the post

      ReplyDelete
    2. Thanks a lot, it simple open my eyes on how it really works. Could you be more specific about https autentication and ssl cerificates (more advanced form of autentication)

      ReplyDelete

    Please make sure that the question you ask is somehow related to the post you choose. Otherwise you post your general question in Forum section.