Creating an AS2 Client in Stages.
This page will describe how to create an AS2 client in C# with the Framework EDI component in steps - starting with the simplest that sends a plain AS2 message to something that sends an encrypted, signed message with a request for a signed MDN.
- Plain AS2 message with no request for an MDN
- Plain AS2 message with request for an MDN
- Encrypted AS2 message with request for an MDN
- Encrypted and Signed AS2 message with request for an MDN
- Encrypted and Signed AS2 message with request for a signed MDN
Plain AS2 message with no request for an MDN
First we need to instantiate an object for the AS2 document. We do that by doing the following:
oMailDoc = oEdiDoc.GetMailDocument();
We would also need an object for the message itself
oMailSubject = oMailDoc.GetMessageContent();
Next we need to add headers to identify this message, its sender and where it's going to,
oMailSubject.set_HeaderFieldValue("Message-ID", "1234567890@evalusercompany.com");
oMailSubject.set_HeaderFieldValue("AS2-Version", "1.0");
oMailSubject.set_HeaderFieldValue("AS2-From", "FromCompanyXYZ");
oMailSubject.set_HeaderFieldValue("AS2-To", "ToCompanyABC");
We also need to add a header to describe the content of the message. In this case, we are sending an EDI X12 file so we'll use the predefined code for EDI X12 in our "Content Type" header.
oMailSubject.set_HeaderFieldValue("Content-Type", "Application/EDI-X12");
We insert the EDI file into our message by calling the Import method
oMailSubject.Import(sPath + "ediFile.X12");
At this point we are done constructing our AS2 message so we can save it to a file
oMailDoc.Save(sPath + @"\MailFolder\AS2PlainText.bin");
We can then send the file by http.
TransmitFileByHttp(ref oMailDoc, "AS2PlainText.bin");
Below is the code for the procedure TransmitFileByHttp
private void TransmitFileByHttp(ref mailDocument oMailDoc, string sFile)
{
ediTransports oTransports = oMailDoc.GetTransports();
ediTransport oTransport = oTransports.CreateTransport();
oTransport.SetHTTP();
oTransport.InternetUrl = "http://domain.com:9999/As2ServerNet/As2Server.aspx/";
oTransport.TimeOut = 7200;
ediHttpCfg oHttpCfg = oTransport.GetHttpCfg();
oHttpCfg.SendVerb = "POST";
oHttpCfg.EnableProcessResponse = true;
oTransport.Send(sPath + @"\MailFolder\" + sFile);
}
Click here to evaluate a sample plain AS2 message with no request for an MDN
Plain AS2 message with request for an MDN
To add a request for MDN acknowledgment in our AS2 message. We simply add the header "Disposition-Notification-To".
For asynchronous, we do the following:
oMailSubject.set_HeaderFieldValue("Receipt-delivery-option", "http://domain.com:9999/testsite/AsyncMDN/");
To add the Disposition header requesting for a synchronous MDN, we do the following:
oMailSubject.set_HeaderFieldValue("Disposition-Notification-To", "<NoValue@NoValuecompany.com>");
Note that a value must be present for requesting a synchronous MDN, but holds no meaning in an AS2 environment.
Asynchronous means that the MDN is sent using a different connection (not the same connection that was used for sending the AS2 message). Therefore, you must provide a valid address where the MDN can be sent.
To read the MDN that was received asynchronously, you would have to import the MDN file into a mail message object.
mailMessage oMDN = new mailMessage();
oMDN.Import(sPath + @"MailFolder\Received_MDN.bin");
ReadMdnMessage(ref oMDN);
On the other hand, synchronous connection means that the MDN is received using the same connection. Therefore, the connection is not broken after the AS2 message is sent, but it stays open until the MDN is received. In the Framework EDI component, the MDN that is received synchronously can be obtained from the AS2 mailMessage object using the GetMDN method.
mailMessage oMDN = oMailDoc.GetMDN();
oMDN.Save(sPath + @"MailFolder\Received_MDN.bin");
ReadMdnMessage(ref oMDN);
Click here to evaluate a sample plain AS2 message with request for an MDN
Encrypted AS2 message with request for an MDN
To encrypt an AS2 message, we would first have to configure its security object.
ediSecurity oSecurity = oMailSubject.GetSecurity();
oSecurity.EncryptionAlgorithm = "3DES";
oSecurity.AssuranceAlgorithm = "SHA-1";
We also need to load our trading partner's public key certificate
oSecurity.SetCertSubjectNameByLocation("Partner_Cert", "CurrentUser", "My", "Microsoft Strong Cryptographic Provider");
To enable encryption, set the property to true.
oSecurity.EnableEncryption = true;
Actual encryption happens at the Prepare method
oMailSubject.Prepare();
In an AS2 document, the entire document is not encrypted, but only the message content, which consists of the "Content-Type" header and the EDI X12 file. So the following lines should remain before the oMailSubject.Prepare() method.
oMailSubject.set_HeaderFieldValue("Content-Type", "Application/EDI-X12");
oMailSubject.Import(sPath + "ediFile.X12");
The other headers have to be moved after the Prepare method so that they do not get encrypted
oMailSubject.set_HeaderFieldValue("Message-ID", "1234567890@evalusercompany.com");
oMailSubject.set_HeaderFieldValue("AS2-Version", "1.0");
oMailSubject.set_HeaderFieldValue("AS2-From", "FromCompanyXYZ");
oMailSubject.set_HeaderFieldValue("AS2-To", "ToCompanyABC");
Click here to evaluate a sample encrypted AS2 message with request for an MDN
Encrypted and Signed AS2 message with request for an MDN
To sign an AS2 message, we have to provide our private key security certificate location to the ediSecurity object. Private keys are used of signing and decrypting files.
oSecurity.SetCertSignerNameByLocation("MyCert", "CurrentUser", "My", "Microsoft Strong Cryptographic Provider");
Next we enable the Assurance property of our ediSecurity objet.
oSecurity.EnableAssurance = true;
To give us assurance that our message was not changed during transmission, we calculate the MIC (Message Integrity Check) of the message before we send it.
txtMIC.Text = oMailSubject.GenerateDigest(MailMessagePartTypeConstants.Message_All, EncodingMechanismTypeConstants.EncodeType_Base64);
We can then request for a signed MDN, and then compare this MIC value to the value of the MIC returned in the MDN. If the MIC values are not the same then the message was compromised during transmission.
Click here to evaluate a sample encrypted, signed AS2 message with request for an MDN
Encrypted and Signed AS2 message with request for a signed MDN
To request for a signed MDN, we have to add a "Disposition-Notification-Options" header with the algorithm parameter that's to be used for the signed receipt
sDnOpts = "signed-receipt-protocol=optional,pkcs7-signature;";
sDnOpts = sDnOpts + "signed-receipt-micalg=optional,sha1";
oMailSubject.set_HeaderFieldValue("Disposition-Notification-Options", sDnOpts);
Click here to evaluate a sample encrypted, signed AS2 message with request for a signed MDN
To read the MIC value in the MDN, we first obtain the message content from the MDN object:
mailMessages oMdnMsgs = oMDN.GetMessages();
mailMessage oMdnMsg = oMdnMsgs.GetMessageContent(i);
mailContentType oContentType = oMdnMsg.GetContentType();
mailMessages oSubMessages = oMdnMsg.GetMessages(); mailMessage oDisposition = oSubMessages.GetMessageContent(1);
Then find the header "Received-Content-MIC", and then obtain its value.
mailHeaders oHeaders = oDisposition.GetHeaders();
mailHeader oHeader = oHeaders.GetHeaderByIndex(i);
if (oHeader.Name == "Received-Content-MIC") {
sRecvMicFldValue = oHeader.Value;
Finally, you can compare this MIC value in the signed MDN (sRecvMicFldValue) with the MIC value that was calculated before the signed AS2 message was sent (txtMIC.Text) to see if the received message had changed.
if (sMicValue != txtMIC.Text)
{
MessageBox.Show("Recipient received invalid document. Subject MIC=" + txtMIC.Text + ", Recv MIC=" + sMicValue);
}
Click here to evaluate a sample unsigned MDN
Click here to evaluate a sample signed MDN
View source code that reads a signed MDN
To download the complete program, please click on As2_Steps.zip.
For more AS2 examples, click here.
Click here to evaluate the Framework EDI