My app uses WCF to transfer data from server and app.It works well all along.But recently,if the app does not operate after a period of time,there's always throwing a timeout exception.When the timeout exception was thrown,winform application can call WCF normally。If restart debug,the app can call WCF again;and after a while,it throw timeout exception again.What can I do for this?
My code like this:
// CreateBinding
private static BasicHttpBinding CreateBasicHttp()
{
BasicHttpBinding binding = new BasicHttpBinding
{
Name = "basicHttpBinding",
MaxBufferSize = 2147483647,
MaxReceivedMessageSize = 2147483647
};
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
TimeSpan timeout = new TimeSpan(0, 0, 30);
binding.SendTimeout = timeout;
binding.OpenTimeout = timeout;
binding.ReceiveTimeout = timeout;
return binding;
}
// Create Endpoint
private static EndpointAddress CreateEndPoint(string serviceName)
{
string serviceUrl = App.RemoteUrl + serviceName + ".svc";
EndpointAddress EndPoint = new EndpointAddress(serviceUrl);
return EndPoint;
}
// Create binder
public static WCFBinder GetBinder<T>()
{
WCFBinder binder;
Type t = typeof(T);
string serviceName = t.Name.Substring(1, t.Name.Length - 1);
binder.Binding = CreateBasicHttp();
binder.EndPoint = CreateEndPoint(serviceName);
return binder;
}
// Create a client
var binder = SDHCommonMethod.GetBinder<IAAA001BLLService>();
IAAA001BLLService asc = new AAA001BLLServiceClient(binder.Binding, binder.EndPoint);
// Call WCF
var obj = await Task.Factory.FromAsync(asc.BeginSelectAAA001, asc.EndSelectAAA001, dto, TaskCreationOptions.None);
The code is right. In vs2017,it can work.Maybe my vs2015 has something wrong.
Related
I add a reference to a service in my .net core 2.2 project using svcutil 2.0.2 from here :
http://sms.magfa.com/services/urn:SOAPSmsQueue?wsdl
the created service proxy send the request to server and server send reply back to the us but the proxy can not get the result !!
we use this service in our asp .net web app but in .net core 2.2 using svcutil 2.0.2 we can not get the result.
what is the problem ?
thank you
my code :
BasicHttpBinding basicHttpBinding = null;
EndpointAddress endpointAddress = null;
ChannelFactory<ServiceReference1.SoapSmsQueuableImplChannel> factory = null;
ServiceReference1.SoapSmsQueuableImplChannel serviceProxy = null;
try
{
basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
basicHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
endpointAddress = new EndpointAddress(new Uri("https://sms.magfa.com/services/urn:SOAPSmsQueue?wsdl"));
factory = new ChannelFactory<ServiceReference1.SoapSmsQueuableImplChannel>(basicHttpBinding, endpointAddress);
factory.Credentials.UserName.UserName = "**";
factory.Credentials.UserName.Password = "****";
serviceProxy = factory.CreateChannel();
//((ICommunicationObject)serviceProxy).Open();
//var opContext = new OperationContext((IClientChannel)serviceProxy);
//var prevOpContext = OperationContext.Current; // Optional if there's no way this might already be set
//OperationContext.Current = opContext;
using (var scope = new OperationContextScope((IContextChannel)serviceProxy))
{
var result = await serviceProxy.getCreditAsync("***").ConfigureAwait(false);
}
factory.Close();
((ICommunicationObject)serviceProxy).Close();
}
catch (MessageSecurityException ex)
{
throw;
}
catch (Exception ex)
{
throw;
}
finally
{
// *** ENSURE CLEANUP (this code is at the WCF GitHub page *** \\
CloseCommunicationObjects((ICommunicationObject)serviceProxy, factory);
}
I have a Self-Hosted WCF Service and client.
The client does not have a service reference, I have linked it to the endpoint programmatically.
The bindings are set to BasicHttpBinding in both the client and service -
Service
Uri baseAddress = new Uri("http://localhost:8733/Design_Time_Addresses/DSCentralService/Service1/");
DSCentralService.Service1 contentServer = new DSCentralService.Service1();
//initialise the servicehost
centralSvrHost = new ServiceHost(typeof(DSCentralService.Service1), baseAddress);
//add bindings
centralSvrHost.AddServiceEndpoint(
typeof(DSCentralService.IService1),
new BasicHttpBinding(),
baseAddress
);
Client
serviceFactory = new ServiceFactory<DSCentralService.IService1>();
String serviceAddress="http://localhost:8733/Design_Time_Addresses/DSCentralService/Service1/";
iContentServer = serviceFactory.GetService(serviceAddress);
Service Factory Class
public class ServiceFactory<T> where T : class
{
private T _service;
public T GetService(string address)
{
return _service ?? (_service = GetServiceInstance(address));
}
private static T GetServiceInstance(string address)
{
BasicHttpBinding basicBinding = new BasicHttpBinding();
basicBinding.Name = "DSCentralSvr";
basicBinding.TransferMode = TransferMode.Streamed;
basicBinding.MessageEncoding = WSMessageEncoding.Mtom;
basicBinding.MaxReceivedMessageSize = 10067108864;
basicBinding.SendTimeout = new TimeSpan(0, 10, 0);
basicBinding.OpenTimeout = new TimeSpan(0, 10, 0);
basicBinding.CloseTimeout = new TimeSpan(0, 10, 0);
basicBinding.ReceiveTimeout = new TimeSpan(0, 10, 0);
EndpointAddress endpoint = new EndpointAddress(address);
return ChannelFactory<T>.CreateChannel(basicBinding, endpoint);
}
}
Yet upon debugging, I receive the common error of
The client and service bindings may be mismatched
There are no settings for bindings in any config files of either the client or service, to avoid conflicts with the programmatic settings.
Is there something I have missed, which is necessary when doing this programmatically? What is causing this mis-match?
You are hosting the service with a default BasicHttpBinding which means TransferMode Buffered and MessageEncoding Text.
In your client you are using Streamed and Mtom, respectively.
I have hosted wcf service in worker role on http port and i iopen that port onStart method as given bellow in code
public override bool OnStart()
{
try
{
ServicePointManager.DefaultConnectionLimit = 12;
CreateServiceHost();
return base.OnStart();
}
catch (Exception)
{
return true;
}
// Set the maximum number of concurrent connections
}
private ServiceHost serviceHost;
private void CreateServiceHost()
{
//serviceHost = new ServiceHost(typeof(Service));
//WebHttpBinding binding = new WebHttpBinding(WebHttpSecurityMode.None);
//RoleInstanceEndpoint externalEndPoint =
// RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["ServiceEP"];
//string endpoint = String.Format("http://{0}/Service",
// externalEndPoint.IPEndpoint);
//serviceHost.AddServiceEndpoint(typeof(IService), binding, endpoint);
//serviceHost.Open();
var endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["ServiceEP"];
var ub = new UriBuilder();
ub.Host = endpoint.IPEndpoint.Address.ToString();
ub.Port = endpoint.IPEndpoint.Port;
ub.Scheme = "http";
ub.Path = "Service";
var host = new ServiceHost(typeof(Service), ub.Uri);
host.AddDefaultEndpoints();
host.Description.Behaviors.Add(new ServiceMetadataBehavior() { HttpGetEnabled = true });
foreach (var e in host.Description.Endpoints)
{
((BasicHttpBinding)e.Binding).HostNameComparisonMode = HostNameComparisonMode.Exact;
}
host.Open();
//Trace.WriteLine("WCF Hello service running...");
}
when i try to access method defined in service i got bellow error
The remote server returned an error: (400) Bad Request.
In order to tell whether my project should migrate from .net remoting to WCF, I extracted its network communication part and implemented it by WCF. I run the remoting version and wcf version and eventually find remoting is faster than wcf by a factor of 1.5, which greatly differs from the msdn article.
Test configuration
WCF and .NET Remoting both use tcp channel without encryption, no app.config file. Compiled in release mode, no optimization.
Operations
What my program does is this.
You can download the two solutions here.
WCF test
Service Host
ServiceHost host = new ServiceHost(typeof(Server), new Uri(string.Format("net.tcp://{0}:{1}/{2}", args[0], args[1], args[2])));
var binding = new NetTcpBinding();
binding.MaxReceivedMessageSize = 614400;
binding.ReaderQuotas.MaxArrayLength = 512000;//a max picture of 500KB
binding.Security.Mode = SecurityMode.None;
host.AddServiceEndpoint(typeof(IServer), binding, string.Empty);
host.Open();
Server
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single
//, IncludeExceptionDetailInFaults = true
, ConcurrencyMode = ConcurrencyMode.Reentrant
)]
public class Server : IServer
{
public EntryRequirement GetEntryRequirement()
{
return new EntryRequirement(new[] { "fuck", "sex" }, false);
}
public void AddClient()
{
var client = OperationContext.Current.GetCallbackChannel<IServerCallback>();
var p = client.Profile;
var x = client.Password;
System.Diagnostics.Debug.WriteLine(p);
System.Diagnostics.Debug.WriteLine(x);
}
}
Client side
Player player = new Player();
player.Password = "12423";
player.Profile = new Contracts.PlayerProfile
{
Description = "I'm a man.",
HeadImage = imageData,
Name = "Loveright"
};
var binding = new NetTcpBinding();
binding.Security.Mode = SecurityMode.None;
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 20; i++)
{
ServerProxy server = new ServerProxy(player, binding,
new EndpointAddress(string.Format("net.tcp://{0}:{1}/{2}", args[0], args[1], args[2])));
server.GetEntryRequirement();
server.AddClient();
}
watch.Stop();
HeadImage is a picture of size 139KB.
Player class
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
class Player : IServerCallback
{
public PlayerProfile Profile { get; set; }
public string Password { get; set; }
public void ClientCollectionChangedEventHandler(object sender, ControllersChangedEventArgs e)
{
}
public void ClientUpdatedEventHandler(object sender, ClientUpdatedEventArgs e)
{
}
}
.NET Remoting test
Host
var serverProv = new BinaryServerFormatterSinkProvider();
serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
var clientProv = new BinaryClientFormatterSinkProvider();
IDictionary props = new Hashtable();
props["port"] = args[1];
props["name"] = "tcp server";
var channel = new TcpChannel(props, clientProv, serverProv);
ChannelServices.RegisterChannel(channel, false);
System.Runtime.Remoting.RemotingConfiguration.RegisterWellKnownServiceType(typeof(Server),
args[2], System.Runtime.Remoting.WellKnownObjectMode.Singleton);
Client
var serverProv = new BinaryServerFormatterSinkProvider();
serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
var clientProv = new BinaryClientFormatterSinkProvider();
IDictionary props = new Hashtable();
props["name"] = "tcp client " + Guid.NewGuid();
props["port"] = 0;
var channel = new TcpChannel(props, clientProv, serverProv);
ChannelServices.RegisterChannel(channel, false);
FileStream stream = new FileStream(#"logotz6.png", FileMode.Open);
byte[] imageData = new byte[stream.Length];
stream.Read(imageData, 0, imageData.Length);
stream.Close();
Player player = new Player();
player.Password = "12423";
player.Profile = new PlayerProfile
{
Description = "I'm a man.",
HeadImage = imageData,
Name = "Loveright"
};
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 20; i++)
{
var serverProxy = (IServer)Activator.GetObject(typeof(IServer), string.Format("tcp://{0}:{1}/{2}", args[0], args[1], args[2]));
serverProxy.GetEntryRequirement();
serverProxy.AddClient(player);
}
watch.Stop();
You can download the two solutions here.
Result
So do I make the test somewhere unfair to WCF?
Should it be the message encoding king ?
Have you used binaryMessageEncoding instead of textMessageEncoding or soapMessageEncoding ?
You can create a custom binding to do this :
internal sealed class MyBinding : CustomBinding
{
private static readonly BindingElementCollection elementCollection;
static MyBinding()
{
MessageEncodingBindingElement encoding = new BinaryMessageEncodingBindingElement();
TcpTransportBindingElement transport = new TcpTransportBindingElement();
elementCollection = new BindingElementCollection();
elementCollection.Add(encoding);
elementCollection.Add(transport);
}
internal MyBinding(string bindingName, string bindingNamespace)
: base()
{
base.Namespace = bindingNamespace;
base.Name = bindingName;
}
public override BindingElementCollection CreateBindingElements()
{
return elementCollection;
}
}
I have the following class that configures security, encoding, and token parameters but I am having trouble adding a BasicHttpBinding to specify a MaxReceivedMessageSize. Any insight would be appreciated.
public class MultiAuthenticationFactorBinding
{
public static Binding CreateMultiFactorAuthenticationBinding()
{
HttpsTransportBindingElement httpTransport = new HttpsTransportBindingElement();
CustomBinding binding = new CustomBinding();
binding.Name = "myCustomBinding";
TransportSecurityBindingElement messageSecurity = TransportSecurityBindingElement.CreateUserNameOverTransportBindingElement();
messageSecurity.AllowInsecureTransport = true;
messageSecurity.EnableUnsecuredResponse = true;
messageSecurity.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12;
messageSecurity.SecurityHeaderLayout = SecurityHeaderLayout.Strict;
messageSecurity.IncludeTimestamp = true;
messageSecurity.SetKeyDerivation(false);
TextMessageEncodingBindingElement Quota = new TextMessageEncodingBindingElement(MessageVersion.Soap11, System.Text.Encoding.UTF8);
Quota.ReaderQuotas.MaxDepth = 32;
Quota.ReaderQuotas.MaxStringContentLength = Int32.MaxValue;
Quota.ReaderQuotas.MaxArrayLength = 16384;
Quota.ReaderQuotas.MaxBytesPerRead = 4096;
Quota.ReaderQuotas.MaxNameTableCharCount = 16384;
X509SecurityTokenParameters clientX509SupportingTokenParameters = new X509SecurityTokenParameters();
clientX509SupportingTokenParameters.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient;
clientX509SupportingTokenParameters.RequireDerivedKeys = false;
messageSecurity.EndpointSupportingTokenParameters.Endorsing.Add(clientX509SupportingTokenParameters);
//binding.ReceiveTimeout = new TimeSpan(0,0,300);
binding.Elements.Add(Quota);
binding.Elements.Add(messageSecurity);
binding.Elements.Add(httpTransport);
return binding;
}
}
If you need to specify MaxReceivedMessageSize you can do it on your transport binding element - HttpsTransportBindingElement. You can't add binding to binding.
Just Found this to create a BasicHttpBinding
BasicHttpBinding Basicbinding = new BasicHttpBinding(BasicHttpSecurityMode.None);
Basicbinding.MaxReceivedMessageSize = 10000000;