DCSIMG
Vladislav Amirov

Vladislav Amirov

Integrating .NET technologies in to the enterprise system is an exciting proposition!
www.easy-forex.com

WcfTestClient Launcher

All of us (one that dialed WCF technologies) tried to make and run WCF host service project created by VS 2008 WCF Service Library template. It's very useful template that help us to configure and debug our service.

Two most effective tools executed at debugging are WcfSvcHost and WcfTestClient. When you press F5 key (Start Debugging) WCF Service Library project launch WcfSvcHost.exe with command line argument /client:"WcfTestClient.exe" that run WcfTestClient application. This is fine but what if you have Consol, Window or Web Application and you have no goodies of WCF Service Library project. Of course you can execute manually WcfTestClient in Command Prompt (Outside Visual Studio) but it's not useful (really, you aren’t going to do this each debug time). And what about to have some WcfTestClient instance during your debugging or you need to host some WCF services?

Ok, how am I going to do this? First I tried make a batch (*.bat) file and to change debug property from 'Start project' to 'Start external program:' with this batch file but, oops… The external program must to be executable file path (*.exe).




Alert if you try to run debagging



So I decided to create a simple Class Library Project with single help static that can to launch WcfTestClient tool with your needed settings. By the way this class can be included to your project as well. The class has static Start() overloaded functions that launch the WcfTestClient  tool by specify path to WcfTestClient.exe file or by VS 2008 environment definition, plus the function uses all metadata addresses retrieved from ServiceHost instance or your provided metadata addresses.

Source Code

Using WcfTestClient Launcher snippet code:

Example 1
ServiceHost sh = new ServiceHost(typeof(Trading));
sh.Open();

//Self WcfTestClient.exe discovering and retriving metadata from ServiceHost instance

Process process1 = WcfTestClientLauncher.Start(sh);

process1.WaitForExit();

 

Example 2

string wcfTestClientPath = @"C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\WcfTestClient.exe";

string serviceMetadataAddresses = "http://localhost:8181/CustomBaseServer/Trading/";

Process process2 = WcfTestClientLauncher.Start(wcfTestClientPath, serviceMetadataAddresses);

process2.WaitForExit();

 

Example 3

ServiceHost sh1 = new ServiceHost(typeof(Trading));

sh1.Open();

 

ServiceHost sh2 = new ServiceHost(typeof(Trading1), new Uri("http://localhost:8181/CustomBaseServer/Trading1/"));

sh2.AddServiceEndpoint(typeof(ITrading), new BasicHttpBinding(), "");

 

ServiceMetadataBehavior metadataBehavior = sh2.Description.Behaviors.Find<ServiceMetadataBehavior>();

if (metadataBehavior == null)

{

    metadataBehavior = new ServiceMetadataBehavior();

    metadataBehavior.HttpGetEnabled = true;

    sh2.Description.Behaviors.Add(metadataBehavior);

}

sh2.Open();

 

#if (DEBUG)

Process p1 = WcfTestClientLauncher.Start(sh1);

Process p2 = WcfTestClientLauncher.Start(sh2);

 

Console.ReadLine();

 

p1.CloseMainWindow();

p1.WaitForExit();

p2.CloseMainWindow();

p2.WaitForExit();

#endif

 

In this last example I have to test two services hosted both in one AppDomain, it's very simple to test them with WcfTestClient launched by my small tool.

 

Example 3 snapshot

 
Posted: Jul 20 2009, 06:10 PM by FanMix | with no comments
תגים:,

Coupling Issue Solution by WCF Technology - Part II

In my first post we could see different client and service contract interfaces that successfully worked in reviewed example. The differences between two interfaces were in following details:
  1. Namespace:  CustomBaseServer and CustomBaseClient – works without specify solution
  2. Interface Name: Trading and Trading1 – solved by [ServiceContract (Name=...)]
  3. Method Name:  GetRate and GetRate1 - solved by [OperationContract(Name=...)]
So we have enough reasons to say that interfaces really diverse. But between two contacts can be additional differences worked and supported by WCF as well:
  1. Number of methods
  2. Number of method parameters
  3. Name of method parameters
Example Source Code

File: ITrading.cs - Service Interface Code Snippet

namespace CustomBaseServer
{

    [ServiceContract]

    interface ITrading

    {

        [OperationContract]

        void Foo1();

 

        [OperationContract]

        void Foo2(string text);

 

        [OperationContract]

        void Foo3(

            //[MessageParameter(Name = "p1")] int x

            //,[MessageParameter(Name = "p2")] int y

            //,[MessageParameter(Name = "p3")] int z

            int x, int y, int z);

 

        [OperationContract]

        void Foo4(double val);

 

        void Foo88(DateTime dt);

    }

}

 

 

File: ITrading.cs - Client Interface Code Snippet 

namespace CustomBaseClient

{

    [ServiceContract(Name = "ITrading")]

    interface ITrading1

    {

        [OperationContract]

        void Foo();

 

        [OperationContract]

        void Foo1();

 

        [OperationContract]

        void Foo2();

 

        [OperationContract]

        void Foo3(int y, int var2);

 

        void Foo99();

    }

}

 

 

File: Programm.cs - Client Consol Code Snippet 

namespace CustomBaseClient

{

    class Program

    {

        //Run it in debug mode

        static void Main(string[] args)

