(See update below)

If you have attempted to send email from BizTalk, you’ve gotten pretty comfortable
with this documentation
topic.

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

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:

  1. Download & build Jon Flanders’ ContextAdder pipeline
    component, and make sure the build outputs end up in your Microsoft BizTalk Server
    2004\Pipeline Components directory.
  2. Build this
    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
    with email.)
  3. Use the RawString type on the orchestration port operation that you are trying to
    receive RawStrings on…

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

  5. Specify the ReceiveRawString pipeline for the associated physical port.
  6. 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.

    >

    Update:

    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:

    1. You will need to do step 2 from above.
    2. Use the XmlDocument type on the orchestration port operation that you are trying to
      receive raw string content on, and use a PassThruReceive pipeline.
    3. Create a multipart message type, with a single part that is of type RawString. 
      Also, declare an instance of this type, say, tempRawStringMsg.
    4. Receive the message from the port in step 1 into an XmlDocument-typed message (say,
      xmlDocIn)
    5. Drag out a message assignment shape.  In the expression, do: tempRawStringMsg.rawString
      = xmlDocIn;
    6. 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.

    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.