MSMQ WCF Throttling - wcf

I have a windows service that reads my message queue through WCF. I want the service to process one message before another message (intensive memory actions per msg). I set the throttling configuration to 1, but it does not seem to do anything. If i have 6 messages in my queue, it takes 4 right after the start.
Am i missing something?
My web.config :
<system.serviceModel>
<client>
<endpoint
address="net.tcp://spserv30:9999/services/SPInterface"
binding="netTcpBinding" bindingConfiguration="tcpspbinding"
contract="Itineris.OPM.WCFSP.ActionContracts.ISPActions" >
</endpoint>
</client>
<services>
<service name="Itineris.OPM.MSMQProcessorV2.MSMQProcessor" behaviorConfiguration="Throttled" >
<endpoint address="msmq.formatname:DIRECT=OS:localhost\private$\documents" binding="msmqIntegrationBinding"
bindingConfiguration="MSMQProcessorBinding" contract="Itineris.OPM.MSMQProcessorV2.IMSMQProcessor" />
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="tcpspbinding" transferMode="StreamedRequest" />
</netTcpBinding>
<msmqIntegrationBinding>
<binding name="MSMQProcessorBinding" maxReceivedMessageSize="2147483647"
receiveRetryCount="0" retryCycleDelay="00:10:00" maxRetryCycles="0"
receiveErrorHandling="Move">
<security mode="None" />
</binding>
</msmqIntegrationBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="Throttled">
<serviceThrottling
maxConcurrentCalls="1"
maxConcurrentSessions="1"
maxConcurrentInstances="1"
/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
My servicehost creation :
protected override void OnStart(string[] args)
{
if (_serviceHost != null)
{
if (_serviceHost.State != CommunicationState.Faulted)
_serviceHost.Close();
else
_serviceHost.Abort();
}
//create servicehost
_serviceHost = new ServiceHost(typeof(MSMQProcessor));
_serviceHost.Open();
_serviceHost.Faulted += serviceHost_Faulted;
// Already load configuration here so that service does not start if there is a configuration error.
new DocumentGeneratorV2.LoadGeneratorConfigurator().Load();
var startLog = new LogEntry {Message = "Itineris MSMQ Processor Service V2 has started"};
startLog.Categories.Add(CategoryGeneral);
startLog.Priority = PriorityNormal;
Logger.Write(startLog);
}
private void serviceHost_Faulted(object sender, EventArgs e)
{
if (!_isClosing)
{
_serviceHost.Abort();
_serviceHost = new ServiceHost(typeof(MSMQProcessor));
_serviceHost.Faulted += serviceHost_Faulted;
_serviceHost.Open();
}
}
Class with contract :
[ServiceContract(Namespace = "http://Itineris.DocxGenerator.MSMQProcessor")]
[ServiceKnownType(typeof(string))]
public interface IMSMQProcessor
{
[OperationContract(IsOneWay = true, Action = "*")]
void GenerateWordDocument(MsmqMessage<string> message);
}
public class MSMQProcessor : IMSMQProcessor
{
/// <summary>
/// Method that processed the message and generates a word document
/// </summary>
/// <param name="message">message from MSMQ to be processed</param>
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void GenerateWordDocument(MsmqMessage<string> message)
{
DocumentGeneration documentGenerator = null;
var state = new DocumentStatus();
var docGenerator = new DocumentGenerator(new LoadGeneratorConfigurator().Load());
var deserializer = new XmlSerializer(typeof(DocumentGeneration));
documentGenerator = deserializer.Deserialize(new StringReader(message.Body)) as DocumentGeneration;
if(documentGenerator == null)
throw new Exception("Deserializing of the message has failed");
docGenerator.MailQueue = appSettings["MAILQUEUE"];
docGenerator.GenerateDocument(documentGenerator);
var builder = new StringBuilder();
builder.Append("The documents have been saved to the following locations: \r\n");
}
}

