Complete programmatic WCF service client wrapper in C#

Hi,the goal of this class was to avoid to use a app config file for the WCF object model so as to not have to restart my application (MDSManager) when updating endpoint url it is now done and you can update the endpoint on the fly!

 note: this post is based on Steve Wilkes’ article (see here)

 download the latest version of this class file (right click and ‘save as’ )

usage:

 using (ServiceClient c = new ServiceClientWrapper().CreateServiceClient())
                    {
}
Service Wrapper Code :
using System;
using System.Net;
using System.Net.Security;
using System.ServiceModel;
using Common.ServiceReference1;
using System.ServiceModel.Description;

namespace Common
{
    public class ServiceClientWrapper :
    ServiceClientWrapper<ServiceClient, ServiceReference1.IService>
    {
        public ServiceClientWrapper()
            : base()
        {
        }
    }

    public class ServiceClientWrapper<TClient, IService> : IDisposable
        where TClient : ClientBase
        where IService : class
    {
        public const int maxStringContentLength = 2147483647;
        private readonly string _domain;
        private readonly string _userName;
        private readonly string _password;
        private readonly Uri _uri;

        private TClient _serviceClient;

        public ServiceClientWrapper()
        {
            this._domain = Globals.Domain;
            this._userName = Globals.UserName;
            this._password = Globals.Password;
            this._uri = Globals.EndPointAddress;

        }

        public ServiceClientWrapper(string domain, string userName, string password, Uri uri)
        {
            this._domain = domain;
            this._userName = userName;
            this._password = password;
            this._uri = uri;
        }
      public TClient CreateServiceClient()
        {
            this.DisposeExistingServiceClientIfRequired();
            if (Globals.EndPointAddress != null)
            {
                //if (this._config.IgnoreSslErrors)
                //{
                ServicePointManager.ServerCertificateValidationCallback =
                    (obj, certificate, chain, errors) => true;
                //}
                //else
                //{
                //    ServicePointManager.ServerCertificateValidationCallback =
                //        (obj, certificate, chain, errors) => errors == SslPolicyErrors.None;
                //}

                //here we can specify the end point identity, so as to avoid security negocation errors
                EndpointIdentity epid = EndpointIdentity.CreateUpnIdentity("host\\localhost");

// update : programmatic binding
EndpointAddress epaddr = new EndpointAddress(new Uri(Globals.EndpointAddress), epid);
            this._serviceClient = (TClient)Activator.CreateInstance(
                typeof(TClient), new WSHttpBinding()
                {
                    MaxBufferPoolSize = maxStringContentLength,
                    MaxReceivedMessageSize = maxStringContentLength,
                    OpenTimeout = new TimeSpan(1, 0, 0),
                    ReceiveTimeout = new TimeSpan(1, 0, 0),
                    SendTimeout = new TimeSpan(1, 0, 0)
                },
                epaddr);
                //we specify here the windows client credentials
                if (!string.IsNullOrEmpty(Globals.EndPointName))
                    this._serviceClient.Endpoint.Name = Globals.EndPointName;

                if (!string.IsNullOrEmpty(Globals.Domain))
                    this._serviceClient.ClientCredentials.Windows.ClientCredential.Domain = Globals.Domain;
 //update to specify UserName and Password for other credentials than ClientCredentials.Windows
 if (!string.IsNullOrEmpty(Globals.UserName))
            {
                this._serviceClient.ClientCredentials.Windows.ClientCredential.UserName = Globals.UserName;
                this._serviceClient.ClientCredentials.UserName.UserName = (!string.IsNullOrWhiteSpace(Globals.Domain) ? Globals.Domain + "\\" + Globals.UserName : Globals.UserName);
            }
            if (!string.IsNullOrEmpty(Globals.Password))
            {
                this._serviceClient.ClientCredentials.Windows.ClientCredential.Password = Globals.Password;
                this._serviceClient.ClientCredentials.UserName.Password = Globals.Password;
            }
                //here we override the "MaxItemsInObjectGraph" property with max value :2147483647, so as to avoid buffer limit error
                var operations = _serviceClient.Endpoint.Contract.Operations;
                foreach (var operation in operations)
                {

                    operation.Behaviors.Find().MaxItemsInObjectGraph = maxStringContentLength;
                }
                _serviceClient.InnerChannel.OperationTimeout = new TimeSpan(1, 0, 0);

                return this._serviceClient;
            }
            return null;
        }
     public void Dispose()
        {
            this.DisposeExistingServiceClientIfRequired();
        }

private void DisposeExistingServiceClientIfRequired() { if (this._serviceClient != null) { try { if (this._serviceClient.State == CommunicationState.Faulted) { this._serviceClient.Abort(); } else { this._serviceClient.Close(); } } catch { this._serviceClient.Abort(); } this._serviceClient = null; } } update october 29 : added 2 catch blocks so as to catch the REAL error message, please see this post: http://fczaja.blogspot.com/2009/05/communication-object.html

   
 private void DisposeExistingServiceClientIfRequired()
    {
            if (this._serviceClient != null)
            {
                try
                {
                    if (this._serviceClient.State == CommunicationState.Faulted)
                    {
                        this._serviceClient.Abort();
                    }
                    else
                    {
                        this._serviceClient.Close();
                    }
                }
                catch (CommunicationException)
                {
                    this._serviceClient.Abort();
                }
                catch (TimeoutException)
                {
                    this._serviceClient.Abort();
                }
                catch (Exception ex)
                {
                    this._serviceClient.Abort();
                    throw ex;
                }

                this._serviceClient = null;
            }
        }
    }
}

