I have an simple Pub/Sub service built on WCF. the interface of server side looks like below:
[ServiceBehavior(UseSynchronizationContext = false, InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class RDFService : IRDFService
{
public Guid Register(string ric)
public void Unregister(Guid guid)
}
Client side call back interface:
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
internal class ServiceCallback : IRDFCallBack
{
// [OperationContract(IsOneWay = true)]
public void UpdateSignal(Guid guid, string ric, MarketFeedData data, MarketDataMessageType type)
}
Client side is an Win form project.
The handling logic is as below:
If client receives an UpdateSignal request, withing the handling method, client will make an call to unregister it self.
Usually, both UpdateSignal and Unreg methods takes almost no time. But when an influx(8-10) of UpdateSignal requests are sent to client concurrently, there's a significant delay between 1-3 seconds. I opened trace and found that the time are held on the Unregister service method call:
As in the picture, there's an 2 seconds delay between activity 3 and 4. What can be the cause? Thanks.
Related
In a Request Response pattern using MassTransit with RabbitMQ, I'm trying to create a request client. But when doing some research on the internet i saw two possibilities:
CreateRequestClient and CreatePublishRequestClient
Does someone know what's the difference between those two and when to use them?
see below for the methods:
public static class RequestClientExtensions
{
public static IRequestClient<TRequest, TResponse> CreateRequestClient<TRequest, TResponse>(this IBus bus, Uri address, TimeSpan timeout, TimeSpan? ttl = null, Action<SendContext<TRequest>> callback = null) where TRequest : class where TResponse : class
{
return (IRequestClient<TRequest, TResponse>) new MessageRequestClient<TRequest, TResponse>(bus, address, timeout, ttl, callback);
}
public static IRequestClient<TRequest, TResponse> CreatePublishRequestClient<TRequest, TResponse>(this IBus bus, TimeSpan timeout, TimeSpan? ttl = null, Action<SendContext<TRequest>> callback = null) where TRequest : class where TResponse : class
{
return (IRequestClient<TRequest, TResponse>) new PublishRequestClient<TRequest, TResponse>(bus, timeout, ttl, callback);
}
}
Well, the set of arguments explain the difference. This is the same difference as we have between Send and Publish. Publish uses fan-out exchange and Send delivers to a specific exchange only.
Normal RequestClient will do Send under the hood and needs the receiver address.
PublishRequestClient does not need any address since it will just publish the message and hope that someone will reply to it.
If you want to know more about Send vs Publish difference, you can check this blog post.
Sorry to bother you guys again.
I am going to consume a WCF service on a server. The service was created by outside. If I look at it in the browser, it is fine. Please see the image below.
To consume it, I add service reference. with the url http://wsvc01/BOERPI/BOERPI.svc
Then I instantiate the proxy by the code.
BOERPI.PostPhoneCallResponse client = null;
client = new BOERPI.PostPhoneCallResponse();
double x = client.ActualCallCharge; // suppose to get a proper value but not
Some of the code of the service is:
[ServiceContract]
public interface iBOERPI
{
[OperationContract]
PostPhoneCallResponse PostPhoneCall(PostPhoneCallRequest objCDRRequest);
[DataContract]
public class PostPhoneCallResponse
{
[DataMember]
public double ActualCallCharge = -1.0;
I assume the service code is 100% right, is any thing wrong when I consume the service?
When I righted click the definition of PostPhoneCallResponse, it is:
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="PostPhoneCallResponse", Namespace="http://schemas.datacontract.org/2004/07/nsBOERPI")]
[System.SerializableAttribute()]
public partial class PostPhoneCallResponse : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged {
[System.NonSerializedAttribute()]
private System.Runtime.Serialization.ExtensionDataObject extensionDataField;
[System.Runtime.Serialization.OptionalFieldAttribute()]
private double ActualCallChargeField;
Thanks.
client = new BOERPI.PostPhoneCallResponse(); You are trying to use your DataContract here instead of Service client.
Check under Service References for your service name you used in your client application and
use it:
eg.
using(var client = new BingMapsGeocodeService()) // This should be your service client name
{
}
Update:
Sending and Received messages using request and response objects:
You need to create a request object as per your operation shows:
var request = new PostPhoneCallRequest(){ // populate all your properties you need to send to the service};
var client = new BOERPI.MyClient(); // Instantiate your client with the name you have given for your service client.
PostPhoneCallResponse response = client.PostPhoneCall(request); // You are sending your request and getting a response as PostPhoneCallResponse object
I have an ASP application which is client of WCF SERVICE1 , which is client of WCF SERVICE2.
I have added IDispatchMessageInspector and IClientMessageInspector to WCF SERVICE1.
Now I need to pass a custom value from ASP to WCF1 , then to WCF2.
from ASP to WCF1 it is trivial , via Message Headers.
The question is , how to pass a custom value from IDispatchMessageInspector.AfterReceiveRequest(request from ASP received by WCF1) to IClientMessageInspector.BeforeSendRequest(prepare to send request to WCF2) operation of WCF SERVICE 1 ?
Is there is some context which could be used ?
What does your code look like? Assuming that first Dispatch Message Inspector is the one making the request to WCF2, then simply using message properties would suffice.
However, if your dispatch message inspector does something; then the request continues processing and it is the service implementation that actually calls WCF2, then you'll need to jump through a few more hoops. In general, I'd say you'd need the inspector to put some data in the service request message properties that the service implementation would need to pick up and copy to the message to send to WCF2 so that the client inspector can pick them up.
That's ugly, and would kinda make the whole process more brittle.
Can you elaborate a bit more what you're trying to do? What kind of data are you hoping to pass around this way?
In my case, I had to identify and log nested service calls requested by client.
To do that, I stamp each service call by ThreadStatic property and add this property to the header of client call(service1 count as client for service2) than in AfterReceiveRequest method I have checked its existance. If exists,current method was requested by parent service.
public class GenericMessageInspector : IDispatchMessageInspector, IClientMessageInspector
{
[ThreadStatic]
private static string _masterServiceGUID;
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
if (request.Headers.Action == null)
return null;
//Control request header for nested call
string masterRequestId = string.Empty;
var IsMasterExist = request.Headers.FindHeader("MasterServiceGUID", "namespace");
if (IsMasterExist > -1)
{
//requested by internal service
masterRequestId = request.Headers.GetReaderAtHeader(IsMasterExist).ReadInnerXml();
}
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
if (!String.IsNullOrEmpty(_masterServiceGUID))
{
request.Headers.Add(MessageHeader.CreateHeader("MasterServiceGUID", "namespace", _masterServiceGUID));
}
return null;
}
}
}
We've got the following WCF Service Contracts:
[ServiceContract(Namespace = "http://example.com", Name = "Service1")]
public interface IService1
{
[OperationContract]
[FaultContract(typeof(Fault1))]
ValidateUserResult ValidateUser(
string username,
string password);
}
[ServiceContract(Namespace = "http://example.com", Name = "Service1")]
public interface IService1Async
{
[OperationContract(AsyncPattern = true)]
[FaultContract(typeof(Fault1))]
IAsyncResult BeginValidateUser(
string username,
string password,
AsyncCallback callback,
object userState);
ValidateUserResult EndValidateUser(IAsyncResult asyncResult);
}
[DataContract(Namespace = "http://example.com")]
public class Fault1
{
}
We are calling the async version of ValidateUser in the client side and we are throwing a FaultException<Fault1> on the server, but all the client receives is the base FaultException.
What can be the reason the contractually-specified fault is not being received?
We found now why. We are generating the fault from a Service Behaviour using the ProvideFault method. There we use code similar to the example at IErrorHandler.ProvideFault in msdn
The only difference was that we weren't passing the right action on the Message.CreateMessage overload. We copied exactly what gets generated in the case that we manually throw the fault and voila.
My excuses for not giving that last detail :-)
Can you show us the catch statements for your call? The contract and everything looks fine to me...
In which order do you check for faults?? You would have to check for FaultException<Fault1> before checking for FaultException or CommunicationException - any chance you might have that order mixed up somehow?
Does it work when you call the sync version of the method?
How can I implement one way WCF operations?
I just tried using IsOneWay attribute as:
[OperationContract(IsOneWay=true)]
void MethodName(string param1, int param2)
Is there any other change I need to make or any specific change in app.config?
FYI, my WCF service implements netTcpBinding, though I think that shouldn't make any difference.
As shown, your code looks ok. There should be no problem with doing one-way calls with netTcpBinding.
If you're interested, chapter 5 in Juval Lowy's awesome Programming WCF Services 2nd Edition contains a good bit of information about one-way services.
From what you've shown, so far though I don't see anything wrong. Please give us some more details.
We had a problem with one-way calls not returning immediately using the NetTcpBinding. This blog post identifies the problem and provides a solution.
http://blogs.msdn.com/b/distributedservices/archive/2009/02/12/client-proxy-close-method-call-does-not-finish-immediately-in-one-way-wcf-calls.aspx
From the article:
Problem: Clients calling a one-way method in WCF Service and then close method on proxy does not return until the call is actually finished or call times out. Ever wonder why this happens?
Cause: When you specify “One-Way” on your interface, the underlying channel operation is still two-way since the one way binding element is not in the channel stack. Thus, the close operation gets blocked until the one way operation completes.
This is by design and the development team is working to change it in future versions of .Net framework.
...
Solution (Work around):
Layer the OneWayBindingElement on top of netTcpBinding as shown in the below code. This way, close call on proxy will return immediately and eventually the one-way call will return in fire and forget fashion.
[ServiceContract]
public interface IService1
{
[OperationContract(IsOneWay = true)]
void SetData(int value);
}
public class Service1 : IService1
{
public void SetData(int value)
{
//Application specific code
}
}
Service Host code:
Form1ServiceHost = new ServiceHost(this, new Uri("net.tcp://localhost:8091/WindowsFormApp/Form1/"), new Uri("http://localhost:8090/WindowsFormApp/Form1/"));
Binding binding = new NetTcpBinding();
BindingElementCollection oldBindingElements = binding.CreateBindingElements();
BindingElementCollection bindingElements = new BindingElementCollection();
bindingElements.Add(new OneWayBindingElement());
foreach (BindingElement bindingElement in oldBindingElements)
{
bindingElements.Add(bindingElement);
}
binding = new CustomBinding(bindingElements);
Form1ServiceHost.AddServiceEndpoint("WCFServiceLibrary.IService1", binding, "");
Form1ServiceHost.Open();
Client Code:
Binding binding = new NetTcpBinding();
BindingElementCollection oldBindingElements = binding.CreateBindingElements();
BindingElementCollection bindingElements = new BindingElementCollection();
bindingElements.Add(new OneWayBindingElement());
foreach (BindingElement bindingElement in oldBindingElements)
{
bindingElements.Add(bindingElement);
}
binding = new CustomBinding(bindingElements);
Service1Client client = new Service1Client(binding, new EndpointAddress("net.tcp://localhost:8091/WindowsFormApp/Form1/"));
client.SetData(10);
Console.WriteLine("set data");
Console.WriteLine("Now closing the channel,Before close, current time is {0}", DateTime.Now.ToString() + " " + DateTime.Now.Millisecond.ToString());
client.Close();
Console.WriteLine("Now closing the channel,After close, current time is {0}", DateTime.Now.ToString() + " " + DateTime.Now.Millisecond.ToString());`