title: WCF IErrorHandler Get Request message
body: <p>(Similar to <a href="https://stackoverflow.com/questions/1399971/ierrorhandler-get-original-message">this</a> question, however it ended up not being needed in that case)</p>
  
  <p>I'm using an IErrorHandler implementation -- creating a FaultException so that clients to the service receive 'pretty' errors in the event of unhandled exceptions.</p>
  
  <p>I'd now like to use an element in the <em>request</em> message and bounce it back in the FaultException and I'm not winning.</p>
  
  <p>I can access the <code>OperationContext.Current.RequestContext.RequestMessage</code>, and can see the full envelope (including the 'message ID' property I want the FaultResponse to contain) using its <code>ToString()</code>, however I'd like to either 'manually' deserialize the request Message, or even just read the body as XML in order to extract the request property I'm looking for.</p>
  
  <p>However I'm not able to read from the message, as (I assume) the Message has already been read somewhere previous in the WCF pipeline: </p>
  
  <p><strong>'The message cannot support the operation because it has been copied'</strong></p>
  
  <p>Here's my <code>ProvideFault()</code> implementation (I'm aware the XElement parsing may not even work in this form -- I'm not focusing on that now):</p>
  
  <pre><code>public void ProvideFault(Exception error, MessageVersion version, ref Message fault) {
      if (error is FaultException)
      {
          // Let WCF handle            
      }
      else
      {
          // Extract the 'messageID' element from the request message
          var req = OperationContext.Current.RequestContext.RequestMessage;
  
          // Throws the 'has been copied' exception
          XElement body = XElement.Parse(XElement.ReadFrom(req.GetReaderAtBodyContents()).ToString()); 
  
          var msgId = (string)body.Descendants("messageID").FirstOrDefault();
  
          var err = new FaultException&lt;Foo&gt;(new Foo
              {
                  MessageID = msgId
              }, "Server error");
  
          var msgFault = err.CreateMessageFault();
          fault = Message.CreateMessage(
              version,
              msgFault,
              null);
      } }
  </code></pre>
  
  <p>What's the best way to do this?</p>
  
  <p><strong>EDIT:</strong> It doesn't look like it's possible to read the OperationContext's Request Message during the IErrorHandler events -- presumably because it's already been read earlier in the WCF pipeline (so creating a copy of the message using the MessageBuffer will not work). A 'workaround' to the problem is described in the accepted answer.</p>