and your app.config “serviceModel” section will be reduced to: (and could be reduced even more..)

update details (@Oct 16,2011):

programatic bindind in C#

 EndpointAddress epaddr = new EndpointAddress(Globals.EndPointAddress, epid); this._serviceClient = (TClient)Activator.CreateInstance( typeof(TClient), Globals.EndPointName, epaddr);
becomes
            this._serviceClient = (TClient)Activator.CreateInstance(
                typeof(TClient), new WSHttpBinding()
                {
                    MaxBufferPoolSize = maxStringContentLength,
                    MaxReceivedMessageSize = maxStringContentLength,
                    OpenTimeout = new TimeSpan(1, 0, 0),
                    ReceiveTimeout = new TimeSpan(1, 0, 0),
                    SendTimeout = new TimeSpan(1, 0, 0)
                },
                epaddr);

update 2011/10/19: added a binding type switch

  EndpointIdentity epid = EndpointIdentity.CreateUpnIdentity("host\\localhost");
                // update : programmatic binding
                EndpointAddress epaddr = new EndpointAddress(Globals.EndPointAddress, epid);
                if (Globals.myBindingType == Globals.BindingType.BasicHttpBinding)
                {
                    this._serviceClient = (TClient)Activator.CreateInstance(
                        typeof(TClient), new BasicHttpBinding()
                        {
                            MaxBufferPoolSize = maxStringContentLength,
                            MaxReceivedMessageSize = maxStringContentLength,
                            ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
                            {
                                MaxArrayLength = maxStringContentLength,
                                MaxBytesPerRead = maxStringContentLength,
                                MaxDepth = 32,
                                MaxNameTableCharCount = maxStringContentLength,
                                MaxStringContentLength = maxStringContentLength
                            },
                            MaxBufferSize = maxStringContentLength,
                            UseDefaultWebProxy = true,
                            OpenTimeout = new TimeSpan(1, 0, 0),
                            ReceiveTimeout = new TimeSpan(1, 0, 0),
                            SendTimeout = new TimeSpan(1, 0, 0)
                        },
                        epaddr);
                }
                if (Globals.myBindingType == Globals.BindingType.WSHttpBinding)
                {
                    this._serviceClient = (TClient)Activator.CreateInstance(
                        typeof(TClient), new WSHttpBinding()
                        {
                            MaxBufferPoolSize = maxStringContentLength,
                            MaxReceivedMessageSize = maxStringContentLength,
                            OpenTimeout = new TimeSpan(1, 0, 0),
                            ReceiveTimeout = new TimeSpan(1, 0, 0),
                            SendTimeout = new TimeSpan(1, 0, 0),
                            ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
                            {
                                MaxArrayLength = maxStringContentLength,
                                MaxBytesPerRead = maxStringContentLength,
                                MaxDepth = 32,
                                MaxNameTableCharCount = maxStringContentLength,
                                MaxStringContentLength = maxStringContentLength
                            }
},
                        epaddr);
                }
Bookmark the permalink.

About Xavier

7 years+ .net consulting

Leave a Reply

Your email address will not be published.

Captcha * Time limit is exhausted. Please reload CAPTCHA.

This site uses Akismet to reduce spam. Learn how your comment data is processed.