Your service as configured in the question should only process message at a time. Although you are not using the ServiceBehavior attribute for the service implementation class, the default value for the ConcurrencyMode is Single not Multiple (which could cause the behavior you are seeing). The default value of InstanceContextMode is Per Session but the maxConcurrentInstances and maxConcurrentSessions values force support for a single session at a time.
The only other option that I see is to force the ServiceHost to use only one service instance by using a different constructor. Here is the code:
// ... snipped ...
//force single service instance to be used by servicehost
var singleton = new MSMQProcessor();
_serviceHost = new ServiceHost(singleton);
_serviceHost.Open();
// ... snipped ...

Related

WCFCore and serviceAuthorizationManager not working

I'm trying to assemble a .Net 6 WCF Service with WCFCore, using a basicHttpBinding, and I'm strugling to add a service authorization manager.
My purpose is to enable WCF to read and validate bearer tokens and use OAuth. I can't move to REST because of legacy applications compatibility, so I need to keep WCF but use bearer tokens.
My service at this stage is quite simple:
[ServiceContract]
public interface IService
{
[OperationContract]
string GetData(int value);
[OperationContract]
CompositeType GetDataUsingDataContract(CompositeType composite);
}
public class Service : IService
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
}
// Use a data contract as illustrated in the sample below to add composite types to service operations.
[DataContract]
public class CompositeType
{
bool boolValue = true;
string stringValue = "Hello ";
[DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
My Program.cs:
var builder = WebApplication.CreateBuilder();
builder.Services.AddServiceModelServices();
builder.Services.AddServiceModelConfigurationManagerFile("wcf.config");
builder.Services.AddServiceModelMetadata();
builder.Services.AddSingleton<IServiceBehavior, UseRequestHeadersForMetadataAddressBehavior>();
builder.Services.AddSingleton<OAuthAuthorizationManager>();
var app = builder.Build();
app.UseServiceModel(bld =>
{
bld.AddServiceEndpoint<Service, IService>(new BasicHttpBinding(BasicHttpSecurityMode.Transport), "/Service.svc");
var mb = app.Services.GetRequiredService<ServiceMetadataBehavior>();
mb.HttpsGetEnabled = true;
});
app.Run();
Then my wcf.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicBinding" receiveTimeout="00:10:00">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="CoreWCFService.Service" behaviorConfiguration="Default">
<endpoint address="basic" binding="basicHttpBinding" bindingConfiguration="basicBinding" contract="CoreWCFService.IService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Default">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true" />
<serviceAuthorization serviceAuthorizationManagerType="CoreWCFService.OAuthAuthorizationManager,CoreWCFService" />
<dataContractSerializer maxItemsInObjectGraph="10000000" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
But when I call the service with tokens, nothing happens on the authorization manager, the operation runs simply ignoring this service behavior.
Is there anyone out there that can help me with this?
You may refer to the Corewcf project template. There are a few things to note:
The interface and its implementation need to be separated to facilitate subsequent maintenance and invocation of the interface.
We need to look at the UseServiceModel part in Program.cs.

how to find the service address in WCF client

I created a WCF service and client in same machine, the services address is wrote into Client's code, so I can easily find the service and create connection to service.
Then I try to deploy them into Intranet. The first problem is: how could Client find the address of server. In actual environment, customers can install service at any computer in Intranet, is there any way to let client find the server address?
WCF service could expose a specific endpoint as a discovery endpoint to all clients so that client could find where the service lies. You could even use UDP multicast to enable the service to be discovered by the client.
You could check the official document.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/wcf-discovery
I have made a demo, wish it is useful to you.
Server.
class Program
{
static void Main(string[] args)
{
using (ServiceHost sh=new ServiceHost(typeof(MyService)))
{
sh.Open();
Console.WriteLine("serivce is ready...");
Console.ReadLine();
sh.Close();
}
}
}
[ServiceContract]
public interface IService
{
[OperationContract]
string SayHello();
}
public class MyService : IService
{
public string SayHello()
{
return "Hello, I am a Clown";
}
}
Server app.config
<system.serviceModel>
<services>
<service name="DiscoveryEndpoint20181024.MyService" behaviorConfiguration="mybehavior">
<endpoint address="http://10.157.18.188:4800" binding="wsHttpBinding" contract="DiscoveryEndpoint20181024.IService"></endpoint>
<endpoint kind="discoveryEndpoint" address="http://localhost:9999" binding="wsHttpBinding"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="mybehavior">
<serviceMetadata />
<serviceDiscovery />
</behavior>
</serviceBehaviors>
</behaviors>
Client.
class Program
{
static void Main(string[] args)
{
DiscoveryClient client = new DiscoveryClient("my_client");
client.ClientCredentials.Windows.ClientCredential.UserName = "administrator";
client.ClientCredentials.Windows.ClientCredential.Password = "abcd1234!";
FindCriteria crit = new FindCriteria(typeof(IService));
FindResponse resp = client.Find(crit);
if (resp != null && resp.Endpoints.Count > 0)
{
EndpointDiscoveryMetadata epaddrMtd = resp.Endpoints[0];
ChannelFactory<IService> factory = new ChannelFactory<IService>(new WSHttpBinding(), epaddrMtd.Address);
factory.Credentials.Windows.ClientCredential.UserName = "administrator";
factory.Credentials.Windows.ClientCredential.Password = "abcd1234!";
IService service = factory.CreateChannel();
var result=service.SayHello();
Console.WriteLine(result);
Console.ReadLine();
}
}
}
[ServiceContract]
public interface IService
{
[OperationContract]
string SayHello();
}
class DemoService : IService
{
public string SayHello()
{
OperationContext context = OperationContext.Current;
return $"the address:{OperationContext.Current.Channel.LocalAddress.Uri}";
}
}
Client.config
<system.serviceModel>
<client>
<endpoint name="my_client" kind="discoveryEndpoint" address="http://10.157.18.188:9999" binding="wsHttpBinding"></endpoint>
</client>
</system.serviceModel>

Current thread works even service time out?

I have created a wcf service in order to test wcf time outs. my problem is even time out has expired its still works.
In this service i have created long running method and in there i create log file,then i let to service time out.but even service time out has expired still log file appending data till to the long running method finish execution.?
How this happen? are there is a way to stop that ?
service timeout is 1 min
long running method duration is :10 mins
This service hosted in IIS 7.5 using WAS
here is the my service implementation class
public class LongRunner : ILongRunner
{
public void LongRunnerMethod()
{
int counter = int.Parse(ConfigurationManager.AppSettings["val"]);
string text = string.Empty;
for (int i = 0; true; i++)
{
Thread.Sleep(1000);
if (i >= counter)
break;
text = string.Concat(i.ToString(), DateTime.Now.ToString());
File.AppendAllText(#"C:\Looger\log.txt", text);
}
}
}
Here is the my service interface
[ServiceContract]
public interface ILongRunner
{
[OperationContract]
void LongRunnerMethod();
}
Finally here is the web config
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="val" value="600"/>
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service behaviorConfiguration="ORServiceBehavior" name="PTS.LongRunner">
<endpoint binding="netTcpBinding" bindingConfiguration="DefaultNetTcpBinding" name="ORServiceTCPEndPoint"
contract="PTS.ILongRunner" address="" >
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexTcpBinding" bindingConfiguration="" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8079/___/_________.svc" />
</baseAddresses>
</host>
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="DefaultNetTcpBinding" maxBufferSize="2147483647" maxConnections="10" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647" >
<reliableSession enabled="false" ordered="false" inactivityTimeout="00:10:00"/>
<readerQuotas maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxDepth="32" maxNameTableCharCount="2147483647" maxStringContentLength="2147483647"/>
<security mode="Message">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="ORServiceBehavior">
<serviceMetadata httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="false" />
<serviceThrottling maxConcurrentCalls="200" maxConcurrentSessions="200" maxConcurrentInstances="200" />
<dataContractSerializer maxItemsInObjectGraph="50000" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
WCF has many timeouts...
binding timeouts: SendTimeout, OpenTimeout and CloseTimeout (default 1 minute), ReceiveTimeout (default 10 minutes)
service host: OpenTimeout (default 1 minute), CloseTimeout (default 10 seconds)
reliable session inactivity timeout: default 10 minutes
anything that inherits ConnectionOrientedTransportBindingElement e.g. NetTcp: ChannelInitializationTimeout default 30 seconds
My guess is that you have gotten "Unhandled Exception: System.TimeoutException: The open operation did not complete within the allotted timeout of ...." - this means that proxy has timed out waiting for service to send a response.
"how this happens? [that service keep logging even if you have a "operation did not complete" timeout]"
ServiceHost has allocated a thread to process the request made to the LongRunnerMethod method. This thread will finish processing the request until something catastrophic (e.g. process host shutdown) or exception is raised from inside a method.
"is there a way to stop that [interrupt the thread processing the method call]?"
You would need to get the signal from external source that you need to check on every n-th iteration to see if you should continue. You would need to pass something from the client in a form of unique id (ticket) to the first method then use this id with a Cancel method that will set the signal for the LongRunnerMethod to abort processing.
Here is an example using msmq which allows true one-way call:
SERVER
class Program
{
static void Main(string[] args)
{
var baseAddress = "net.msmq://localhost/private/";
var address = "ILongRunner";
var host = new ServiceHost(typeof (LongRunner), new Uri(baseAddress));
var binding = new NetMsmqBinding(NetMsmqSecurityMode.None);
var se = host.AddServiceEndpoint(typeof (ILongRunner), binding, address );
se.VerifyQueue(); //comes from IDesign ServiceModelEx http://www.idesign.net/Downloads/GetDownload/1887
host.Open();
Console.WriteLine("Press any key to stop");
Console.ReadLine();
}
}
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall)]
public class LongRunner : ILongRunner
{
private static readonly ConcurrentBag<Guid> Cancelations = new ConcurrentBag<Guid>();
public void CancelLongRunnerMethod(Guid id)
{
if (Cancelations.All(z => z != id))
Cancelations.Add(id);
}
public void LongRunnerMethod(Guid id)
{
int counter = 300000;
//concurrent write will require different technique
var file = string.Format(#"D:\log.{0}.txt", id);
for (int i = 0; true; i++)
{
//check every 5th call
if (i % 5 == 0)
{
if (Cancelations.Any(z => z == id))
{
Guid cancelationId;
Cancelations.TryTake(out cancelationId);
if (cancelationId == id)
{
Debug.WriteLine(string.Format("LongRunnerMethod {0} canceled", id));
return;
}
}
}
Thread.Sleep(10);
Console.WriteLine("at " + i);
if (i >= counter)
break;
var text = string.Format("{0} {1} \n", i.ToString(), DateTime.Now.ToString());
File.AppendAllText(file, text);
}
Console.WriteLine("Complete " + id);
}
}
[ServiceContract()]
public interface ILongRunner
{
[OperationContract(IsOneWay = true)]
void CancelLongRunnerMethod(Guid id);
[OperationContract(IsOneWay = true)]
void LongRunnerMethod(Guid id);
}
CLIENT
class Program
{
static void Main(string[] args)
{
var baseAddress = "net.msmq://localhost/private/";
var address = "ILongRunner";
var binding = new NetMsmqBinding(NetMsmqSecurityMode.None);
var c1 = new ChannelFactory<ILongRunner>(binding, new EndpointAddress(new Uri(baseAddress + address)));
var proxy = c1.CreateChannel();
var request1 = Guid.NewGuid();
proxy.LongRunnerMethod(request1);
var co = c1 as ICommunicationObject;
co.Close();
var c2 = ChannelFactory<ILongRunner>.CreateChannel(binding, new EndpointAddress(new Uri(baseAddress + address)));
var request2 = Guid.NewGuid();
c2.LongRunnerMethod(request2);
Thread.Sleep(5000);
var c3 = new ChannelFactory<ILongRunner>(binding, new EndpointAddress(new Uri(baseAddress + address)));
var proxy2 = c3.CreateChannel();
proxy2.CancelLongRunnerMethod(request1);
var co2 = c3 as ICommunicationObject;
co2.Close();
}
}

How to set up WorkflowService authentication?

I just need to secure my WF services. Can't find any resources on this. How to do it?
Already tried:
class Program
{
static void Main(string[] args)
{
using (WorkflowServiceHost host = new WorkflowServiceHost(new Workflow1(), new Uri("http://localhost/Test")))
{
host.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = System.ServiceModel.Security.UserNamePasswordValidationMode.Custom;
host.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new Test();
host.Open();
Console.Write("ready");
Console.ReadLine();
}
}
}
public class Test : UserNamePasswordValidator
{
public Test()
{
Console.Write("hit");
}
public override void Validate(string userName, string password)
{
Console.Write("never hit");
}
}
And a config
<bindings>
<wsHttpBinding>
<binding>
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<!--<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="myAssembly.Test, myAssembly" />
</serviceCredentials>-->
</behavior>
</serviceBehaviors>
Can't create a fixed name endpoint because they are dynamically created
UPDATE - I tried the configuration bellow and worked, but I want a more granular way to set what binding each service use
<protocolMapping>
<add scheme="http" binding="wsHttpBinding"/>
</protocolMapping>
We have an episode of Workflow TV that should help. Workflow TV - Workflow Services Security
As far as the messaging part this is just WCF so anything you can do with WCF should work here.
That said with workflow you typically need more fine grained control on all but the first request. For example all employees can start en expense report but only the employee who started a specific expense report can add expenses to it and submit it. You can do these kind of security checks using the WF Security Pack.
A little hackish, but works. Overrided WorkflowServiceHost in order to grab unknown contract names and added service endpoints for each one.
const string DEFAULT_WORKFLOW_SERVICE_BINDING_NAME = "WorkflowDefaultBinding";
static void Main(string[] args)
{
MyWorkflowServiceHost host = new MyWorkflowServiceHost(new CountingWorkflow2(), new Uri(hostBaseAddress));
foreach (var contractName in host.ImplementedContractsNames)
{
// now I'm able to choose which binding to use depending on a condition
var binding = new WSHttpBinding(DEFAULT_WORKFLOW_SERVICE_BINDING_NAME);
host.AddServiceEndpoint(contractName, binding, string.Empty);
}
}
And MyWorkflowServiceHost
public class MyWorkflowServiceHost : WorkflowServiceHost
{
public MyWorkflowServiceHost(Activity activity, params Uri[] baseAddresses)
: base(activity, baseAddresses)
{
}
private IDictionary<string, System.ServiceModel.Description.ContractDescription> _implementedContracts;
public IEnumerable<string> ImplementedContractsNames
{
get
{
foreach (var contract in _implementedContracts)
yield return contract.Key;
}
}
protected override System.ServiceModel.Description.ServiceDescription CreateDescription(out System.Collections.Generic.IDictionary<string, System.ServiceModel.Description.ContractDescription> implementedContracts)
{
System.ServiceModel.Description.ServiceDescription description = base.CreateDescription(out implementedContracts);
_implementedContracts = implementedContracts;
return description;
}
}
Adding a unamed WSHttpBinding and the following section on service model should work too, but for default configuration
<protocolMapping>
<add scheme="http" binding="wsHttpBinding"/>
</protocolMapping>

WCF net.tcp only service giving TargetInvocationException/ServiceModel.CommunicationException

I'm writing a WCF (net.tcp) file transfer service which will eventually split files into several pieces and transfer said pieces to the client from the server/service. Currently the client and server are console apps.
While writing this service, I have at various times gotten the following exception;
System.ServiceModel.CommunicationException: The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '01:59:59.4220000'.
Actually, it starts as a Unhandled Exception: System.Reflection.TargetInvocationException: An exception occurred during the operation, making the result invalid. Check InnerException for exception details. ---> then the CommunicationException text above is right here.
In typical Microsoft fashion, that exception message is beyond unhelpful, so I'm finally calling out to the community to see if I can tackle this issue.
Also, in case this is important, the client is calling two of the service's methods Asynchronously ( InitGetFilePart() and GetFilePart() ). According to my logs, the first call to InitGetFilePartAsync(1, 1) gets handled all the way to the end; meaning that it's 'Completed' handler is called, which in turn calls vcClient.GetFilePartAsync(FileXferCargo, 1), and it's handler then spawns a BackgroundWorker thread (workers[chunkNum].
RunWorkerAsync(cargoHolder[chunkNum] where chunkNum=1) which itself completes. This is right about the time I get the TargetInvocationException mentioned above.
In the past I have made various tweaks (sadly, I can't remember what exactly) to the App.config to make this exception go away, but now nothing I do seems to make any difference and I just do NOT understand why this keeps happening.
I have read other advice on this matter, including "You have to catch the exception on the client, Abort current proxy and create and open new one." Well, I tried that but it doesn't appear I am able to catch this exception.
I also read that it could be due to sending too much data over the wire, but when I try to send my little 4k test file, I get the same exception. During my investigations, I also read that I can call 1 WCF service function/method, many times using the *Async() calls with the UserState parameter, which I am doing.
I will admit to being a relitive n00b when it comes to WCF, but I'm pretty sure I have my config files set correctly for what I'm trying to do.
Here are the client and server app.config files, the service interface definition and the top of the service's implementation class.
Client's App.config:
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="MyTcpBinding_IFileXferService"
receiveTimeout="02:00:00"
sendTimeout="02:00:00"
transferMode="Streamed"
maxBufferSize="65536"
maxReceivedMessageSize="2147483647">
<readerQuotas maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="65536" />
<security mode="Transport">
<transport clientCredentialType="None">
<extendedProtectionPolicy policyEnforcement="Never" />
</transport>
</security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="ClientConfigBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
<clientCredentials>
<serviceCertificate>
<authentication certificateValidationMode="None" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint name="ClientConfig"
behaviorConfiguration="ClientConfigBehavior"
binding="netTcpBinding"
bindingConfiguration="MyTcpBinding_IFileXferService"
contract="ServiceRefs.IFileXferService" />
</client>
</system.serviceModel>
Server's App.config:
<bindings>
<netTcpBinding>
<!-- Under <netTcpBinding> setting the listenBacklog,
maxConnections, and maxBuffer* values high -->
<binding name="MyTcpBinding_IFileXferService"
receiveTimeout="02:00:00"
sendTimeout="02:00:00"
openTimeout="00:01:00"
transferMode="Streamed"
portSharingEnabled="true"
listenBacklog="32"
maxConnections="64"
maxBufferSize="65536"
maxReceivedMessageSize="2147483646">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</netTcpBinding>
</bindings>
<services>
<service name="MediaServer.LNMediaServerSvc"
behaviorConfiguration="ServerConfigBehavior">
<host>
<baseAddresses>
<add baseAddress="net.tcp://lngsead148191a:9000/fileXferSvc"/>
</baseAddresses>
</host>
<endpoint name="mainEndPoint"
binding="netTcpBinding"
bindingConfiguration="MyTcpBinding_IFileXferService"
contract="ServiceInterfaces.IFileXferService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServerConfigBehavior">
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceThrottling maxConcurrentCalls="64" />
<dataContractSerializer maxItemsInObjectGraph="2147483646" />
<serviceCredentials>
<serviceCertificate findValue="tp_value"
x509FindType="FindByThumbprint" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
The Service interface is defined as follows;
[DataContract(IsReference = true)]
public class FileData
{
private long m_startPos;
[DataMember]
public long StartPosition
{
get { return m_startPos; }
set { m_startPos = value; }
}
private long m_endPos;
[DataMember]
public long EndPosition
{
get { return m_endPos; }
set { m_endPos = value; }
}
private byte m_chunkNumber;
[DataMember]
public byte ChunkNumber
{
get { return m_chunkNumber; }
set { m_chunkNumber = value; }
}
private long m_chunkSize;
[DataMember]
public long ChunkSize
{
get { return m_chunkSize; }
set { m_chunkSize = value; }
}
private string md5Hash;
[DataMember]
public string MD5Hash
{
get { return md5Hash; }
set { md5Hash = value; }
}
private string m_destFileSpec;
[DataMember]
public string DestinationFileSpec
{
get { return m_destFileSpec; }
set { m_destFileSpec = value; }
}
private string m_srcFileSpec;
[DataMember]
public string SourceFileSpec
{
get { return m_srcFileSpec; }
set { m_srcFileSpec = value; }
}
private Stream m_sourceStream;
[DataMember]
public Stream SourceStream
{
get { return m_sourceStream; }
set { m_sourceStream = value; }
}
private UInt32 m_JobNo;
[DataMember]
public UInt32 JobNumber
{
get { return m_JobNo; }
set { m_JobNo = value; }
}
private UInt32 m_fileNumber;
[DataMember]
public UInt32 FileNumber
{
get { return m_fileNumber; }
set { m_fileNumber = value; }
}
private long m_fileSize;
[DataMember]
public long FileSize
{
get { return m_fileSize; }
set { m_fileSize = value; }
}
}
[DataContract]
public partial class FileXferCargo
{
private FileData m_fileData;
[DataMember]
public FileData FileData
{
get { return m_fileData; }
set { m_fileData = value; }
}
private bool m_cancelled;
[DataMember]
public bool Cancelled
{
get { return m_cancelled; }
set { m_cancelled = value; }
}
private long m_errorCode;
[DataMember]
public long ErrorCode
{
get { return m_errorCode; }
set { m_errorCode = value; }
}
private Exception m_exceptionObj;
[DataMember]
public Exception Exception
{
get { return m_exceptionObj; }
set { m_exceptionObj = value; }
}
}
[ServiceContract]
public interface IFileXferService
{
[OperationContract]
bool InitFileRequest(ref FileXferCargo fileRequest);
[OperationContract]
bool InitGetFilePart(ref FileXferCargo fileCargo);
[OperationContract]
Stream GetFilePart(FileXferCargo fileCargo);
[OperationContract]
int CloseFile(FileData fileData);
}
The Service implementation class is defined as follows;
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Multiple,
UseSynchronizationContext = false)
]
public class LNMediaServerSvc : IFileXferService
{
...
}
For your netTcpBinding, set the security mode to none, on both the client and the server configuration files:
<security mode="None" />
this is a quick fix.
If you need to have security enable for netTcpBinding then you have to implement delegation and impersonation.
read more here: http://msdn.microsoft.com/en-us/library/ms730088.aspx
From what I have read and googled this is an issue of multi-hop impersonation. Impersonation can carry over to one hop only. By setting the security mode to none you prevent the authentication step when calling the WCF service.
Don't have a comment button anymore so I'll put this here. Yes, I have turned on tracing, but it seems like I'm going to need to read a BOOK to understand all the stuff the trace data is trying to tell me. That said, I looked over the trace info and the one thing I couldn't see was anything leading up to the socket being aborted. Just seems to happen for no reason. :(
For me it was because of not having net.tcp binding in web.config in the server which hosted the WCF. When I added the same binding for the service I did not get the exception. So you need to have the binding in both sides in Web and WCF if they are hosted in different servers.