(See update below)
If you have attempted to send email from BizTalk, you’ve gotten pretty comfortable
with this documentation
It discusses how to use a sample class (Microsoft.XLANGs.CustomFormattersSDK.RawString)
and associated custom formatter to deal with messages that contain raw string content.
As the docs say, “Sending a message of type System.String will not work, because
the string gets formatted as an XML document in the message, which is not your desired
solution.” (In other words, whether you send or receive, using System.String
as a message type means you are dealing with a wrapping tag.)
However, though the docs cover sending RawStrings, it is less clear how you
can use the RawString class when you want to receive messages as such. Just
typing the port operation as RawString will yield a UnexpectedMessageTypeException,
because none of the default receive pipelines will set the MessageType context property
on inbound messages to be RawString – and this type matching is what orchestrations
We need a custom receive pipeline that will set the MessageType context property equal
to the fully qualified type name for RawString. Jon’s discussion of receiving
binary messages provides some background here, and Jon’s ContextAdder pipeline
component can make the MessageType context property assignment very easy.
Here are the steps required to receive RawStrings:
Download & build Jon Flanders’ ContextAdder pipeline
component, and make sure the build outputs end up in your Microsoft BizTalk Server
2004\Pipeline Components directory.
code (the RawString class & custom formatter) into a separate C# library (with
a strong name) and deploy it to the GAC (if you haven’t already when dealing
Use the RawString type on the orchestration port operation that you are trying to
receive RawStrings on…
Create a receive pipeline (ReceiveRawString), and add the ContextAdder pipeline component
in the Validate stage. (You will only ever need one such pipeline around –
put it in a common library.) Configure the properties collection with the properties
for RawString, as shown below (“Value” property will be the full five-part
assembly-qualified type name):
- Specify the ReceiveRawString pipeline for the associated physical port.
- You will need to do step 2 from above.
Use the XmlDocument type on the orchestration port operation that you are trying to
receive raw string content on, and use a PassThruReceive pipeline.
Create a multipart message type, with a single part that is of type RawString.
Also, declare an instance of this type, say, tempRawStringMsg.
Receive the message from the port in step 1 into an XmlDocument-typed message (say,
Drag out a message assignment shape. In the expression, do: tempRawStringMsg.rawString
As before, you might want to declare an orchestration variable (not a message) of
type RawString, and assign it to tempRawStringMsg.rawString so you can access properties/methods
like ToString(), which returns the underlying string content.
Now you will have full access to the raw string content, and can do whatever you need
to do…You might want to declare an orchestration variable of type RawString,
and assign it to the RawString message so you can access properties/methods like ToString(),
which returns the underlying string content.
Greg Van de Wiele has pointed
out the other way to go about this (and Jon has talked
about this approach in his recent posts as well.) It can be less work
in that no custom pipeline is required (a one time task) – though perhaps a little
harder to explain to the “next guy“…you can decide!
It goes like this:
Note that not wrapping the RawString in a multipart message doesn’t work
– you will get a compiler error indicating that assignments can’t be made between
XmlDocument and RawString types. Also note that introducing an intermediate
message has a performance cost.