Did you ever want to know how to process (parse) or create EDI files by just using .NET C#? There is a great library that can help.
I’m working on a new Udemy class that is an Intro to EDI (Electronic Data Interchange). Other than using more expensive enterprise systems like BizTalk, I wanted to show students how they could both 1) parse EDI themselves, and 2) use any good .NET libraries that are available.
In doing some research on StackOverflow, I ran across EDI.NET. The author, Constantinos Leftheris, from Greece, was inspired and influenced by the NewtonSoft JSON library. You may know that the NewtonSoft library allows you to serialize and deserialize JSON from objects in memory, to and from disk files (or strings).
With EDI.Net, you can do the same with EDI. The only catch is, you have to create a C# class (he calls it a POCO class) that defines the interchange, including all the EDI fields you want to access. It uses C# attributes (or decorators) to tell the software the relationship between an EDI column and the class variable.
It handles X12, EDIFact and the older TRADACOMS.
For example, if you are familiar with the X12 850 Purchase Order,
it a a “BEGIN” segment like this:
BEG*00*SA*1000012**20090827~
You interpret it by looking at an implementation guide, such as the one below:
In the example above, the “*” is the delimiter or separator character from each element. You then count over and each element has a sequential name, BEG01, BEG02, BEG03 (etc) based on the Segment Name “BEG” and a two digit number.
This tells us that BEG03 is the Purchase Order Number, and BEG05 is the PurchaseOrderDate. BEG04 is not used on a new PO, only for revisions to existing PO (which many companies do not support). Note that it has the letter “O” for Optional in the required column, while the other fields have “M” for Mandatory.
You can also learn from the above implementation guide that the PO Number (BEG03) can be from 1 to 22 alphanumeric (AN) characters.
The “type” for BEG05 is “DT” (Date) and it’s min/max length are both 8. The comment tells us that is must in the format CCYYMMDD.
Note in the attributes below, that “BEG/2” is zero-based, representing BEG03. It uses COBOL-like “Picture” clauses to describe the length and type of number in the field.
The sample above has BEG01=SA, which is not in the implementation guide I included above. Each company will hvae its own implementation guide and they may vary slightly as to code values and other nuances. But certain things like the PO Number being in BEG03 and the PODate being in BEG05 should never change.
<pre>
[EdiValue(Path = "BEG/2", Description = "BEG03 - Purchase Order Number")]
public string PurchaseOrderNumber { get; set; }
[EdiValue("9(8)", Path = "BEG/4", Format = "yyyyMMdd", Description = "BEG05 - Purchase Order Date")]
public string PurchaseOrderDate { get; set; }
</pre>
Deserializing is the process of taking an EDI file and loading into an object made from the POCO class. To create a new EDI file, you would be the object in the C# program, then serialize it to disk as an EDI file.
Download the zip
To do the demo below, you will need either download the .zip file from the GitHub or do a Git Clone. You will be needing the the “POCO” class called “PurchaseOrder850” in X12_850.xs.
Instructions for an easy X12 demo
- Create new C# console program, put code below in the program.cs.
- From top menu, click “Tools”, “NuGet Package Manager”, “Package Manager Console”, then type in “Install-Package “indice.Edi”.
- In Solution Explorer, click “add” then “existing item”, and select indice.Edi.Tests\Models\X12_850.cs (from the GitHub zip download).
- Adjust the filename to match where you put the files on your disk.
- Run it with the sample
- Then try it one of your EDI 850 files if you have one.
- Customize the C# POCO class as needed.
<pre>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using indice.Edi;
using indice.Edi.Tests.Models;
using System.IO;
namespace EDINetDemo
{
class Program
{
static void Main(string[] args)
{
string inputEDIFilename = @"c:\EDI.Net-master\test\indice.Edi.Tests\Samples\x12.850.edi";
//string inputEDIFilename = @"c:\EDIClass\Samples\Sample_850_01_Orig.edi";
var grammar = EdiGrammar.NewX12();
grammar.SetAdvice(
segmentNameDelimiter: '*',
dataElementSeparator: '*',
componentDataElementSeparator: '>',
segmentTerminator: '~',
releaseCharacter: null,
reserved: null,
decimalMark: '.');
var po850 = default(PurchaseOrder_850);
using (var stream = new StreamReader(inputEDIFilename))
{
po850 = new EdiSerializer().Deserialize<PurchaseOrder_850>(stream, grammar);
// If you have only one ST and one PO/850 per file,
// you can use subscript 0,
// otherwise you will need loops here.
Console.WriteLine("PO Number:" +
po850.Groups[0].Orders[0].PurchaseOrderNumber);
Console.WriteLine("PO Date:" +
po850.Groups[0].Orders[0].PurchaseOrderDate);
foreach (var lineitem in po850.Groups[0].Orders[0].Items)
{
Console.WriteLine(" LineItem:");
Console.WriteLine(" ItemNum=" + lineitem.OrderLineNumber);
Console.WriteLine(" Qty=" + lineitem.QuantityOrdered);
Console.WriteLine(" Price=" + lineitem.UnitPrice);
Console.WriteLine(" PartNo=" + lineitem.BuyersPartno);
Console.WriteLine(" Descr=" + lineitem.ProductDescription);
}
// 1) store PO into Database
// (create SQL statements or call Stored Proc)
// 2) write to XML for ERP system
// 3) call some web service
}
Console.WriteLine("\n\n Press enter to end:");
Console.ReadLine();
}
}
}
</pre>