Mapforce Anyone who has been forced to deal with EDI X12 documents knows that they are a royal pain. Each document has tons of fields—enough for any reasonable use for any reasonable organization. Having so many defined fields is actually its biggest liability. It means that every organization that uses EDI X12 pretty much has to decide what fields are significant for them. That means, for example, that an 850 document is functionally different for Nordstroms than it is for, say, Wal-Mart.

As a result, there’s a significant market for people who can map EDI documents. Most of them are service vendors pushing both document translation and document delivery with the result (happy for them) of tying you tightly into their service—and revenue stream. Jerks.

Mapforce to the Rescue

Anyway, Altova has a different model because their business is still tied to producing software that makes it easy to manipulate XML documents. They’ve grown to the point where they do a lot more than simple XML and one of those areas of growth is the ability to understand EDI documents (both X12 and EDIFACT formats). This alone was worth it for us to spring for their professional "Mission Kit".

The cool thing about their Mapforce product is that once you’ve defined your mapping, it has an option to "Generate code" with one of the selections being C#.

Mapforce Mapping

This is extremely cool and actually works

A Minor Inconvenience

Now, this is pure magic as far as I’m concerned, so I’m certainly not going to gripe about the code generated by Altova. Much. There are a few things that niggle, though.

  1. The resulting project is created as a "Console" app, so it generates an .exe file.
  2. The worker class’s Run method accepts both source and destination parameters so you’ll hit the file system if you use it "as is". Since want to use this as a library .dll, I’d prefer not to hit the file system for the destination.
  3. If you customize the Run method, you’ll overwrite it if you have to make changes and regenerate the code.

As I said, minor. Still, it means that I have to manually edit code every time I (re)generate a project and every developer knows that if it isn’t automated, it’s a potential source for errors.

Making it Better

I don’t know about you, but little things like that sometimes bug me enough that I’ll try to do something about it. In this case, I found a work-around that is useful enough that I thought I’d share it (thus this post). Two things make this work-around possible.

  1. Mapforce doesn’t clear directories when it generates code.
  2. Mapforce uses templates to generate code.

So a little creative editing and this becomes a lot less error-prone. Here’s what I ended up doing.

  • The templates are located in \{mapforce install dir}\spl\cs\MapForce\
  • Edit the "Mapforce2005.csproj" file so that it’s a Library instead of Exe:
	<OutputType>Library</OutputType>
  • If you want to get fancy, add a compile reference for a partial class you’ll be adding (the highlighted Compile line):
    <ItemGroup>
        <Compile Include="AssemblyInfo.cs"/>
        <Compile Include="[=$application.Name]Console.cs"/>
[foreach $Mapping in $application.Mappings
    foreach $AlgorithmGroup in $Mapping.AlgorithmGroups
]        <Compile Include="[=$application.Name][=$AlgorithmGroup.Name].cs"/>
         <Compile Include="[=$application.Name][=$AlgorithmGroup.Name]Partial.cs"/>
[    next
    foreach $AlgorithmGroup in $Mapping.AllLocalFunctions
]        <Compile Include="[=$AlgorithmGroup.LocalFunctionNamespace]_[=$AlgorithmGroup.Name].cs"/>
[    next
next
]    </ItemGroup>
  • Edit the "AlgorithmGroup.cs" file so that the main generated class is partial:
public partial class [=$classname] 
  • After code is generated, you’ll need to open the solution and add the partial class file it is expecting. Once you’ve done this once, however, you shouldn’t need to redo this step if/when you make changes.

Since I only really want to override the "Run" method, I’ll copy that from the main class, change the return type to XmlDocument and replace the save logic. Since saving is in a try...catch bit at the end, this is easy to replace.

At that point, you can reference the generated .dll file in whatever project is having to read EDI files. Having Mapforce target a project-specific DataSet schema makes it easy to use the returned document, though you have to work the XmlDocument into the DataSet.

public EDI850Data ReadNordstrom850File(string FileName)
{
    NordstromX850MapToEDI850Data nordstromEDIProcessor = new NordstromX850MapToEDI850Data();
    XmlDocument targetDoc = nordstromEDIProcessor.Run(FileName);

    StringReader reader = new StringReader(targetDoc.OwnerDocument.OuterXml);
    EDI850Data ds = new EDI850Data();
    ds.ReadXml(reader);

    return ds;
}
 
Trying This at Home

This is my first pass at it, so bear that in mind if you plan on doing something similar. And I’d welcome any refinement or suggestions you might have. That said, initial indications for this solution are pretty good so by all means use this as a basis for your own experimentation.