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


AltStyle によって変換されたページ (->オリジナル) /