Saturday, December 29, 2012

How to handle soap Exceptions


try
{
     service.StartGame();
}
catch(SoapHeaderException)
{
// soap fault in the header e.g. auth failed
}
catch(SoapException x)
{
// general soap fault  and details in x.Message
}
catch(WebException)
{
// e.g. internet is down
}
catch(Exception)
{
// handles everything else
}

Thursday, December 27, 2012

WCF Binding Decision Chart




1.   If your WCF service will have non-.NET clients choose Http Soap
2.   If your WCF will have .NET clients in other machines choose Net Tcp
3.   If your WCF will have .NET clients in the same machine choose Message Queue





WCF Binding Decision Chart



------------------------------------------------------------------------------------------------------------------------------

I found another version of the algorithm:
http://mohammedatef.files.wordpress.com/2009/06/wcfbinding.jpg

Tuesday, December 25, 2012

Working with Multiple Contracts, Multiple Endpoints in WCF


A given WCF service can be configured to work with Http, TCP , old asmx clients, non .Net clients etc etc. — by just changing configuration values, anytime after the service has been developed/deployed. I assume you are familiar with Address,Binding and Contract components of WCF.If not then this link can help, — http://msdn.microsoft.com/en-us/magazine/cc163647.aspx .Here in this example, I try to create different Endpoint combinations of a service residing in my Library. Following are few valid EndPoint generation combinations, in a given service.
Binding(B1) + Address(A1) + Contract(C1)  —>  valid EndPoint
Binding(B1) + Address(A2) + Contract(C1)  —>  valid EndPoint
Binding(B1) + Address(A1) + Contract(C2)  —>  valid EndPoint
Binding(B1) + Address(A1) + Contract(C3)  —>  valid EndPoint
Binding(B2) + Address(A2) + Contract(C1)  —>  valid EndPoint
Binding(B3) + Address(A3) + Contract(C1)  —>  valid EndPoint
For the above, the gist is –
1) Multiple EndPoints having same binding, but different contracts, can have same address.
2) Multiple EndPoints having different bindings, needs to have unique address.
I started with VS2010->Projects->NEW->WCF Service Library template. I added 2 WCFServices to this library — namely IHelloWorld and IByeWorld. Next I added one more ServiceContract “IMultipleContract” which is derived from IhelloWorld and IByeWorld interfaces. So IMultipleContract contains 2 Contracts. Next I rename my existing App.Config to something else — say AppOld.config. The point is, I will add a brand new ApplicationConfiguration file and make all necessary configuration changes using in-built WCF Configuration Editor.It’s a good choice to alter the configuration settings through configuration files & NOT in code , because then we don’t need to recompile & re-deploy the application, when we want to make the service work in different scenarios. My goal is to make this service (IMultipleContract), containing 2 differen contracts, — have different EndPoints, so that, if at all needed in future, it works with
– old ASMx or non-.Net clients through basicHttpBinding,
– .Net3.0 onwards clients with wsHttp or intranet-ready faster TCP binding. Hence I genearte 4 unique Endpoints. Other than for the TCP endPoint, I use common base Address and a path, to generate address information. Here’s how it goes.
1) basicHttpBinding Endpoint
Address=Base Address; Binding=basicHttpBinding; Contract=MyWCFLibrary.IMultipleContract;
2) WsHttpBinding EndPoint with Service Contract IhelloWorld
Address=Base Address+Path(test1); Binding=wsHttpBinding; Contract=MyWCFLibrary.IHelloWorld;
3) WsHttpBinding EndPoint with Service Contract IByeWorld
Address=Base Address+Path(test1); Binding=wsHttpBinding; Contract=MyWCFLibrary.IByeWorld;
Here’s the actual code and few screenshots of the WCF Configuration Editor.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace MyWCFLibrary
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IHelloWorld" in both code and config file together.
    [ServiceContract]
    public interface IHelloWorld
    {
        [OperationContract]
        string DoWork();
    }

    public class HelloWorld : IHelloWorld
    {
        public string DoWork()
        {
            return "Hello World";
        }
    }
}

namespace MyWCFLibrary
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IByeWorld" in both code and config file together.
    [ServiceContract]
    public interface IByeWorld
    {
        [OperationContract]
        string DoWork2();
    }
    public class ByeWorld : IByeWorld
    {
        public string DoWork2()
        {
            return "bye World";
        }
    }
}
namespace MyWCFLibrary
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IMultipleContract" in both code and config file together.
    [ServiceContract]
    public interface IMultipleContract : IHelloWorld, IByeWorld
    {
      
    }

    public class MultipleContract : IMultipleContract
    {
        public string DoWork()
        {
            return "Hello World Overidden";
        }

        public string DoWork2()
        {
            return "bye World overridden";
        }
    }

}
App.config
xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior name="MulContractService">
                    <serviceMetadata httpGetEnabled="true" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <bindings>
            <basicHttpBinding>
                <binding name="MulContractBasicBinding" />
            </basicHttpBinding>
            <netTcpBinding>
                <binding name="MulContractTCPBinding" />
            </netTcpBinding>
            <wsHttpBinding>
                <binding name="MulContractWsHttpBinding" />
            </wsHttpBinding>
        </bindings>
        <services>
            <service behaviorConfiguration="MulContractService" name="MyWCFLibrary.MultipleContract">
                <clear />
                <endpoint binding="basicHttpBinding" bindingConfiguration="MulContractBasicBinding"
                    name="MulContractBasicEndPoint" contract="MyWCFLibrary.IMultipleContract"
                    listenUriMode="Explicit">
                    <identity>
                      <dns value="localhost" />
                        <certificateReference storeName="My" storeLocation="LocalMachine"
                            x509FindType="FindBySubjectDistinguishedName" />
                    </identity>
                </endpoint>
                <endpoint address="test1" binding="wsHttpBinding" bindingConfiguration="MulContractWsHttpBinding"
                    name="MulContractWsHttp" contract="MyWCFLibrary.IByeWorld"
                    listenUriMode="Explicit">
                    <identity>
                      <dns value="localhost" />
                        <certificateReference storeName="My" storeLocation="LocalMachine"
                            x509FindType="FindBySubjectDistinguishedName" />
                    </identity>
                </endpoint>
                <endpoint address="test1" binding="wsHttpBinding" bindingConfiguration="MulContractWsHttpBinding"
                    name="MulContractWsHttp" contract="MyWCFLibrary.IHelloWorld"
                    listenUriMode="Explicit">
                    <identity>
                      <dns value="localhost" />
                        <certificateReference storeName="My" storeLocation="LocalMachine"
                            x509FindType="FindBySubjectDistinguishedName" />
                    </identity>
                </endpoint>
                <endpoint address="net.tcp://localhost:8733/Design_Time_Addresses/MyWCFLibrary/MultipleContract/"
                    binding="netTcpBinding" bindingConfiguration="MulContractTCPBinding"
                    name="MulContractTCPEndPoint" contract="MyWCFLibrary.IMultipleContract" />
                <host>
                    <baseAddresses>
                        <add baseAddress="http://localhost:8732/Design_Time_Addresses/MyWCFLibrary/MultipleContract/" />
                    </baseAddresses>
                </host>
            </service>
        </services>
    </system.serviceModel>
</configuration>