WCF when to use MessageHeader rather than passing variable in function argument - c#

I am reading about MessageContract & MessageHeader and trying to understand the use case of sending some info in MessageHeader and not use it just as a function parameters?

Message contracts and message headers are somewhat advanced concepts which most people will never need to use. They're mostly used in interoperability scenarios where you need to communicate with a 3rd party service which expects the data in a certain format (i.e., some parameters in the headers).
Other possible scenarios for passing some parameters in message headers:
Headers can be easily accessed in message inspectors and other extensibility points in WCF (since headers are always buffered), so if you want to use some of those to do some validation (for example, some authentication decision), you may want to have the parameter in the header
As #Vasile mentioned, if you want to have a streamed transfer, since the headers are always buffered they can be used to convey some additional information to the operation prior to the (streamed) body being read / consumed

The MessageContract & MessageHeader provides lower-level control of your messages than DataContract & DataMember. Also it provides a way to create SOAP Headers if you're using webHttpBinding or basicHttpBinding.
If you're using streaming capabilities in your WCF service, than using MessageHeader is the only way to pass data besides the stream itself.
You can read more about message contracts in this MSDN article

Related

REST Batch\Bulk API implemetation in WCF similiar to Facebook API

I'm implementing new REST API method which allows calling other REST API methods in batch\bulk manner. Similar to Facebook's https://developers.facebook.com/docs/graph-api/making-multiple-requests
Request example:
POST /batch
[
{"method":"GET", "relative_url":"/user/anton"},
{"method":"GET", "relative_url":"/user/vitaliy"}
{"method":"POST", "relative_url":"/user/dan", "body":{name:Dan}}
]
Response example:
status 200
[
{"status":"200", "body":{name:"Dan"}},
{"status":"404"},
{"status":"201"}
]
In short, batch method should on server-side call OTHER methods one-by-one and return result as array of results.
The most simple solution will be create .Net HttpClient on server side and call other WCF methods on-by-one.
The question is: How implement this using WCF infrastructure without calling WCF method externally via HttpClient?
The reason for that - I don't want to have network-round trips.
The most perfect solution will be to use .Net Reflection, but this not good solution in terms of REST abstraction
The most close solution is create WCF Message including HttpRequestMessageProperty (URL, Headers, Method, Content-Type) and send it to processing by WCF infrastructure (just it was sent via HTTP protocol) (not sure about this):
Message responseMessage = wcfInsfrastucture.Process(createWcfMessage(url, method,contentType,body));
Currently I'm lost in WCF Samples, and WCF server-side channel architecture.
Most similar question was asked in Sending custom WCF Message to a service but I can't making it work with existing configured server-side behaviors.
Similar questions:
Sending custom WCF Message to a service
https://stackoverflow.com/questions/26049136/generic-way-to-send-wcf-messages-to-different-channels
How implement this using WCF infrastructure without calling WCF method externally via HttpClient?
The only way I found is to implement request-response pattern over WCF.
Create a single entry point in WCF service, that receives an abstract request as an argument and returns an abstract response.
For example,
<OperationContract> function Execute(Request as IRequest) as IResponse
Create concrete request and response classes for service operations
Create CompositeRequest and CompositeResponse for Batch / Bulk operations
All service has to do is to apply business logic according to request type.
In case service receives CompositeRequest it just calls the same Execute method for all nested requests one-by-one and aggregates responses into CompositeResponse.

Can an endpoint behavior accept parameters

I am using message inspector in WCF application to store request & responses, into DB.
Whether to store these data in DB or not has to be restricted based on userInput received in the front-end.
To cut the long story short, I need help to address these issues -
States in page context are not available in the extensibility points
interface.
Inspectors method also do not accept any custom
parameters.
In this case, How can we pass the parameters to the WCF extensibility points for customizations?
Well the IDispatchMessageInspector interface receives a IClientChannel on each call, which is in turn an IExtensible. You would have to implement an custom IExtension, and extend the client channel when it's initialized (using an IChannelInitializer implementation). You could then retrieve the extension from the channel parameter in the inspector method implementation, and use it as a means of communication with you front end..

How to return both stream and file length from WCF Restful json webservice?

Hihi all,
I am able to return stream from my WCF restful json webservice, everything works fine. But when I mixed the stream with another piece of data (both wrap into a custom class), upon consuming the webservice from my client, it gives an error message of "An existing connection was forcibly closed by the remote host".
Any advice how can I achieve the above? What it's required for my webservice is to allow downloading of a file with the file length as an additional piece of information for validation at the client end.
Thanks in advance! :)
There are various restrictions while using Stream in WCF service contracts - as per this MDSN link, only one (output) parameter or return value (of type stream) can be used while streaming.
In another MSDN documentation (this is anyway a good resource, if you want to stream large data using WCF), it has been hinted that one can combine stream and some input/output data by using Message Contract.
For example, see this blog post where author has used explicit message contract to upload both file name & file data. You have to do the similar thing from download perspective.
Finally, if nothing works then you can always push the file length as a custom (or standard such as content-length) HTTP header. If you are hosting in IIS then enable ASP.NET compatibility and use HttpContext.Current.Response to add your custom header.

