I want to implement a one-way, fire-and-forget call from an ASP.NET application to a WCF service (hosted in a Windows Service). It's a long-running operation at the service-side (otherwise I would just do it inside the ASP.NET application) so the client (channel) should not remain open until the action completes.
However trivial a scenario this may seem, I've been searching for a graceful solution for hours and can't really find anything to my liking. There are a couple of SO questions and blog posts about it, and it seems there are two possible solutions:
- Use a message queue as communication layer, as suggested here.
- Use
OneWayBindingElement
, as suggested here.
I would rather not use Message Queues, installing these on the server environment is too much overhead.
That leaves adding OneWayBindingElement
. But all examples I found do this in code, which I would rather not do because that rules out using the Visual Studio WcfSvcHost. Is it possible to extend my netTcpBinding with this infamous OneWayBindingElement
through configuration ?
For completeness, here are the key parts in my code:
Service Interfce
[ServiceContract]
public interface ICalculationService
{
[OperationContract(IsOneWay = true)]
void StartTask(TaskType type);
[OperationContract(IsOneWay = true)]
void AbortTask(TaskType type);
}
Service Implementation
[ServiceBehavior(
ConcurrencyMode = ConcurrencyMode.Multiple,
InstanceContextMode = InstanceContextMode.PerCall)]
public class CalculationService : ICalculationService
{
// ...
public void StartTask(TaskType type)
{
// ...
}
}
Client code, inside controller
public class SourcesController
{
[HttpPost]
public ActionResult Upload(UploadFilesVM files)
{
// ...
using(var svcClient = GetSvcClientInstance())
{
svcClient.StartTask(TaskType.RefreshInspectionLotData);
svcClient.StartTask(TaskType.RefreshManugisticsData);
}
// ...
return RedirectToAction("Progress");
}
private CalculationServiceClient GetSvcClientInstance()
{
var client = new CalculationServiceClient();
client.Endpoint.Behaviors.Add(new SatBehavior(Context));
client.Open();
return client;
}
}
Service configuration
<services>
<service name="...CalculationService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/PLU0006B/"/>
<add baseAddress="net.tcp://localhost:8733/PLU0006B/"/>
</baseAddresses>
</host>
<endpoint
address="CalculationService"
binding="netTcpBinding"
bindingConfiguration="SatOneWayBinding"
contract="....ICalculationService" />
<endpoint
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"/>
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="SatOneWayBinding">
<!-- I'm hoping I can configure 'OneWayBindingElement' here ? -->
<security mode="None">
</security>
</binding>
</netTcpBinding>
</bindings>