Tuesday, December 14, 2010

Adventures with BizTalk: HTTP "GET" Part 4: Custom HTTP Adapter

[Note: This post is based upon an old blog post that I'm migrating for reference purposes, so some of the content might be a bit out of date. Still, hopefully it might help someone sometime...]

So, if we can't use the HTTP Send Adapter to retrieve files from a dynamically-obtained URL, can we override the behaviour in a custom HTTP Adapter?

Hmm... Well, first of all, writing a custom Adapter for BizTalk isn't something that I'd normally embark upon lightly. After all, you have the BizTalk OOTB Adapters and 3rd party Adapters, why write your own that you then have to test, support and maintain, particularly just to retrieve a file?!

So, in this case, I wasn't REALLY considering writing a custom HTTP Adapter... What I did briefly consider though was whether we could leverage the existing BizTalk HTTP Send Adapter, and just override its use of the "POST" HTTP verb.

The plan was coming together nicely, I'd identified the piece of code in the BizTalk HTTP Send Adapter that hardcodes the HTTP verb... It's in Microsoft.BizTalk.HttpTransport.dll, in the HttpAsyncTransmitter class's SetRequestProperties method:

request.Method = "POST"

So temptingly close, yet so far. Alas, the majority of the classes in Microsoft.BizTalk.HttpTransport.dll are sealed, and HttpAsyncTransmitter is one of them... So I couldn't inherit from it and override this one line!

I was left with the alternative of potentially disassembling the entire DLL and using it as the basis for writing my custom Adapter, or just going it alone...

Although I was already strongly leaning away from the custom Adapter approach, this really hammered the final nail in place...

So, it seems as though we've exhausted the alternatives for leveraging the OOTB BizTalk HTTP Adapters...

[UPDATE]

Another alternative to my rather brutal efforts to extend the OOTB BizTalk Adapter is to use the HTTP Adapter sample in the BizTalk SDK, also known as the "HTTP.NET" Adapter.

This sample is a rather rudimentary custom .NET implementation of an HTTP Adapter, so it's nowhere near as fully-featured as the OOTB HTTP Adapter, but it's a good start. And the good part is we have the full source code, so can change it to suit our needs.

The HTTP.NET Adapter implementation already supports specifying the HTTP verb as part of its configuration [why this hasn't been worked back into the OOTB HTTP Adapter I'm not sure].

In our case, the only change required came down to modifying the SendHttpRequest method in the HttpTransmitterEndpoint class (excerpt below):

private WebResponse SendHttpRequest(IBaseMessage msg, HttpAdapterProperties config)
{
  // ...
  // Original code...
  // Note: both the body part and the stream maybe null, so we
  // need to check for them
  string charset = string.Empty;
  IBaseMessagePart bodyPart = msg.BodyPart;
  Stream btsStream;

  if (request.Method != "GET")
  {
    // Original code...
    if (null != bodyPart && (null != (btsStream = bodyPart.GetOriginalDataStream())))
    {
      // ...
    }
  }

  return request.GetResponse();
}


The only change we've made is to wrap the code that deals with the request message body inside a check against the HTTP method (verb). If it's GET, we don't want to pass a request message body. Otherwise, we play on as per the original code.

This change could certainly be tidied up: It could be possible that there are some instances where we DO want to pass a body in the request message even when we're using GET, so you could introduce another configuration property such as "SuppressMessageBody" to cater for this.

The end-result however was that this change allowed us to achieve the desired result.

Looking back at it, I'm still not sure where my preference would be: I really do prefer to use OOTB Adapters where possible, not write and maintain my own, particularly when the custom version is a lot less feature-rich than the OOTB Adapter. However, I do kind of like using Adapters over custom .NET code... Now if the OOTB HTTP Adapter just included configuration properties for HTTP verb and message body suppression... Isn't this kind of requirement likely to become more prevalent with the increased focus on using REST?

No comments:

Post a Comment