WCF messageheader vs messagebodymember?

I do not understand when I should put the [MessageHeader] instead of the [MessageBodyMember]?
I have read that it's used to conform some protocol like Soap, but still, what does it change at the end?
SOAP is a protocol in which each message (request or response) is made up of two parts: the Header and the Body, inside an Envelope:
<s:Envelope xmlns:s='the namespace for the soap version'>
<s:Header>
<!-- SOAP headers will come here -->
</s:Header>
<s:Body>
<!-- SOAP body members will come here -->
</s:Body>
</s:Envelope>
You normally wouldn't use [MessageContract] (and MessageHeader or MessageBodyMember) in WCF services, only if you really need to interop with some 3rd party which expects the data in a certain format.
I think when I want to put something independent of message content, I will put it in the message header.
And if you want another party to read something from your message, it should be put in the header, because sometimes you may allow someone to read the message header not message body as it contains confidential contents.
You can think about it as difference between message data (MessageBodyMember) and message metadata (MessageHeader). There is plenty of build in standardized headers provided by WCF which deals with addressing, security, reliable messaging, etc. In default WCF implementation it is related only to SOAP.
There is also general rule that in complex messaging architecture there can be intermediaries who read metadata and use them to some processing and message routing (they can even add additional metadata) but they should never interfere with message body (data). In case of security they can even not be able to read message body or some metadata (headers).
In case of WCF you are able to set different security requirements (none, signed, signed and encrypted) for each message header and for whole message body (WCF doesn't support separate security requirements for different body parts). That can also lead to some decision about using body member or header.
For example if you decide to make some custom authentication, or transferring some client information in each message you will probably create custom header for that but real data payload related to the operation will be part of message body.

WCF REST client with TransferMode=Streamed - logging entire ("raw") http requests/responses

This is on .Net 4, full framework.
I'm trying to make a simple winforms app that will make some simple WCF REST calls. It's using ChannelFactory and the service contract interface. Of the ~20 methods in the interface, 2 of them involve Stream (an upload and a download method) so the service side (and currently also the client side) using TransferMode=Streamed.
My goal is to include the full HTTP request and response (much like you would see in ethereal/wireshark, or fiddler, or whatever), with headers, in a textbox of the winforms app (just to show what went over the wire)
In trying to use the built-in diagnostics (via SvcConfigEditor) and my own (via implementing IClientMessageInspector and then IEndpointBehavior to add the inspector, then channelFactory.Endpoint.Behaviors.Add to add the behavior :), I'm having 2 issues:
When doing request.ToString() or reply.ToString() in BeforeSendRequest and AfterReceiveReply, it only gets the 'body' and not the headers. Digging around in the objects in the debugger it looks like the reply has them in reply.Properties["httpResponse"], but the request's request.Properties["httpRequest"] has an empty Headers property even though Fiddler shows headers for Content-Type, Host, Accept-Encoding, and Connection. It seems like there's likely a better way to get the 'raw' message that I'm missing (and if there's not, someone probably knows an existing chunk of code to 'reconstruct' the raw one from the Message)
Since the transfer mode is Streamed, the 'body' part just shows up as the string '... stream ...', both in SvcTraceViewer (and the 'raw' svclog - even with logEntireMessage=true) and when doing a ToString(). If the mode is Buffered instead, it shows the actual body fine. I tried making a copy with reply.CreateBufferedCopy(int.MaxValue); but that then caused the actual WCF call to fail with an InvalidOperationException: This message cannot support the operation because it has been copied.
One fallback would be to move the client to Buffered and just change to StreamedRequest for the one upload call and StreamedResponse for the download call (but I'd have to do that programmatically AFAICT, as it's set at the binding level in the config and I don't see anyway of doing it via attributes on the calls), which would take care of the 'body' part and leave me with just the "get the http request headers" (issue #1, specifically request.Properties["httpRequest"].Headers being empty) to deal with, but I'm hoping there's some way of logging the 'raw' messages without doing so, leaving the TransferMode as Streamed.
Thanks!
I can't find any reference right now, but it's a known fact that you cannot capture the contents of a streamed message to WCF tracing. When streaming is enabled, only the headers of the message will be traced.
Here's the source: Configuring Message Logging on MSDN
See towards the end of the page:
Service Level
Messages logged at this layer are
about to enter (on receiving) or leave
(on sending) user code. If filters
have been defined, only messages that
match the filters are logged.
Otherwise, all messages at the service
level are logged. Infrastructure
messages (transactions, peer channel,
and security) are also logged at this
level, except for Reliable Messaging
messages. On streamed messages, only
the headers are logged. In addition,
secure messages are logged decrypted
at this level.

Categories