With BizTalk 2004, it can be quite helpful to eventually maintain binding files as
“source code”.  After a solution has reached a certain point of stability (where
port definitions are not changing often), many projects will use the Deployment Wizard
to do one last export of the binding information — and then maintain it by hand for
any future changes (storing it in version control along with the rest of the solution.)

There are some interesting benefits that come along with this.  One such benefit
is the ability to use the XmlPreProcess tool
to merge environment-specific elements into the binding file (like URIs, retry counts,
etc.), using the SettingsFileGenerator.xls spreadsheet to assist — as has been discussed
on this blog before.  Even if you are not using the Deployment
Framework (which uses XmlPreProcess extensively), you should consider using XmlPreProcess as
a standalone tool.  The ability to easily maintain a matrix of logical names
(for physical endpoints, etc.) versus “environment names” (development, QA, production,
etc.) is a huge help.  See the example spreadsheet below.  (The Deployment
Framework also shows how to extend use of this same spreadsheet to manage run-time
configuration settings that are stored in the BizTalk SSO.)

(click)

Optional Deployment of Port Definitions

On to a bit more advanced topic: If you have a set of port definitions that you want
to conditionally deploy into a given environment, you can define a true/false
value within the spreadsheet and use simple “ifdef” logic in your binding file around
the port definition.  For instance, you might want a particular File Send Port
or Receive Location to only be active in your development and test environments. 
To do this, define a name such as “LogInboundPODocsToFile”, and set the default value
to “true” – and set it to “false” in the “production” column.  Mark up your binding
file accordingly.  See the example spreadsheet and binding file snippet below. 
(When XmlPreProcess is run on this binding file, the port definition will only be
included for environments where the LogInboundPODocsToFile value is true.)

(click)

<!-- ifdef ${LogInboundPODocsToFile} -->
<SendPort Name="LogSalesOrderResponse_FILE" IsStatic="true" IsTwoWay="false">
<TransmitPipeline Name="SendWithDefaultNamespaceFormat"        
FullyQualifiedName="SendWithDefaultNamespaceFormat, XYZCo.BizTalk.Pipelines, Version=1.0.0.0,
Culture=neutral,     PublicKeyToken=343bd7a15fff8d6e"
Type="2" />
<PrimaryTransport>
<Address>C:\Dev\FileLog\%MessageID%.xml</Address>
<TransportType Name="FILE" Capabilities="11" ConfigurationClsid="5e49e3a6-b4fc-4077-b44c-22f34a242fdb"
/>
...
</SendPort>
<!-- endif -->

Why would you want to conditionally deploy ports?  Like many, I have found it
useful to have an additional file-based Receive Location (associated with a Receive
Port bound to an orchestration) to kick off orchestrations during development – even
if the actual transport used in production will be something different.  In addition,
binding an orchestration to a Send Port Group allows you to have an additional
file-based Send Port that will create an easy log of outbound traffic.  Finally,
you might create a file-based Send Port that acts as an “additional” subscriber (by
Receive Port Name) to your inbound messages for an easy log of inbound traffic. 
(And, combined with a file-based receive port, these two mechanisms give you an easy
re-processing mechanism – just drag/drop in Explorer.)  But you might want all
of this machinery shut off in production, hence the technique we just discussed.

Macro Recursion

Another feature within XmlPreProcess is the ability to use “macro” recursion with
XmlPreProcess.  This means you can define a macro (logical name) such as QueueServer
(with a different value for development, QA, and production, etc.) and then define
additional values in the spreadsheet that build on this such as: POAckQueue = {$QueueServer}\private$\POAckQueue. 
This indirection can make maintaining large numbers of endpoint URIs even easier…See
the example below – where POAckQueue can now appear in the “default” column (applicable
to all environments.)

(click)

Multiple Environments

Note that the SettingsFileGenerator.xls spreadsheet provided with the Deployment Framework
sample (and with XmlPreProcess) has room for four environments (development, QA, staging,
and production.)  However, you can simply add columns to manage additional environments
if need be.  One such use of this would be to create a column for “unit testing”,
where the URIs and other binding file substitutions point to resources under the control
of your unit testing framework.

More to say on binding file management in another post…