EDI Tools for .NET Tutorial - Part 1

Article author

EDI Tools for .NET is a software development kit for .NET Framework and .NET Core, which makes it straightforward to parse, generate, validate, acknowledge, split, customize, or in other words, to programmatically manipulate EDI files. It is written in C# and is distributed as a NuGet package.


EDI Tools for .NET Tutorial - Part 1

The techniques you’ll learn in the tutorial are fundamental to building any EDI apps, and mastering them will give you a deep understanding of the C# EDI library.

The tutorial is divided into several sections:

  • The How to represent EDI Transactions will teach you the fundamentals of EDI Templates
  • How to Translate EDI Files will teach you how to parse EDI files
  • What to do with EDI Template POCOs will teach you about the available operations such as EDI validation, create, save, and query a custom database for any EDI template, generate EDI acknowledgment, or export/import to/from JSON/XML/Custom CSV
  • How to Generate EDI Files will teach you how to generate EDI files

The second part of this tutorial, EDI Tools for .NET Tutorial - Part 2, will cover in more detail all operations for EDI Templates POCOs - EDI validation, EDI acknowledgment, creating DB structures to save and query, serialize\deserialize to\from JSON & XML.

You don't have to complete all of the sections at once to get the value out of this tutorial. Try to get as far as you can - even if it's one or two sections.


Setup and Prerequisites

You can see what we'll be building here:

Download C# examples

The narrative will use primarily X12 examples; however, a link to the corresponding EDIFACT/HL7/NCPDP examples will be included for every section. We'll assume that you have some familiarity with EDI and X12, but you should be able to follow along even if you're new to EDI. We'll also assume that you're familiar with .NET and C#. To learn more about EDI go to our What is EDI article.

You'll also need Visual Studio to open the example solutions: Get Visual Studio.


How to represent EDI Transactions

Now that you're set-up let's get an overview of EDI Tools for .NET C# Library!

EDI Tools for .NET is an efficient and flexible .NET C# library for building EDI applications. It lets you seamlessly convert between EDI files and C# instances, and can be incorporated into your Visual Studio solution(s) as a NuGet package.

EDI Tools for .NET has different components and features, but we'll start with the EDI Template, which is the core building block.

EDI Template is the name we've given to the C# model that represents an EDI transaction. In the EDI world, the format (or rule, or specification) of business documents (or transactions) is provided as some sort of a text or pdf file with diagrams and lists, like this:

x12 specification

We've gone a step further and turned all this information into a simple class that is annotated with our EDI attributes and follows the same principle as the Data Annotations in ASP.NET MVC or Entity Framework like this:

edi template

So, the most important concept of EdiFabric is a simple C# class, or model as in MVC, that inherits from our own EdiMessage and is comprised of properties annotated with our own EDI attributes.


Additional Information

Great, now that we have established that our EDI transactions are represented with simple C# classes, let's see what we can use them for.


How to Translate EDI Files

The main feature of EDI Tools for .NET C# Library is to translate EDI files into C# instances (or EDI Template C# POCOs) and to generate EDI files from C# instances (of the same EDI Templates C# POCOs). In other words, the library extends .NET Framework and .NET Core with extra functionality for EDI files and EDI transactions.

In order to translate (or parse, or read in this case) an EDI file using EDI Tools for .NET C# Library, you'll need the following:

  1. The EDI file itself - download sample X12 file
  2. The EDI template(s) for the transaction(s) in the EDI file - download sample X12 template
  3. The EdiFabric.Trial NuGet package - Download EDI Tools for .NET Trial

We'll use purchase order 850, version 4010 for the examples. It doesn't have to be an EDI file, the reader takes System.IO.Stream as an argument so any stream of EDI data can be parsed.

The act of translation is to go over the EDI file, identify each transaction or control segment and load the corresponding EDI Template, and finally parse the transaction data onto an instance of that EDI Template.

Let's assume that we want to translate the following file:

edi file

The parsing steps are:

  1. Identify the header control segments

    In this case, it's ISA and GS. All control segments are also represented by EDI Templates and are referenced from the EdiFabric.Core namespace. The information in the control segments is also used to determine the EDI delimiters (or separators) that must be used to parse the contents of the EDI interchange.

    X12 Control Segments Object Reference

    EDIFACT Control Segments Object Reference

    HL7 Control Segments Object Reference

    NCPDP Control Segments Object Reference

  2. Identify the transactions

    In this case, it's a single purchase order (850 as denoted in the ST segment) of version 4010 (as denoted in the GS segment), all marked in purple.

This means that the block of data between the ST and the SE segment will be transposed into an instance of the EDI Template class that represents purchase order, version 4010.

How does the framework work this out? In the general case, it does that by matching the values from the file to the values in the MessageAttribute that is applied to the EDI Template class:

[Message("X12", "004010", "850")]
public class TS850 : EdiMessage

So, to be able to translate EDI messages into C# instances, we need to know the C# classes for those instances beforehand.

It's a good practice to store all the templates for each EDI version in their separate project. Similarly, all partner-specific modifications of the standard templates should be moved into their own projects.

All EDI templates for a version share the same set of segment and data element classes, as well as EDI codes, and all of them implement common interfaces (for X12 and EDIFACT only). This allows you to implement any mapping logic over the interfaces, thus eliminating the duplication of the mapping code.

Let's get back to our example purchase order.


Code to parse EDI files

Create a new Console project following the Create a New Project from Scratch tutorial.

After you finished it, your code in Program.cs should look like the following:

Stream edi = File.OpenRead(@"C:\PurchaseOrder.txt");

List<IEdiItem> ediItems; using (var ediReader = new X12Reader(edi, "EdiFabric.Templates.X12")) ediItems = ediReader.ReadToEnd().ToList(); var purchaseOrders = ediItems.OfType<TS850>(); 

Change the path in File.OpenRead to the path of the sample purchase order file you downloaded earlier.

That's it, now run this in Debug mode and see the magic happen!


Example Code in GitHub for all EDI standards:


Inspect the code

What does the code do? Let's delve into the details.

  • The first line loads the EDI data from the sample file into a System.IO.Stream.
  • Then we declare a list of IEdiItem which will hold all of the control segments and transactions that the parser finds, in the order, they were found.
  • Next, we create an instance of the X12Reader and pass two arguments to it:
    • The stream of EDI data to parse
    • The assembly name of the project where the corresponding EDI template will be instantiated from
  • Finally, we call ReadToEnd(), which will read all the data in the sample file, from the beginning to the end


EDI reader main concepts

  • It's a stream-based, forward-only reader, similar to XmlReader.
  • All EDI items are presented in an ordered list, matching the order they appear in the file.
  • There are two reading modes - ReadToEnd and Read, the latter allowing you to stream EDI item by EDI item for large EDI files (> 2MB).
  • All read modes are provided in an async version as well.
  • The assembly name of a project can be found by right-clicking on the project name in Visual Studio and selecting Properties:

edi assembly name


Additional information:


How to Parse Large EDI Files

We briefly mentioned that there are two reading modes - ReadToEnd and Read, together with their async counterparts. The reason for the existence of the two is to allow you to either translate a file at once (and have all the EDI items in a list in memory) or to read only one EDI item at a time.

Sometimes EDI files contain batches of transactions, for historical or other reasons, mixed or uni-type, but in large volumes. Plowing through large files requires careful resource planning and efficient streaming, which we are going to demonstrate in this section.

Open the Program.cs file we created in the previous step and add the following code: 

Stream edi = File.OpenRead(@"C:\PurchaseOrder.txt");
using (var ediReader = new X12Reader(edi, "EdiFabric.Examples.X12.Templates.V4010"))
    while (ediReader.Read())
var po = ediReader.Item as TS850;
if (po != null)
} private static void ProcessPurchaseOrder(ISA isa, GS gs, TS850 purchaseOrder)
// Do something with the purchase order

Change the path in File.OpenRead to the path of the sample purchase order file you downloaded earlier.


Example Code in GitHub for all EDI standards:


Inspect the code

