I've been asked a couple times recently about generating message out of BizTalk Server with a dynamically-set file name. Here are 3 primary ways of setting this value.

In the scenario I built here, it's a basic "stock order" situation, where the order is received, and an output file is created with a file name that adheres to a format of <date><ticker symbol>.xml. My "order" schema has a few elements, and the "ticker symbol" element has been both promoted and distinguished.

Option #1. This is arguable the easiest. Take the message in, create a dynamic send port, and use an Expression Shape to set the Address of the file drop, including the file name. Here I created a simple date string and appended the distinguished "symbol" field to build the file name.

As expected, the output file was generated.

Option #2. Let's say you want the send port pre-configured as a FILE port and don't want to dynamically set all the values of the port. Well, what you can do is create a copy of your incoming message (via Message Assignment) and then set the context value FILE.ReceivedFileName to your dynamically generated name. The FILE.ReceivedFileName is assigned when the FILE adapter receives a message. It contains the physical name of the inbound file.

This comes into play in the FILE send port where you can use the token %SourceFileName% as the destination file name. That token uses the FILE.ReceivedFileName value. So what we've done is set the value in our orchestration that this token will use when writing the file out. Once again, after running this version I get the file output with the expected name.

Option #3. Let's say you have a "messaging-only" solution and no need for orchestration. In that case, you can use a simple custom pipeline component to do the same thing we did in Option #2. I created a basic custom send pipeline component which sets the value of the FILE.ReceivedFileName using the code below ...

public IBaseMessage Execute(IPipelineContext pc, IBaseMessage inmsg)
{
//set friendly date string
string dateString = System.DateTime.Now.Year.ToString() + System.DateTime.Now.Month.ToString() + System.DateTime.Now.Day.ToString();

//create pointer string
string tickerString = "";
string fileString = "";

//get value of ticker symbol that's been promoted
tickerString = Convert.ToString(inmsg.Context.Read("Symbol", "http://Microsoft.Blog.DynamicOutput.PropSchema"));

//build outbound file name
fileString = dateString + tickerString + ".xml";

//write updated value back to context
inmsg.Context.Write("ReceivedFileName", "http://schemas.microsoft.com/BizTalk/2003/file-properties", fileString);

//return the message with modified context
return inmsg;
}

Once that component is compiled and made available to Visual Studio, you create a Send Pipeline and drop our little component in there, like so ...

And I get the same file name as the other two options. So, it's fairly easy to manipulate the destination file name using either dynamic ports or playing with context values. Any other options I missed?

Technorati Tags: