I have developed a WCF Self hosted service using .Net Framework 4.0.
[ServiceContract(SessionMode=SessionMode.Required)]
[ServiceKnownType(typeof(XmlDocument))]
public interface IMyMSMQ
{
[OperationContract(IsOneWay=true, Action="*")]
void OnMessageReceived(MsmqMessage<XmlDocument> msg);
}
My Class implementation of this interface looks like this.
public class MyMSMQ : IMyMSMQ, IErrorHandler
{
public void OnMessageReceived(MsmqMessage<XmlDocument> msg)
{
// Log Message To appropriate destination
Logger.LogMessage(msg);
}
}
I have tried multiple scenarios.
Scenario 1:
Launch service.
Launch Client app.
Send Message to queue using Client App
Notice that the Queue does not appear to get populated with the message because the service already read the message.
Notice that nothing else happens in the service.
Send one more message
Notice that message stays in the queue
Scenario # 2: This is similar to Scenario 1 but starting the apps were in different order
Launch Client app.
Send Message to queue using Client App
Notice that the Queue does appear to get populated with the message because the service is not started and has not read the message.
Launch service.
Notice that the message disappears.
Notice that nothing else happens in the service.
Send one more message
Notice that message stays in the queue
Every time the service starts, a message is removed from the queue so, it appears that my service IS in fact reading the message but it is not able to figure out where to send it or what to do with it once it reads the message.
I found out that the code in the WCF Library was not the problem. It was how I was defining the endpoint binding.
MsmqIntegrationBinding binding = new MsmqIntegrationBinding(MsmqIntegrationSecurityMode.None);
binding.ReceiveTimeout = new TimeSpan(0, 1, 0); // set timeout to 1 minute.
binding.ReceiveErrorHandling = ReceiveErrorHandling.Fault;
this.AddServiceEndpoint(typeof(eRxMsmqWCF.IeRxMSMQ), binding, GetMQUri());
It needed to have the MsmqIntegrationBinding (which requires you to include the following using statement: using System.ServiceModel.MsmqIntegration;.
Sometimes I rely on intellisense too much. The MsmqIntegrationBinding is not present under the standard System.ServiceModel where the other bindings are located. So I used the NetMsmqBinding instead.
Related
How do I get the source address in a message received?
The context is that I'm designing a monitor for a service bus implemented with Rebus. I use the publish - subscribe pattern thus a message is always published on a topic. The monitor subscribes to all topics in order to supervise that a service has send something and so is alive and healthy. Though in a message handler the received message don't contain any source address or information identifying the service publishing. This means it's not possible to supervise which services are alive and healthy. Of course I can create an attribute "Service" identifying the service publishing in all messages. This implies that each service have to set the attribute before publishing a message, which I find a bit cumbersome. The source address is there and can identify the service publishing.
When you're in a Rebus message handler, you can access the IMessageContext - either by having it injected by your IoC container (which is the preferrent way, because of the improved testability), or by accessing the static MessageContext.Current property.
The message context gives you access to a couple of things, where the headers of the incoming transport message can be used to get the return address of the message (which, by default, is set to the sender's input queue).
Something like this should do the trick:
public class SomeHandler : IHandleMessages<SomeMessage>
{
readonly IMessageContext _messageContext;
public class SomeHandler(IMessageContext messageContext)
{
_messageContext = messageContext;
}
public async Task Handle(SomeMessage message)
{
var headers = _messageContext.TransportMessage.Headers;
var returnAddress = headers[Headers.ReturnAddress];
// .. have fun with return address here
}
}
I am new to WCF and windows services.
I have wcf service that is called from a class library. I am using that library in Windows service(WS) and this WS subscribes to the services and executes call back methods. The problem here is when I use
wsDualHttpBinding, I get an exception at the highlighted line
subscribe () {
InstanceContext ctx = new InstanceContext(this);
fcsc = new FeatureCreationServiceClient(ctx, "MyEndPoint"); //error
fcsc.Subscribe();
error says
Could not find endpoint element with name 'xx' and contract 'xx' in the ServiceModel client configuration section.
Some of our friends in StackOverFlow suggested replacing wsDualHttpBinding with WShttpBinding. Now the problem is gone but there is new exception saying
Contract requires Duplex, but Binding 'WSHttpBinding' doesn't support it or isn't configured properly to support it.
Please help me. I know that some one might have already asked this question but my search for that was in vain. Thanks in Advance.
Just getting my head around message queues and Redis MQ, excellent framework.
I understand that you have to use .RegisterHandler(...) to determine which handler will process the type of message/event that is in the message queue.
So if I have EventA, EventB etc should I have one Service which handles each of those Events, like :
public class DomainService : Service {
public object Any(EventA eventA) {...}
public object Any(EventB eventA) {...}
}
So these should be only queue/redis list created?
Also, what If I want a chain of events to happen, so for example a message of type EventA also has a handler that sends an Email providing handlers earlier on the chain are successful?
ServiceStack has no distinction between services created for MQ's, REST, HTML or SOAP services, they're the same thing. i.e. they each accept a Request DTO and optionally return a Response DTO and the same service can handle calls from any endpoint or format, e.g HTML, REST, SOAP or MQ.
Refer to ServiceStack's Architecture diagram to see how MQ fits in.
Limitations
The only things you need to keep in mind are:
Like SOAP, MQ's only support 1 Verb so your methods need to be named Post or Any
Only Action Filters are executed (i.e. not Global or Attribute filters)
You get MqRequest and MqResponse stubs in place of IHttpRequest, IHttpResponse. You can still use .Items to pass data through the request pipeline but any HTTP actions like setting cookies or HTTP Headers are benign
Configuring a Redis MQ Host
The MQ Host itself is completely decoupled from the rest of the ServiceStack framework, who doesn't know the MQ exists until you pass the message into ServiceStack yourself, which is commonly done inside your registered handler, e.g:
var redisFactory = new PooledRedisClientManager("localhost:6379");
var mqHost = new RedisMqServer(redisFactory, retryCount:2);
mqHost.RegisterHandler<Hello>(m => {
return this.ServiceController.ExecuteMessage(m);
});
//shorter version:
//mqHost.RegisterHandler<Hello>(ServiceController.ExecuteMessage);
mqHost.Start(); //Starts listening for messages
In your RegisterHandler<T> you specify the type of Request you want it to listen for.
By default you can only Register a single handler for each message and in ServiceStack a Request is tied to a known Service implementation, in the case of MQ's it's looking for a method signature first matching: Post(Hello) and if that doesn't exist it looks for the fallback Any(Hello).
Can add multiple handlers per message yourself
If you want to invoke multiple handlers then you would just maintain your own List<Handler> and just go through and execute them all when a request comes in.
Calling different services
If you want to call a different service, just translate it to a different Request DTO and pass that to the ServiceController instead.
When a MQ Request is sent by anyone, e.g:
mqClient.Publish(new Hello { Name = "Client" });
Your handler is invoked with an instance of type IMessage where the Request DTO is contained in the Body property. At that point you can choose to discard the message, validate it or alter it.
MQ Requests are the same as any other Service requests
In most cases you would typically just forward the message on to the ServiceController to process, the implementation of which is:
public object ExecuteMessage<T>(IMessage<T> mqMsg)
{
return Execute(mqMsg.Body, new MqRequestContext(this.Resolver, mqMsg));
}
The implementation just extracts the Request DTO from the mqMsg.Body and processes that message as a normal service being passed a C# Request DTO from that point on, with a MqRequestContext that contains the MQ IHttpRequest, IHttpResponse stubs.
I'm putting together a WCF service using net.tcp and netTcpBinding to get duplex comms with my Silverlight client. I call into the service from the Silverlight app and the service calls out to another server, passing it a callback method in the WCF service class. The remote server calls back several times and each time it does, the WCF service uses the callbackchannel to send the data to the Silverlight client. It all works nicely most of the time.
If the user puts in a big request, I get a TimeoutException after a large number of callbacks have already worked. (Clearly, there's some work to do elsewhere to prevent this but I'd like to robustify the service, first.)
I was expecting to do some kind of 'if (client.ConnectionState == faulted)' check before trying to call back to the Silverlight client but I can't seem to find the object that holds the state of the connection. Is there one? Am I approaching this from the wrong side?
This is my first venture into a service net.tcp and duplex. I just moved house and my WCF bible is still in a box. Somewhere. :-) So, I can't do my usual background reading.
Any pointers would be gratefully received. Here's some bare code in case my description is too soupy:
private IActiveDirectoryClient client;
private AsyncSearchRunner runner;
public void Search(Request request)
{
this.client = OperationContext.Current.GetCallbackChannel<IActiveDirectoryClient>();
runner = new AsyncSearchRunner();
runner.Run(request.SearchRoot, request.SearchFilter, request.PageSize,
System.DirectoryServices.Protocols.SearchScope.Subtree, SendObjects);
}
private void SendObjects(List<DirectoryObject> items)
{
Response response = new Response();
response.DirectoryObjects = items.ToArray();
client.SendResponse(response);
}
Yes, there is a State property that is defined in the ClientBase<> class (all the proxy classes are derived from ClientBase<>).
There are some proxy wrappers out there that handle fault states of the connection and re-establish connections as needed. Google for "wcf proxy wrapper".
You can also home-brew something if you use some kind of ServiceLocator pattern.
this is a weird thing.
I created a simple SOAP based web service with WCF. When the 'SubmitTransaction' method is called, the transaction is being passed on to an application service. But if the application service is not available, it is being written to a MSMQ.
Like this:
public void SubmitTransaction(someTransaction)
{
try
{
// pass transaction data to application
}
catch(SomeError)
{
// write to MSMQ
}
}
So when an error occures the transaction is written to the queue. Now, when using the MSMQ API directly in my WCF service, everything is fine. Each call takes a few milliseconds.
E.g.:
...
catch(SomeError)
{
// write to MSMQ
var messageQueue = new MessageQueue(queuePath);
try
{
messageQueue.Send(accountingTransaction, MessageQueueTransactionType.Single);
}
finally
{
messageQueue.Close();
}
}
But since I want to use the message queue functionality at some other points of the system as well, I created a new assembly that takes care of the message queue writing.
Like:
...
catch(SomeError)
{
// write to MSMQ
var messageQueueService = new MessageQueueService();
messageQueueService.WriteToQueue(accountingTransaction);
}
Now when using this setup, the web service is suddenly very slow. From the above-mentioned milliseconds, each call now takes up to 4 seconds. Only because the message queue stuff is encapsulated in a new assembly. The logic is exactly the same. Anyone knows what the problem could be...?
Thanks!
Ok, now I know. It has something to do with my logging setup (log4net). I'll have to check that first. Sorry for stealing your time..
You have two new lines of code here:
var messageQueueService = new MessageQueueService();
messageQueueService.WriteToQueue(accountingTransaction);
Do you know which of the two is causing the problem? Perhaps add some logging, or profiling, or step through in a debugger to see which one seems slow.