What does the code do? Loading the EDI file into a stream, and creating the X12Reader, are the same as the last example. The difference is in the reading mode:

  • Use Read() instead of ReadToEnd() in a while loop
  • Each iteration will return an EDI item, so for our sample file there will be 5 iterations with 5 EDI items returned:
    • ISA
    • GS
    • The only purchase order or 850
    • GE
    • IEA
  • The current item can be accessed by ediReader.Item where the type of the item determines which transaction or control segment it is
  • The items we are interested in can be processed (it's a good idea to offload that processing asynchronously or in a different thread) downstream and then disposed of as the file is being read.
  • Each current item holds references to its ISA (ediReader.CurrentInterchangeHeader) and GS (ediReader.CurrentGroupHeader) as well as the delimiters used (ediReader.Separators) and the offset of bytes from the start of the reading operation (ediReader.BytesRead)

Sometimes the transactions themselves are large and contain EDI loops that repeat multiple times (for example patient data for all patients in a hospital). In this situation, the streaming won't do much good and the transaction itself will need to be broken into parts. This is called splitting and you can learn more about it in Translate Large EDI messages by splitting.

Now that we've covered the EDI translation techniques, let's move on and do something useful with the EDI transaction C# instance.


What to do with EDI Template POCOs

The diagram below colorfully depicts the main operations:

edi net framework

As you can see, the EDI Template C# POCO (or POCO-like if we want to be precise because it does depend on our DOM attributes and base class, but let's not be overly meticulous) is at the center of all operations.

Once you have the POCO, either by reading an EDI file or by manually instantiating and populating it, you can immediately:

  • Write it out to an EDI file (or a stream for that matter)
  • Save it to a database using Microsoft Entity Framework
  • Validate it for the relevant EDI compliance, such as the HIPAA Snip Levels
  • Serialize it to JSON using Newtonsoft Json.NET
  • Generate acknowledgments such as 997 or 999 (that is on the whole interchange or group and not just the transaction)
  • Serialize it to XML using Microsoft XmlSerializer
  • Export it to CSV using custom code and file format
  • Map it to another POCO or domain object
  • Process it downstream to another application or service, etc.

As part of this tutorial, we'll demonstrate the first step and leave all the other steps to part two of this tutorial, EDI Tools for .NET Tutorial - Part 2.


How to Generate EDI Files

My trading partner wants me to send her EDI files, can I do that with EdiFabric? Does this sound familiar, or at least some of it? If yes, then read on.

Having learned about the EDI Templates, we can happily assume that if we can instantiate the correct EDI Template for the transaction and version we need, and populate it with data, we can then somehow turn it into an EDI file.

So, generating (or creating) an EDI file is a two-step process:

  1. Create an instance of the EDI Template and populate it
  2. Write the instance(s) to an EDI file (or stream)


Create an instance of the EDI Template and populate it

The data to go out to a trading partner usually originates in a domain entity, internal database, CSV file, XML output, or service response in JSON. Whatever the case, the data will need to be mapped to an EDI Template. There are multiple approaches to this; however, the topic of converting data structures from one to another is outside the scope of our discussion.

The general idea is to reuse the existing mapping pattern for all other, non-EDI, processes in your other (personal or work) projects and to apply it for EDI as well.

We'll use invoice, 810, version 4010 for the examples. Here are some instantiation\mapping ideas which might be useful pointers:

To recap: let's say that you need to send an EDI file to a trading partner that contains an invoice, 810 in version 4010, as a response to a previously received purchase order from that same trading partner.

You've pulled the invoice from your invoicing system in some format, and converted it to its corresponding EDI Template instance. That is, step 1 completed.


Write the instance(s) to an EDI file (or stream)

To create the destination EDI file, we'll use the EdiWriter. Once you have the file, you can transport it to the recipient; however, the communication part is not a feature of EdiFabric.

Create a new Console project following the Create a New Project from Scratch tutorial.

Open Program.cs and add the following code:

var transaction = BuildInvoice("1");

using (var stream = new MemoryStream())
    using (var writer = new X12Writer(stream))

    string edi = stream.LoadToString();


Example Code in GitHub for all EDI standards:


Inspect the code

The first line creates an invoice POCO by manually instantiating an 810, version 4010, and populating it with hard-coded data. In reality, this will be the end product of a mapping component\code\routine\deserialization\etc.


  • A new MemoryStream is created (it could be any stream really, such as FileStream, etc.). This is where all the EDI data will be written to
  • Next, an instance of the X12Writer is created, taking the stream as a parameter
  • Then, write to the stream beginning with the ISA segment:
public static ISA BuildIsa(string controlNumber, 
            string senderId = "SENDER1", 
            string senderQ = "14", 
            string receiverId = "RECEIVER1", 
            string receiverQ = "16", 
            string ackRequested = "1", 
            string testIndicator = "T")
	return new ISA
		//  Authorization Information Qualifier
		AuthorizationInformationQualifier_1 = "00",
		//  Authorization Information
		AuthorizationInformation_2 = "".PadRight(10),
		//  Security Information Qualifier
		SecurityInformationQualifier_3 = "00",
		//  Security Information
		SecurityInformation_4 = "".PadRight(10),
		//  Interchange ID Qualifier
		SenderIDQualifier_5 = senderQ,
		//  Interchange Sender
		InterchangeSenderID_6 = senderId.PadRight(15),
		//  Interchange ID Qualifier
		ReceiverIDQualifier_7 = receiverQ,
		//  Interchange Receiver
		InterchangeReceiverID_8 = receiverId.PadRight(15),
		//  Date
		InterchangeDate_9 = DateTime.Now.Date.ToString("yyMMdd"),
		//  Time
		InterchangeTime_10 = DateTime.Now.TimeOfDay.ToString("hhmm"),
		//  Standard identifier
		InterchangeControlStandardsIdentifier_11 = "U",
		//  Interchange Version ID
		//  This is the ISA version and not the transaction sets versions
		InterchangeControlVersionNumber_12 = "00204",
		//  Interchange Control Number
		InterchangeControlNumber_13 = controlNumber.PadLeft(9, '0'),
		//  Acknowledgment Requested (0 or 1)
		AcknowledgementRequested_14 = ackRequested,
		//  Test Indicator
		UsageIndicator_15 = testIndicator,
  • Followed by the GS segment:
public static GS BuildGs(string controlNumber, 
            string senderId = "SENDER1", 
            string receiverId = "RECEIVER1")
	return new GS
		//  Functional ID Code
		CodeIdentifyingInformationType_1 = "IN",
		//  Application Senders Code
		SenderIDCode_2 = senderId,
		//  Application Receivers Code
		ReceiverIDCode_3 = receiverId,
		//  Date
		Date_4 = DateTime.Now.Date.ToString("yyMMdd"),
		//  Time
		Time_5 = DateTime.Now.TimeOfDay.ToString("hhmm"),
		//  Group Control Number
		//  Must be unique to both partners for this interchange
		GroupControlNumber_6 = controlNumber.PadLeft(9, '0'),
		//  Responsible Agency Code
		TransactionTypeCode_7 = "X",
		//  Version/Release/Industry id code
		VersionAndRelease_8 = "004010"
  • Lastly, we write our invoice out

You don't need to close the group (write GE segment) or the interchange (write the IEA segment), the X12Writer does that automatically for you.

By default, the writer uses the standard separators. If you want to use different separators don't set it in the ISA object, but use the Separators object when writing the ISA out.

The stream now contains our EDI data and we can write it out to a file, turn it into a string or do anything else we want with it.


Additional information:


Next Steps

Congratulations! You've created code that translates EDI files and generates EDI files.

Nice work! We hope you now feel like you have a decent grasp on how EDI Tools for .NET works.

Throughout this tutorial, we touched on concepts including EDI Templates, parsing EDI files, and generating EDI files.

Check out the next part of this tutorial, EDI Tools for .NET Tutorial - Part 2, which covers the remainder of the features.

Share this:

Was this article helpful?



  • Comment author
    Andrew Kelly

    Hi. C# Novice here, do you have any syntax examples for accessing the values? Single and loop items. 


  • Comment author
    • Edited


    You can download the demo and open the SDK solution.  It contains many samples on how to parse or generate EDI, validation, etc.

    Also, take a look at the CodeLibrary.

    Single data elements are always strings. Loops are always List<string>. It's pretty straightforward.


Please sign in to leave a comment.