Mapping a WCF request message to the underlying operation - wcf

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.

Related

IClientMessageInspector CorrelationState

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).

Action vs Reply action WCF

What's the use of action/reply action for service operation in WCF. So far, what I've understood is; action is used by WSDL to identify the service operation to which the message from the client belongs and in return reply action is used by service operation to identify the caller to which reply message belong --> Please correct me if I am wrong with this!
Now, I want to understand; what's the real use (apart from handling anonymous messages by using aster ix [*]), I mean this could well be handled internally by WCF instead of exposing it to the developer.
Also, why is action and replyaction required at all? I mean, we already have a name property for the service operation to identify the method and when I call Proxy.SomeMethod() then somemethod is already mapped to the Name property and it should be enough to identify the destination method for the message and similarly the replyaction. Please clarify.
Can I please get a simple real world scenario/or link to that to understand Action/ReplyAction in real life.
Many Thanks.
Actions are part of the various SOAP and WS-* specifcations.
So the first point is that this is not something unique to WCF it is a standard part of the specification you need to support if you want to have interoperable web services. They are used for message routing and other message handling functions.
Second, WCF DOES manage these by default. You only need to specify them yourself if you wish to customise or manage them in some other way. E.g. WCF will automatically generate them into the WSDL for you. WCF will also use them by default when it is selecting which operation to invoke for an incoming message. Again, WCF provides extension points to customise this behavior if you require.

Generic WCF Routing/Forwarding/Proxy Server

Is it possible to create a "generic" as in "adaptable" routing service, which will NOT have any public methods to call. Instead, you'd be able to call any command, which would then be mapped in the service and will pass it to appropriate end point with simple message transformation where required.
It may be hard to understand and idea might seem a bit crazy (it came from a colleague of mine), but it's clearer if you look at the example:
similar to what's described in this article, only difference is that our service should not have a "SubmitTimeSheet" public method, in fact it should have no public methods to call. We'd have to "intercept" an incoming call on a much lower level before it returns "Method Not Found" error.
Is this at all possible? The reason for this is obvious: possibility of adding new clients without having to change the code. All we'd have to do is to add a new mapping entry in some sort of config file or even database, e.g.
<Client address="newClientAddress" method="DoAnything" transformation="NewClientDoAnything.xslt" endPoint="endPointClientAddress" endPointMethod="endPointClientDoAnything" />
Check out WCF 4 routing - supports content based routing, xpath transforms and much more.
http://blogs.msdn.com/b/routingrules/
They have already done it in Nirvana. But it is very expensive.
This is not possible in WCF unless you define your contract as a very loose, fit-for-all contract which takes a message and returns a message. By doing this, you will los all the goodness (although not huge goodness in WCF) of WCF.

Accessing the ServiceModel layer directly

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)

Problem with WCF client calling one-way operation

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.