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); }