Source code for the AS2 Server C# example program posted at EDIINT AS2.  A detailed explanation of the algorithm can be read at "An AS2 Server example".

namespace As2ServerNet
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

            if (!IsPostBack)
            {
                //Get Http header so that it can be included in the oMailDoc object during LoadContent
                string sHttpHeader = "";
                
                // Load ServerVariable collection into NameValueCollection object.
                NameValueCollection coll = Request.ServerVariables;
                // Get names of all keys into a string array. 
                String[] arr1 = coll.AllKeys;
                for (int i = 0; i < arr1.Length; i++)
                {
                    if (arr1[i].StartsWith("ALL_RAW"))
                    {
                        String[] arr2 = coll.GetValues(arr1[i]);
                        for (int ii = 0; ii < arr2.Length; ii++)
                        {
                            if (ii != 0)
                            {
                                sHttpHeader = sHttpHeader + "<br>";
                            }
                            sHttpHeader = sHttpHeader + arr1[i] + ": " + arr2[ii];
                        }
                    }
                }

                //saves AS2 message into a file.
                string uploadFileName = SaveAS2ToFile(Request, sHttpHeader);

                //processes the uploaded AS2 message, and then replies back an MDN syncronously or asyncronously
                string MDNResult = ProcMDN(uploadFileName, sHttpHeader);
            }
        }

        protected string SaveAS2ToFile(HttpRequest Request, string sHttpHeader)
        {
            if (!IsPostBack)
            {
                try
                {
                    //path of where the received AS2 message will be saved
                    string uploadFileName = ConfigurationManager.AppSettings["uploadDirectory"] + "\\" + Session.SessionID.Trim() + ".bin";

                    //read the stream of the file that is beig uploaded.  Note that the stream does not include headers.
                    BinaryReader reader = new BinaryReader(Request.InputStream);

                    //save the stream to a file
                    if (reader != null)
                    {
                        FileStream fsAs2 = new FileStream(uploadFileName, FileMode.Create, FileAccess.Write);
                        BinaryWriter writerAs2 = new BinaryWriter(fsAs2);

                        int buffSize = 512;
                        bool done = false;
                        byte[] bits = new byte[buffSize];

                        while (!done)
                        {
                            bits = reader.ReadBytes(buffSize);
                            if (bits.Length == 0)
                            {
                                done = true;
                            }
                            else
                            {
                                writerAs2.Write(bits);
                            }
                        }
                        writerAs2.Close();
                        reader.Close();
                        fsAs2.Close();
                        writerAs2.Dispose();
                        reader.Dispose();
                        fsAs2.Dispose();
                    }
                    
                    // save headers to a file (not necessary, but useful for troubleshooting)
                    if (sHttpHeader != "")
                    {
                        string uploadFileNameHeader = ConfigurationManager.AppSettings["uploadDirectory"] + "\\" + Session.SessionID.Trim() + ".hdr.txt";
                        StreamWriter oWriter;

                        oWriter = new StreamWriter(uploadFileNameHeader);
                        oWriter.Write(sHttpHeader);
                        oWriter.Close();
                        oWriter.Dispose();
                    }
                    
                    return uploadFileName;
                }
                finally
                {
                }

            }
            else
            {
                return "";
            }
        }
        protected string ProcMDN(string AS2FileName, string sHttpHeader)
        {
            if (!IsPostBack)
            {
                //Get path of app
                string sPath = AppDomain.CurrentDomain.BaseDirectory;

                //path where MDN and log files are saved
                string sSaveFilePath = ConfigurationManager.AppSettings["processDirectory"] + "\\" + Session.SessionID.Trim();

                //instantiate oEdiDoc
                ediDocument oEdiDoc = new ediDocument();

                //full path to log FREDI component internal execution
                oEdiDoc.set_Property(DocumentPropertyIDConstants.Property_Execution_Log, sSaveFilePath + "_log.txt");

                //Use certificates in Machine Key Sets Certificate Store.  Enable this when certificates are installed on servers. 
                oEdiDoc.set_Option(DocumentOptionIDConstants.OptDocument_MachineKeySet, 1);

                //set cursor type to forward only
                oEdiDoc.CursorType = DocumentCursorTypeConstants.Cursor_ForwardOnly;

                //security settings. Use the eSecurity Console Utility to view where the certificates are located.
                ediSecurities oSecurities = oEdiDoc.GetSecurities();
                oSecurities.DefaultProviderName = "Microsoft Strong Cryptographic Provider";
                oSecurities.DefaultCertSystemStoreLocation = "LocalMachine"; //certificates installed on servers are located in LocalMachine; workstations are located in CurrentUser
                oSecurities.DefaultCertSystemStoreName = "My";
                oSecurities.DefaultKeyContainer = "test_cert_key";  

                //Disable internal standard reference library
                ediSchemas oSchemas = oEdiDoc.GetSchemas();
                oSchemas.EnableStandardReference = false;

                // Load into RAM only the SEF file that is being used
                oSchemas.set_Option(SchemasOptionIDConstants.OptSchemas_SetOnDemand, 1);

                //instantiate oMailDoc
                mailDocument oMailDoc = oEdiDoc.GetMailDocument();

                // RFC4130. The address in the "Disposition-Notification-To" is not used to identify where to 
                //   return the MDN.  Receiving applications MUST ignore the value and MUST not complain about 
                //   RFC 2822 address syntax violations.  For AS2, this field is redefined as generic text so that
                //   any string is accepted.
                oMailDoc.AddDefinedHeader("Disposition-Notification-To", MailMessageHeaderTypeConstants.HeaderType_FieldText, RequirementTypeConstants.Requirement_Optional);
                //oMailDoc.AddDefinedHeader("Receipt-delivery-option", MailMessageHeaderTypeConstants.HeaderType_FieldText, RequirementTypeConstants.Requirement_Optional);
                oMailDoc.AddDefinedHeader("Message-ID", MailMessageHeaderTypeConstants.HeaderType_FieldText, RequirementTypeConstants.Requirement_Mandatory);
                oMailDoc.AddDefinedHeader("Original-Message-ID", MailMessageHeaderTypeConstants.HeaderType_FieldText, RequirementTypeConstants.Requirement_Mandatory);
                //oMailDoc.AddDefinedHeader("Cookie", MailMessageHeaderTypeConstants.HeaderType_FieldText, RequirementTypeConstants.Requirement_Optional)

                ////change default properties of boundaries
                //oMailDoc.set_Property(MailDocPropertyIDConstants.MailDocProp_Boundary, "CompanyX.Electronic.Document.Boundary");
                //oMailDoc.set_Property(MailDocPropertyIDConstants.MailDocProp_BoundaryMdn, "CompanyX.Electronic.Document.Boundary.mdn");
                //oMailDoc.set_Property(MailDocPropertyIDConstants.MailDocProp_BoundarySign, "CompanyX.Electronic.Document.Boundary.sign");

                mailMessage oMDN = oMailDoc.GetMDN();

                //you can add your own MDN headers at this time
                //oMDN.set_HeaderFieldValue("Received-Content-MIC", " ");
                //oMDN.set_HeaderFieldValue("Final-Receipient", "1234");

                //certificate for signing MDN
                ediSecurity oMdnSecurity = oMDN.GetSecurity();
                oMdnSecurity.CertificateSignerName = "as2_test_cert";     

                // Prevent any processing at this point.  Just load the raw document.
                oMailDoc.set_Option(MailDocOptionIDConstants.MailDocOpt_Auto, 0);

                //This option means not to process the EDI file in the content when the process method is called. We only 
                // want to process the mail document upto a point where we can determine the content type.
                oMailDoc.set_Option(MailDocOptionIDConstants.MailDocOpt_EnableEdi, 0);

                // Use certificates in the cretificate store only. (Not in files.) Must enable this to verify signed messages.
                oMailDoc.set_Option(MailDocOptionIDConstants.MailDocOpt_UseCertStoreOnly, 1);

                // Load the mail file that was just received from the client.  If the client had requested that an MDN be generated then 
                // the MDN is also generated internally at this point.
                //Load the http headers with the As2 file
                if (oMailDoc.LoadContent(AS2FileName, sHttpHeader) != 1)
                {
                    // "Failed to load AS2"
                }
                else
                {
                    //Saving the mail document at this point is not necessary, but is saved for troubleshooting if need be.
                    oMailDoc.Save(sSaveFilePath + "_MailDoc.bin");

                    mailMessage oMessage = oMailDoc.GetMessageContent();

                    // Obtain the values from the message headers before the document is processed because they may not exist after.
                    
                    // Check to see if there is a value in the header 'Receipt-Delivery-Option', and if there is then this is an asynchronous session.
                    string sReceiptDeliveryOption = oMessage.get_HeaderFieldValue("Receipt-delivery-option");
                    mailInternetURI oReceiptURI = oMessage.GetHeaderTypeURI("Receipt-delivery-option");

                    //ediSecurity oMsgSecurity = oMessage.GetSecurity();
                    //oMsgSecurity.ProviderName = "Microsoft Strong Cryptographic Provider";
                    //oMsgSecurity.DefaultCertSystemStoreLocation = "LocalMachine"; //'certificates installed on servers are located in LocalMachine; workstations are located in CurrentUser
                    //oMsgSecurity.DefaultCertSystemStoreName = "My";

                    //// The component automatically detects what algorithm was used to encrypt the message and uses the same algorithm to decrypt the it.
                    //// If you wish to know what algorithm was used to encrypt the message, then call the DecryptAlgorithm method.
                    //ediSecurity oMsgSecurity = oMessage.GetSecurity();
                    //ediSecurityEncryptionCfg oSecurityEncryptionCfg = oMsgSecurity.GetEncryptionConfig();
                    //string sCfgDecryptAlgorithm = oSecurityEncryptionCfg.DecryptAlgorithm;
                    //string sDecryptAlgorithm = oMsgSecurity.DecryptAlgorithm;
                    //string sSignDigest = oMsgSecurity.GetSignDigest(EncodingMechanismTypeConstants.EncodeType_Base64);

                    // It's not necessary to process in steps, but good for troubleshooting.  To process in steps, use the ProcessStep method.
                    string sContentTransferEncoding = oMessage.get_HeaderFieldValue("Content-Transfer-Encoding").ToLower();
                    // If the file was encoded in base64, this step will decode it only.
                    if (sContentTransferEncoding == "base64")
                    {
                        oMessage.ProcessStep();
                        oMessage.Save(sSaveFilePath + "_MessageAfterBase64Process.bin");
                    }

                    sContentTransferEncoding = oMessage.get_HeaderFieldValue("Content-Transfer-Encoding").ToLower();
                    // If the file was encrypted, this step will decrypt it only.
                    if (sContentTransferEncoding == "binary")
                    {
                        oMessage.ProcessStep();
                        oMessage.Save(sSaveFilePath + "_MessageAfterBinaryProcessProcess.bin");
                    }
                    
                    // Do all other processes to get to the Content Type of the file.
                    oMailDoc.Process();
                    oMailDoc.Save(sSaveFilePath + "_ContentType.bin");

                    //Get body from message so that we can extract the file from it.
                    mailBody oMailBody = oMessage.GetBody();

                    //Get the content type of the EDI message so that it can be processed appropriately
                    string sTypeMessage = oMessage.get_HeaderFieldValue("Content-Type");

                    if (sTypeMessage.ToLower() == "application/edi-x12") //EDI is X12
                    {

                        //Export the EDI part of the message into a file
                        oMailBody.Export(sSaveFilePath + ".X12");

                        //Load all pertaining X12 SEF files here. 
                        oEdiDoc.LoadSchema(sPath + "SEF/sample_850_X12-4010.SEF", SchemaTypeIDConstants.Schema_Standard_Exchange_Format);
                        oEdiDoc.LoadSchema(sPath + "SEF/sample_837_X098.SEF", SchemaTypeIDConstants.Schema_Standard_Exchange_Format);
                    }

                    else if (sTypeMessage.ToLower() == "application/edifact") //EDI is EDIFACT
                    {

                        //Export the EDI part of the message into a file
                        oMailBody.Export(sSaveFilePath + ".edi");

                        //UNA segment allowed
                        oEdiDoc.set_Option(DocumentOptionIDConstants.OptDocument_ServiceSegment, 1);

                        //Load all pertaining EDIFACT SEF files here. 
                        oEdiDoc.LoadSchema(sPath + "SEF/sample_ORDERS_S93A.SEF", SchemaTypeIDConstants.Schema_Standard_Exchange_Format);
                    }

                    else if (sTypeMessage.ToLower() == "application/xml")    //XML
                    {

                        //Export the XML part of the message into a file
                        oMailBody.Export(sSaveFilePath + ".xml.txt");
                    }

                    else    //unknown
                    {
                        //Export the body part of the message into a file
                        oMailBody.Export(sSaveFilePath + ".stream.bin");
                    }


                    if (!sReceiptDeliveryOption.Equals("")) // SEND MDN ASYNCHRONOUSLY  
                    {

                        // Disconnect the client connection because it is not needed in an asyncronous MDN request while server continues to process 
                        // the received AS2 message, and then send back an MDN with a new connection.

                        Response.Flush();
                        Response.Close();

                        string sMdnTempFile;
                        string sHttpResponse;

                        // Enable the EDI process and everything else (auto) in the next Process method.
                        // These options are not necessary if you don't want to include the EDI validation results
                        // in the MDN
                        oMailDoc.set_Option(MailDocOptionIDConstants.MailDocOpt_EnableEdi, 1);
                        oMailDoc.set_Option(MailDocOptionIDConstants.MailDocOpt_Auto, 1);

                        if (oMailDoc.Process() != 1)
                        {
                            //Failed to process
                        }
                        else
                        {
                            ediTransports oTransports = oMailDoc.GetMdnTransports();
                            ediTransport oTransport = oTransports.CreateTransport();

                            //Get a unique temp file
                            ediFileSystem oFileSystem = oEdiDoc.GetFileSystem();
                            sMdnTempFile = oFileSystem.CreateTempFile("");

                            // Because the cursor type was set to forward only, we have to iterate thru each segment of the EDI file so that they can 
                            // be validated.  This is not necessary if you do not wish to include the validation results in the MDN.
                            ediDataSegment oSegment = oEdiDoc.FirstDataSegment;
                            while (oSegment != null)
                            {
                                ediDataSegment.Set(ref oSegment, oEdiDoc.NextDataSegment);

                            } //while (oSegment != null)

                            // Refresh the MDN to include the result of the EDI validation
                            if (oMailDoc.RefreshMDN() != 1)
                            {
                                // "MDN failed to refresh"
                            }
                            else
                            {
                                if (oMDN.Save(sSaveFilePath + ".mdn1.async.bin") != 1)
                                {
                                    //failed to save MDN file
                                }
                                else
                                {
                                    string sTimeStamp = (DateTime.Now.ToString("yyMMddhhmm"));
                                    string sAsyncSchema = oReceiptURI.SchemeName.Trim().ToUpper();
                                    string sAsyncHost = oReceiptURI.HostName;
                                    string sAsyncUserInfo = oReceiptURI.UserInfo;
                                    string sAsyncUrlPath = oReceiptURI.UrlPath;
                                    string sAsyncPort = oReceiptURI.Port.ToString();
                                    string sAsyncValue = oReceiptURI.Value;  //oMessage.HeaderFieldValue("Receipt-Delivery-Option")

                                    //Send the MDN back to the sender using the scheme and address
                                    //specified in the header 'Receipt-Delivery-Option'

                                    if (sAsyncSchema == "HTTP")
                                    {
                                        oTransport.SetHTTP();
                                        oTransport.InternetUrl = sAsyncValue.Trim() + "/";
                                        ediHttpCfg oHttpCfg = oTransport.GetHttpCfg();
                                        oHttpCfg.SendVerb = "POST";
                                        oHttpCfg.EnableProcessResponse = false;
                                        try
                                        {
                                            oTransport.SendFile(sSaveFilePath + ".mdn1.async.bin");
                                            sHttpResponse = oTransport.LastResponseInfo;
                                            //if (oTransport.Send(sTimeStamp + ".mdn1.async.bin") != 1)
                                            //{ }
                                            //else
                                            //{ }
                                        }
                                        finally
                                        {
                                        }
                                        oHttpCfg.Dispose();
                                    }

                                    else if (sAsyncSchema == "HTTPS")
                                    {
                                        oTransport.SetHTTPS();
                                        oTransport.InternetUrl = sAsyncValue.Trim() + "/";
                                        ediHttpCfg oHttpCfg = oTransport.GetHttpCfg();
                                        oHttpCfg.SendVerb = "POST";
                                        oHttpCfg.EnableProcessResponse = false;
                                        try
                                        {
                                            oTransport.SendFile(sSaveFilePath + ".mdn1.async.bin");
                                            sHttpResponse = oTransport.LastResponseInfo;
                                            //if (oTransport.Send(sTimeStamp + ".mdn1.async.bin") != 1)
                                            //{ }
                                            //else
                                            //{ }
                                        }
                                        finally
                                        {
                                        }
                                        oHttpCfg.Dispose();
                                    }

                                    else if (sAsyncSchema == "FTP")
                                    {
                                        oTransport.SetFTP();
                                        oTransport.Address = sAsyncHost;
                                        oTransport.TargetPath = sAsyncUrlPath;
                                        oTransport.ServerPort = Convert.ToInt16(sAsyncPort);
                                        //if (oTransport.Send(sTimeStamp + ".mdn1.async.bin") != 1)
                                        //{ }
                                        //else
                                        //{ }
                                    }

                                    else if (sAsyncSchema == "MAILTO")
                                    {
                                        oTransport.SetSMTP();
                                        ediSmtpCfg oSmtpCfg = oTransport.GetSmtpCfg();
                                        oSmtpCfg.ServerName = "smtp.comp.domain.com";
                                        oSmtpCfg.User = "userid";
                                        oSmtpCfg.Password = "password";
                                        oSmtpCfg.AddTo(sAsyncUserInfo);
                                        oSmtpCfg.From = "support@domain.com";
                                        oSmtpCfg.FromDisplay = "FrameworkEDI Interoperability test";
                                        oSmtpCfg.Subject = "Interoperability Test Document";
                                        oSmtpCfg.MessageText = "Please find attached text document";
                                        //if (oTransport.Send(sTimeStamp + ".mdn1.async.bin") != 1)
                                        //{}
                                        //else
                                        //{}
                                        oSmtpCfg.Dispose();

                                    } //sAsyncSchema

                                } //if (oMDN.Save
                                
                            }  // if (oMailDoc.RefreshMDN

                            oFileSystem.Dispose();
                            oTransport.Dispose();
                            oTransports.Dispose();

                        } // if (oMailDoc.Process()
                        
                    }
                    else //SEND MDN SYNCHRONOUSLY 
                    {


                        // Enable the EDI process and everything else (auto) in the next Process method.
                        // These options are not necessary if you don't want to include the EDI validation results
                        // in the MDN
                        oMailDoc.set_Option(MailDocOptionIDConstants.MailDocOpt_EnableEdi, 1);
                        oMailDoc.set_Option(MailDocOptionIDConstants.MailDocOpt_Auto, 1);

                        if (oMailDoc.Process() != 1)
                        {
                            //Failed to process
                        }
                        else
                        {
                            // Save MDN to file. This is not necessary because the transport object sends the mdn from the content of 
                            // the object (and not from the file)
                            oMDN.Save(sSaveFilePath + ".mdn1.bin");

                            // Because the cursor type was set to forward only, we have to iterate thru each segment of the EDI file so that they can 
                            // be validated.  This is not necessary if you do not wish to include the validation results in the MDN.

                            ediDataSegment oSegment = oEdiDoc.FirstDataSegment;
                            while (oSegment != null)
                            {
                                ediDataSegment.Set(ref oSegment, oEdiDoc.NextDataSegment);

                            } //while (oSegment != null)

                            // Refresh the MDN to include the result of the EDI validation
                            if (oMailDoc.RefreshMDN() != 1)
                            {
                                // "MDN failed to refresh"
                            }
                            else
                            {
                                oMDN.Save(sSaveFilePath + ".mdn2.bin");

                                //You can still add and edit the header of an MDN at this point, but not the message.
                                //oMDN.set_HeaderFieldValue("AS2-Version", "1.0");
                                //oMDN.set_HeaderFieldValue("Message-ID", "12345demo@companyX.com");

                                
                                mailHeaders oHeaders = oMDN.GetHeaders();

                                //add the headers of the MDN file into the http headers
                                mailHeader oHeader = null;
                                for (int i = 1; i <= oHeaders.Count; i++)
                                {
                                    mailHeader.Set(ref oHeader, oHeaders.GetHeaderByIndex(i));
                                    Response.AddHeader(oHeader.Name, oHeader.Value);
                                }

                                mailMessages oMdnMsgs = new mailMessages();

                                // Get the MDN message only (not the headers) because the headers will automatically be included when the MDN is sent.
                                oMdnMsgs = oMDN.GetMessages();

                                //save the message to a file so that we can read it back as binary
                                oMdnMsgs.Export(sSaveFilePath + ".msgs.mdn");

                                
                                FileStream oMdnFs = new FileStream(sSaveFilePath + ".msgs.mdn", FileMode.Open);
                                BinaryReader oMdnReader = new BinaryReader(oMdnFs);

                                //read the generated .msgs.mdn file and write it back to the response stream
                                int buffSize = 512;
                                bool done = false;
                                byte[] bits = new byte[buffSize];

                                while (!done)
                                {
                                    bits = oMdnReader.ReadBytes(buffSize);
                                    if (bits.Length == 0)
                                    {
                                        done = true;
                                    }
                                    else
                                    {
                                        Response.BinaryWrite(bits);
                                    }
                                }

                                oMdnReader.Close();
                                oMdnFs.Close();
                                oMdnReader.Dispose();
                                oMdnFs.Dispose();
                                oMdnMsgs.Dispose();
                                oHeaders.Dispose();

                            } //oMailDoc.RefreshMDN() <> 1

                        } //oMailDoc.Process()

                    }  //url MDN synchronously

                    oMailBody.Dispose();
                    //oMsgSecurity.Dispose();
                    oReceiptURI.Dispose();
                    oMessage.Dispose();

                } //oMailDoc.Load(AS2FileName) <> 1

                oMdnSecurity.Dispose();
                oMDN.Dispose();
                oMailDoc.Dispose();
                oSchemas.Dispose();
                oSecurities.Dispose();
                oEdiDoc.Dispose();

            } // if (!IsPostBack)

            return "";
        }
    }
}

    Click here to download a trial version of the Framework EDI