I can't find much information on the return value for the BeforeSendRequest method of the IClientMessageInspector interface. All examples I've found always return null. From the description on MSDN, this method's return value is passed back as the correlationState argument once AfterReceiveReply is called. However, MSDN also states that the best practice is to use a GUID for the correlationState.
This statement is somewhat confusing to me as I am interpreting it to mean that I am supposed to use only GUIDs for the correlationState. What I want to do is use the xml content of the request as the state so that if the reply is a fault, I can log both the request and reply. I only want to log the request if the reply is a fault.
Does anyone have any experience with using the correlationState? Can I use it for what I want to use it for? It appears to work in testing but due to the limited amount of information I've found on this, I am worried that there may be some kind of pitfall that I'm not seeing.
The CorrelationState, as it's name, designed to help you to find the correlation between the sent request and the received reply.
Therefore, because GUID is a unique identifier, MSDN recommends to use it as the correlation state.
At the BeforeSendRequest and AfterReceiveReply methods you can log both correlation state value and Messages object (using CreateBufferCopy / CreateMessage and other Message class operations) and do the match between sent request and received reply.
Note that in this solution (and any other pure WCF solutions, BTW) you can't log the request only if the reply is fault. It's because there is no place in the WCF pipeline you have both request and reply.
The only chance to do so, as you mentioned, is to use the message (as string or Message object - again, using Message class operations) as the correlation state.
This is not necessarily a good idea if your service logic can got success reply and fault reply for the same input (for example if your logic depends on external resources as database or other service).
Related
I'm new to WCF, so apologies if I'm missing the boat completely.
It seems like WCF provides plenty of functionality for using the "Channel" layer by itself. For example, to create a server, you can create a channel listener from a binding and call WaitForRequest, Reply, etc. These methods all deal with Message objects, so it is up to you to do something with the message.
My question has to do with what happens once we've already got a message. Suppose I have an object that implements a service, described by a ServiceContract, and a Message object which I know represents a call to a particular operation. What I'd really like to do is something like:
Message requestMessage = GetMessageSomehow();
OperationDescription oc = GetContractForMessage();
Message replyMessage = Invoke(myService, oc, requestMessage);
At the very least, if I could somehow access the IOperationInvoker and IDispatchMessageFormatter objects that get created for a type, it would be pretty simple to chain them together to get the functionality I'm looking for.
In my particular case, I need to implement some simple Soap 1.1 and 1.2 services (with no WS-Addressing). I already have HttpListenerRequest/Response objects, and can route based off of either the SOAPAction or ContentType header.
I think having this functionality would also be pretty useful for unit testing. For example, I need to implement to existing clients. It would be nice to have unit tests where I could test that the Attributes on the service class are correct (i.e. that the message that I know I will be getting gets properly translated into a call on my service interface).
Any suggestions?
Serialization/Deserialization from that Message instance to actual parameters for a call is usually done by an IDispatchMessageFormatter / IClientMessageFormatter.
On the server side, an IDispatchMessageFormatter is injected into the DispatchRuntime by a custom operation behavior that the data contract serializer (or other serializer) inserts.
But... if you're not using ServiceHost, there's no DispatchRuntime. Basically, if you want all of this, you're going to have to do all the hard work yourself :)
That said, if you can get an OperationDescription object, you should be able to instantiate a DataContractSerializerOperationBehavior, but you won't be able to get an IDispatchMessageFormatter out of it... you can get an XmlObjectSerializer, though, which might, or might not, be useful for you.
Notice that an IOperationInvoker wouldn't help all that much, since that presumes you've already done message serialization/deserialization, so it's not really all that useful (and the rest of the functionality is fairly simple for basic use cases if you want to roll it yourself)
I am having a wcf method which has got isoneway attribute set to true.Now when i call this service from client ,service is throwing an invalid operation exception back to the client bcos of some business scenario going wrong.My understanding was that it will throw only endpointnotfound exception and timeoutexception.Can someone please explain why thats happening ?
Marking your contract as One-Way means exactly that: messages flow in one way only. Clients won't get an answer or wait for the service to execute at all, so there's no way that your client could possibly get a reply or fault from the service most of the time.
If you want that, then maybe a One-Way service isn't for you and what you really want is a two-way service with an empty reply (i.e. void)
Does the OneWay method return a value or has ref/out parameter? If yes, then that's the reason you are getting InvalidOperationException. This is expected behavior as per MSDN help for OperationContractAttribute.IsOneWay Property (http://msdn.microsoft.com/en-us/library/system.servicemodel.operationcontractattribute.isoneway(v=vs.110).aspx).
Look for remarks section, it has following text:
One-way methods must not return a value or have ref or out parameters; otherwise a System.InvalidOperationException exception is thrown.
PS: I know it's too late to reply to the thread, but for someone like me who stumbles across the post after 3 years or so, it might be useful.
I need to know what operation is being invoked by examining a request Message object in an IDispatchMessageInspector.
What is the best way to do this?
There's really no 100% sure way of doing this, because IDispatchMessageInspector.AfterReceiveRequest() runs before the dispatcher has matched the message to an actual operation on the service. That said, if you're using the default IDispatchOperationSelector, then it's possible to build a map that matches SOAP Action names with operation names during ApplyDispatchBehavior(). I have a blog post that talks a little bit about this here.
There's a bit of an example of how to build this map on some code here.
We have a situation where we might want to pass client information on every call we make on a WCF operation. At the response level, we want to have fields to indicate success and an error message.
Is it a good idea to use a Request class and a Response class? I was looking into two operation
OpeationResponseData Operation(OperationRequestData input);
I don't use OpeationRequest because that has issues with wsdl.
I will have base classes that will have the common fields each operation will need.
For example:
OperationResonseData : Response
OperationRquestData : Request
Another option is to use
Request<T> and Response<T>
I was wondering if there were a better way, or if there were some guidelines on this issue...
WCF's base messaging architecture, the Message class, already has support for all of these concepts built in.
For information that is supposed to be passed with each logical operation, you use headers.
For errors you throw FaultException or, if you want to return a custom data structure with your error, you throw FaultException. Being that errors result in faults, the lack of a fault indicates success. If you want to return details about your success then your operation should return a custom data type, otherwise you can just return void.
How this maps to what's sent across the wire depends on what formatting stack you're using (SOAP, REST, etc.). The default stack is SOAP and, being the blueprint for WCF, has a very natural mapping: headers map to SOAP headers and faults map directly to SOAP faults. For REST headers can be mapped as HTTP headers and faults would result in a 500 status with a message.
I have run into a problem when calling web service on a SAP PI bus from my WCF client.
The operation is defined as one-way, and the method on my proxy operation contract is decorated accordingly when the service reference is added.
However, the service client gets an exception when calling the according operation:
The one-way operation returned a non-null message with Action=''
Using SoapUI, the method on the bus can be called successfully, and it returns a SOAP envelope with an empty body. The bus people told me, this is according to the SOAP specs:
(SOAP specs, chapter 4.7.9, One-way operations):
There are differing interpretations of how HTTP is to be used when performing one-way operations.
R2714 For one-way operations, an INSTANCE MUST NOT return a HTTP response that contains an envelope. Specifically, the HTTP response entity-body must be empty.
R2750 A CONSUMER MUST ignore an envelope carried in a HTTP response message in a one-way operation.
R2727 For one-way operations, a CONSUMER MUST NOT interpret a successful HTTP response status code (i.e., 2xx) to mean the message is valid or that the receiver would process it.
So it seems, my WCF client doesn't comply with R2750.
I have found out that when I force the operation contract on the proxy to be IsOneWay = false, everything works.
Is there anything wrong with the way WCF handles one way operations or do I do something wrong (more likely)?
Is there anything else I should do, it just doesn't seem right to override the generated WCF proxy client.
Thanks for any suggestions.
It looks like SAP PI incorrectly sends an empty SOAP envelope and .NET incorrectly interprets that envelope.
Some options from this thread:
alter the generated proxy and remove OneWay=true (or add OneWay=false) to the method definition
catch the Protocol Violation in an exception handler and ignore it
use a 2.0 style webreference to call the service
apply SAP patch Note 1459995 - Soap Sender Adapter HTTP 202 and add &responsecode202=true to the url
The first and last options both worked for me. Further discussion on this sap.com thread.
I would take a look at this article as well by Gerben van Loon here. One way operation might not really be one way according to the standards.
Check this SAP thread out for the complete discussion:
http://scn.sap.com/thread/1627368
#Brian Low has answered this question correctly and very thoroughly (is should get marked as the answer).
I would also like to add that this is a known error in which the SOAP Adapter does not comply with the aforementioned WS-I Basic Profile 1.1 (R2750) and WCF does not comply with (R2750). The result... Hours of wasted time and teeth gnashing....
I believe that this particular problem can be fixed by adding the following attribute declaration to the operation in the client porxy:
[WebInvoke(BodyStyle = WebMessageBodyStyle.Wrapped)]
Without seeing what the signature of the method looks like, my best guess is that your method defined to return something other than "void". Since the operation is one-way, the method can only be defined using "void" (has no return). Anything else, and the operation is NOT one-way.