        {

            Console.WriteLine("Client start...");

            var channelFactory = new ChannelFactory<ITrading1>("ITradingBasicHttp");

            //var channelFactory = new ChannelFactory<ITrading1>("ITradingWebService");

            var trading = channelFactory.CreateChannel();

 

            //ActionNotSupportedException, this method undefined in service contract

            trading.Foo();

 

            //Ok

            trading.Foo1();

 

            //Ok, but the service side gets null string

            trading.Foo2();

 

            //Ok, but service side gets only "y" parameter, x and z is initialized with

            //zero value. Even first client and second service parameter matched by

            //common ("y") name. It's work, great!  

            trading.Foo3(11 /*y*/, 22 /*var*/);

 

            //System.NotSupportedException, this method is not marked with

            //OperationContractAttribute in both client and service sides.

            trading.Foo99();

 

            Console.ReadLine();

        }

    }

}

 

Example Source Code

So, WCF is able to match in runtime service contract methods and its parameters numbers and names. It's a very useful capability for enterprise flexibility and amazing SOAP using structure for service versioning management (Service Versioning in my next post).

 

Posted: Jul 14 2009, 02:02 AM by FanMix | with no comments
תגים:,

Coupling Issue Solution by WCF Technology

In one of my discussions with my colleagues about WCF technology we talked about coupling concept and how come WCF solves this important issue. So my decision was creating a very simple code example that explains and shows a key moment of WCF coupling solution.

This example is a simple VS 2008 solution with two consol application projects, CustomBaseServer and CustomBaseClient. The CustomBaseServer  is a service host project and the CustomBaseClient is a service client project that don't use client proxy generated by (Svcutil.exe) tool but use ChannelFactory (how to use ChannelFactory) object instead.

Example Source Code

-- CustomBaseServer  - Service Host Project --

File: ITrading.cs - Service Contract Definition

using System;

using System.ServiceModel;

 

namespace CustomBaseServer

{

    [ServiceContract]

    interface ITrading

    {

        [OperationContract]

        double GetRate(string symbol);

    }

}

 

File: Trading.cs - Service Contract Implemetetion

 

using System;

 

namespace CustomBaseServer

{

    class Trading : ITrading

    {

        public double GetRate(string symbol)

        {

            return 123.456;

        }

    }

}

 

File: Program.cs - Server Consol Runner

using System;

using System.ServiceModel;

 

namespace CustomBaseServer

{

    class Program

    {

        static void Main(string[] args)

        {

            Console.WriteLine("Server start...");

 

            ServiceHost sh = new ServiceHost(typeof(Trading));

            sh.Open();

 

            Console.ReadLine();

        }

    }

}

 

File: App.config - Service Application Configuration 

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <system.serviceModel>

    <services>     

      <service name="CustomBaseServer.Trading">

        <host>

          <baseAddresses>

            <add baseAddress="http://localhost:8181/CustomBaseServer/Trading"/>

          </baseAddresses>

        </host>

        <endpoint address="" binding="basicHttpBinding" contract="CustomBaseServer.ITrading"/>

      </service>

    </services>

  </system.serviceModel>

</configuration>


Note for Vista users: Visual Studio 2008 must be executed in administrator mode or you have to run the console (cmd) in administrator mode and launch next command "netsh http add urlacl url=http://+:8181/CustomBaseServer/Trading user=domain\vlad", learn more http://msdn.microsoft.com/en-us/library/ms733768.aspx.

 

-- CustomBaseClient  - Service Client Project --

File: ITrading.cs - Service Contract Definition

using System;

using System.ServiceModel;

 

namespace CustomBaseClient

{

    [ServiceContract(Name = "ITrading")]

    interface ITrading1

    {

        [OperationContract(Name = "GetRate")]

        double GetRate1(string symbol);

    }

}

 

File: Program.cs - Client Consol Runner

 

 

using System;

using System.ServiceModel;

 

namespace CustomBaseClient

{

    class Program

    {

        static void Main(string[] args)

        {

            Console.WriteLine("Client start...");

            var channelFactory = new ChannelFactory<ITrading1>("ITradingBasicHttp");

            var trading = channelFactory.CreateChannel();

 

            double rate = trading.GetRate1("EURUSD");

            Console.WriteLine(string.Format("Rate: {0}", rate));

 

            Console.ReadLine();

        }

    }

}

 

File: App.config - Client Application Configuration
 

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <system.serviceModel>

    <client>

      <endpoint

           address="http://localhost:8181/CustomBaseServer/Trading/"

           binding="basicHttpBinding"

           contract="CustomBaseClient.ITrading1"

           name="ITradingBasicHttp">

      </endpoint>

    </client>

  </system.serviceModel>

</configuration>


First of all there is no reference between two projects. Also there is no reference from one of these projects to another common or shared one. Two projects are absolutely independent. Like in the standard client – server application the client has to know only server address to establish connection with him.

How can you see the service client defines self CustomBaseClient.ITrading1 interface with GetRate1 function. This interface and its function are different then service host CustomBaseServer.ITrading interface and its GetRate function. To use the service functionality client must to have same defined service contract otherwise client throws System.ServiceModel.ActionNotSupportedException at its interface methods excusing. Exception message  example:  "The message with Action 'http://tempuri.org/ITrading1/GetRate' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver.  Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None".

In my case I used named parameter [Name] of ServiceContract and OperationContract Attributes for coordinating service ITrading and client ITrading1 interfaces name and their methods names.

By this example you can see how the WCF very elegantly solves  the old and heavy coupling issues. Based on the SOAP protocol the WCF technologies provide us supporting for agile R&D process and Application Lifecycle Management (ALM).

Example Source Code

Posted: Jul 09 2009, 01:19 PM by FanMix | with 7 comment(s)
תגים:,