This project has moved. For the latest updates, please go here.

Deserializing into messages

Oct 28, 2013 at 3:41 PM
Hi,

I did a reference to the 997 class and I parsed an envelope with multiple messages.
I would like to serialize the 997 objects.

I tried several things but I don't know what to do now.
What am I missing?

Thanks.
-JLuc
            foreach (XElement xMessage in group.MESSAGES)
            {
                EdiFabric.Definitions.X12_004010_997.M_997 result;
                var serializer = new XmlSerializer(typeof(EdiFabric.Definitions.X12_004010_997.M_997));
                result = (EdiFabric.Definitions.X12_004010_997.M_997)serializer.Deserialize(xMessage.CreateReader());
            }
Nov 4, 2013 at 5:29 PM
I serialize with the EdiParser, make sure you have the XSD for your 997 as embedded resource in the Definitions.DLL and be careful of the namespaces.

Took me awhile to get everything in the right spots, but it's works great one you do.

HTH Mike

using EdiFabric.Framework.InterchangeEnvelopes.X12;
using EdiFabric.Framework.Parsers;
using EdiFabric.Framework.Exceptions;

private INTERCHANGE interchange = new INTERCHANGE();

           public void SaveEDI(string filename, string SegmentTerminator = null)
           {
               IEdiParser ediParser = new EdiParser();
                var interchangeContext = new EdiFabric.Framework.Entities.InterchangeContext();

               var parsedXml = ediParser.ToEdi(interchange, null , interchangeContext);
               using (TextWriter tw = File.CreateText(filename))
               {
                   tw.Write(string.Join(SegmentTerminator, parsedXml));
               }
           }
Nov 4, 2013 at 7:55 PM
I've added a test application that I was working on prior to writing my current software

I've buried it under patches since it's the only place on codeplex I can upload.

http://edifabric.codeplex.com/SourceControl/list/patches

Hope it Helps
Mike
Coordinator
Nov 7, 2013 at 1:56 PM
Hi JLuc,

You can do it like:

foreach (XElement xMessage in group.MESSAGES)
{
        var serializer = new XmlSerializer(typeof(M_997), "www.edifabric.com/x12");
        var deserialized997 = (M_997)serializer.Deserialize(xMessage.CreateReader());
}

or create a helper deserialization method and call it:

public static T Deserialize<T>(XElement xml, string nameSpace)
    {
        var serializer = new XmlSerializer(typeof(T), nameSpace);
        return (T)serializer.Deserialize(xml.CreateReader());
    }
foreach (XElement xMessage in group.MESSAGES)
{
         var deserialized997 = Deserialize<M_997>(xMessage, "www.edifabric.com/x12");
}

Cheers,
Kamen
Dec 19, 2013 at 11:32 AM
Hi,

When you guys talk about embedding the schema files in the Definitions.DLL project, should this be done regardless of the message types I want to use?

For example, if I want to work with INSDES messages, I have to embbed the corresponding xsd file in the Definition project in order to use?
I've been using it as a regular xsd file in the target project.
Dec 30, 2013 at 1:36 PM
Edited Dec 30, 2013 at 5:18 PM
Although not completely related I've decided to post this question here:

How can I build and OSTRPT message directly, without serializing my DB data/objects and then deserializing it into a message?

Is it possible to just "grab" the values I want to write to a file in the following format:?
UNA:+.? '
UNB+UNOC:3+codigo emissor:14+codigo receptor:14+data:hora+IDMensagem'
UNH+IDMensagem2+OSTRPT:D:98A:UN'
BGM+80E+numero do documento+9'
DTM+137:data documento:102'
NAD+SU+5600000768143::9'
NAD+DP+codigo interno recebedor::91'
NAD+LSP+codigo operador logistico::91'
DOC+1+referencia insdes'
DTM+9:data insdes:102'
LIN+1'
PIA+5+codigo interno:SA'
PIA+1+numero do lote:BP'
QTY+128:quantidade de picking efectuada:unidade picking'
DTM+361:data validade lote:102'
UNT+total segmentos+IDMensagem2'
UNZ+1+IDMensagem'
I did a little experiment of writing a tiny portion of code to write just the BGM and see if it would write in the specified format but all I'm writing to the file is the field value (as I expected it would) instead of the whole BGM field.
Here is the sample:
    Public Sub buildReplyTest(ByVal bgm As String)

        Dim file_name As String = "C:\Users\primeiro.ultimo\Desktop\test_ostrpt.txt"
        Dim file As New StreamWriter(file_name, True)

        Dim ost As Edifact_D98A_OSTRPT.S_BGM = New Edifact_D98A_OSTRPT.S_BGM
        ost.C_C002.D_1001_1 = bgm
        file.WriteLine(ost.C_C002.D_1001_1.ToString())
        file.Close()

    End Sub
What is the correct way? To serialize everything and the deserialize into and OSTRPT message?


### UPDATE ###
Okay, after looking at some sample code from mpisano and, correct me if I'm wrong, but it seems that transforming data into Xml is a necessary intermediary step either from EDI to DB or from DB to EDI..
So, after looking at the code, I've updated my code a bit and came up with this:
    Public Sub buildReply(ByVal bgm As XElement)

        Dim file_name As String = "C:\Users\primeiro.ultimo\Desktop\test_ostrpt.txt"
        'Dim file As New StreamWriter(file_name, True)
        'Dim file As File = Nothing

        Dim parser As IEdiParser = New EdiParser()

        Dim group As GROUP = New GROUP()
        group.MESSAGES = New List(Of XElement)


        Dim interchange As INTERCHANGE = New INTERCHANGE()
        interchange.GROUPS = New List(Of GROUP)()
        interchange.S_UNB = New S_UNB()
        interchange.S_UNZ = New S_UNZ()

        group.MESSAGES.Add(bgm)

        interchange.GROUPS.Add(group)
        Dim parsedXml As XElement = parser.Serialize(interchange)

        Dim tw As TextWriter = File.CreateText(file_name)
        tw.Write(parsedXml)

        tw.Close()
    End Sub
Now this outputs this file:
<INTERCHANGE xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="www.edifabric.com/edifact">
  <S_UNB />
  <GROUPS>
    <GROUP>
      <MESSAGES>
        <MESSAGE>
          <D_1004_1>45339734</D_1004_1>
        </MESSAGE>
      </MESSAGES>
    </GROUP>
  </GROUPS>
  <S_UNZ />
</INTERCHANGE>
I've noticed, compared to the INSDES xml message that after <MESSAGE> I should have <M_OSTRPT> and only then (after UNH) have the <S_BGM>.

How can I achieve this? I've been unable to find a way to add a M_OSTRPT to GROUPS or MESSAGES..

A Little help please?

Best Regards,
Celso Santos
Coordinator
Dec 31, 2013 at 8:29 AM
Hi Zed,

Let me repeat it once again - you NEVER include xsd files in ANY of the projects. Xsd files were icluded in a separate package and are only for reference if you need to get the xpath expressions. That's all.

If you require using INSDES, you need to find the definition in the specific version, which is a cs file, and include it in the Definitions project. that's it. One c# file.
Hope it helps.

Regards,
Kamen
Coordinator
Dec 31, 2013 at 8:41 AM
Hi Zed,

In your code above you need to make sure that the input parameter (ByVal bgm As XElement) is an instance of M_OSTRPT. This is defined in the definition file you have added to the Definitions project. Pseudo code:

M_OSTRPT oStrpt = new M_OSTRPT ();
oStrpt.S_BGM = new Edifact_D98A_OSTRPT.S_BGM();
oStrpt.S_BGM.C_C002.D_1001_1 = "something";

// create the rest of your OSTRPT object

group.MESSAGES.Add(parser.Serialize(oStrpt))
Dec 31, 2013 at 10:55 AM
Regarding the xsd, that's how I had it. So, that was the correct step :)

Regarding, the OSTRPT object, I was missing that last step of using the parser do add to the messages.

Thanks for your patience Don.

Best Regards
Celso Santos

BTW, Happy New Year ;)
Coordinator
Dec 31, 2013 at 11:44 AM
Happy New Year mate.

No worries for the patience - I just haven't got the time to properly support it.
It'll be great if you could reveal some more details on the project you're working on - please contact me (either through email or LinkedIn).

Cheers,
Kamen
Jan 8, 2014 at 11:07 PM
Hello Kamen,

I'm once again using this topic to ask a question (instead of openning an issue) and I'm hoping you could clarify this for me if you can:

So, I've been able to build a simple OSTRPT message with just a couple lines just to test it out and everything went fine.
Now, I'm trying to build a more complex and complete one but I'm having an issue which I've been unable to comprehend why it's happening.

I'm building a message that has a DTM field (actually it has more than one but that's not important at this time) and everything seems to go fine in terms of adding it since I can see the correct output in the interchange XML file.

By using this code:
 Dim interchange As INTERCHANGE = New INTERCHANGE()
        interchange.GROUPS = New List(Of GROUP)()
        interchange.S_UNB = New S_UNB()
        interchange.S_UNZ = New S_UNZ()

        'UNB Segment
        interchange.S_UNB.C_S001 = New C_S001()
        interchange.S_UNB.C_S001.D_0001_1 = "UNOC"
        interchange.S_UNB.C_S001.D_0002_2 = "3"
        interchange.S_UNB.C_S002 = New C_S002()
        interchange.S_UNB.C_S002.D_0004_1 = "504016636" 'TODO - Código do emissor (Verificar qual vai ser o nosso código)
        interchange.S_UNB.C_S002.D_0007_2 = "14"
        interchange.S_UNB.C_S003 = New C_S003()
        interchange.S_UNB.C_S003.D_0010_1 = "504016636"
        interchange.S_UNB.C_S003.D_0007_2 = "14"
        interchange.S_UNB.C_S004 = New C_S004()
        interchange.S_UNB.C_S004.D_0017_1 = "Data" 'TODO - Data
        interchange.S_UNB.C_S004.D_0019_2 = "Hora" 'TODO - Hora
        interchange.S_UNB.D_0020_5 = "30987654" 'TODO - IDMensagem (ir buscar a tabela edi_msgs)

        'Initialize message contents
        Dim oRPT As M_OSTRPT = New M_OSTRPT()

        'UNH segment
        oRPT.S_UNH = New Edifact_D98A_OSTRPT.S_UNH()
        oRPT.S_UNH.D_0062_1 = "1" 'Sempre 1 porque indica o nº de mensagens no interior do ficheiro, neste caso, 1 mensagem por ficheiro
        oRPT.S_UNH.C_S009.D_0065_1 = "OSTRPT"
        oRPT.S_UNH.C_S009.D_0052_2 = "D"
        oRPT.S_UNH.C_S009.D_0054_3 = "98A"
        oRPT.S_UNH.C_S009.D_0051_4 = "UN"

        'BGM segment
        oRPT.S_BGM = New Edifact_D98A_OSTRPT.S_BGM()
        oRPT.S_BGM.C_C002.D_1001_1 = msg_type '78E no OSTRPT POD, 80E no OSTRPT PICK
        oRPT.S_BGM.C_C106.D_1004_1 = "9999999" 'TODO: BGM - ir buscar nº documento à BD
        oRPT.S_BGM.D_1225_3 = "9"

        'DTM segment
        Dim dtm As Edifact_D98A_OSTRPT.S_DTM = New Edifact_D98A_OSTRPT.S_DTM()
        dtm.C_C507.D_2005_1 = "137"
        dtm.C_C507.D_2380_2 = "08012013" 'TODO - Colocar a data do documento (now(), sem a parte da hora)
        dtm.C_C507.D_2379_3 = "102"
I get this XML output (where it's clear that the DTM is missing):
<INTERCHANGE xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="www.edifabric.com/edifact">
  <S_UNB>
    <C_S001>
      <D_0001_1>UNOC</D_0001_1>
      <D_0002_2>3</D_0002_2>
    </C_S001>
    <C_S002>
      <D_0004_1>504016636</D_0004_1>
      <D_0007_2>14</D_0007_2>
    </C_S002>
    <C_S003>
      <D_0010_1>504016636</D_0010_1>
      <D_0007_2>14</D_0007_2>
    </C_S003>
    <C_S004>
      <D_0017_1>Data</D_0017_1>
      <D_0019_2>Hora</D_0019_2>
    </C_S004>
    <D_0020_5>30987654</D_0020_5>
  </S_UNB>
  <GROUPS>
    <GROUP>
      <MESSAGES>
        <MESSAGE>
          <M_OSTRPT xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="EdiFabric.Definitions.Edifact_D98A_OSTRPT">
            <S_UNH>
              <D_0062_1>1</D_0062_1>
              <C_S009>
                <D_0065_1>OSTRPT</D_0065_1>
                <D_0052_2>D</D_0052_2>
                <D_0054_3>98A</D_0054_3>
                <D_0051_4>UN</D_0051_4>
              </C_S009>
              <C_S010 />
              <C_S016 />
              <C_S017 />
              <C_S018 />
            </S_UNH>
            <S_BGM>
              <C_C002>
                <D_1001_1>80E</D_1001_1>
              </C_C002>
              <C_C106>
                <D_1004_1>9999999</D_1004_1>
              </C_C106>
              <D_1225_3>9</D_1225_3>
            </S_BGM>
            <S_DTM />
            <S_RFF>
              <C_C506 />
            </S_RFF>
            <S_FTX />
            <G_NAD />
            <G_DOC />
            <S_UNT />
          </M_OSTRPT>
        </MESSAGE>
      </MESSAGES>
    </GROUP>
  </GROUPS>
  <S_UNZ>
    <D_0036_1>1</D_0036_1>
    <D_0020_2>10000</D_0020_2>
  </S_UNZ>
</INTERCHANGE>
But if I use this code (or the variant where the list item is instantiated):
        'oRPT.S_DTM = New List(Of Edifact_D98A_OSTRPT.S_DTM)
        'DTM segment
        Dim dtm As Edifact_D98A_OSTRPT.S_DTM = New Edifact_D98A_OSTRPT.S_DTM()
        dtm.C_C507.D_2005_1 = "137"
        dtm.C_C507.D_2380_2 = "08012013" 'TODO - Colocar a data do documento (now(), sem a parte da hora)
        dtm.C_C507.D_2379_3 = "102"
        oRPT.S_DTM.Add(dtm)
I get the following output:
<S_BGM>
              <C_C002>
                <D_1001_1>80E</D_1001_1>
              </C_C002>
              <C_C106>
                <D_1004_1>9999999</D_1004_1>
              </C_C106>
              <D_1225_3>9</D_1225_3>
            </S_BGM>
            <S_DTM>
              <S_DTM>
                <C_C507>
                  <D_2005_1>137</D_2005_1>
                  <D_2380_2>08012013</D_2380_2>
                  <D_2379_3>102</D_2379_3>
                </C_C507>
              </S_DTM>
            </S_DTM>
Of course the parse to EDI message fails.

What is the correct way of using this? I've tried a few different methods but none seems to be able to function correctly.

Could you give a pointer please?

Best Regards,
Celso Santos
Coordinator
Jan 10, 2014 at 12:45 PM
Edited Jan 10, 2014 at 4:00 PM
Hi Celso,

After going through all the facts the question is - how to serialize a collection ?

Looking at the following:

oRPT.S_BGM = New Edifact_D98A_OSTRPT.S_BGM() -- this creates a new instance of S_BGM as part of oRTP (oRTP has an instance of BGM)
Dim dtm As Edifact_D98A_OSTRPT.S_DTM = New Edifact_D98A_OSTRPT.S_DTM() -- this creates an instance of S_DTM, but it is NOT part of oRTP

In order to have S_DTM created as part of oRTP (oRTP has an instance of DTM), do exactly as you do for BGM:

oRPT.S_DTM = New Edifact_D98A_OSTRPT.S_DTM()

Regards,
Kamen
Jan 10, 2014 at 1:26 PM
Hello Kamen,

I tried that approach, but unlike the BGM segment, I don't see how to attribute values to the DTM segment since I can't access it's properties. Is this a bug or am I just plain dumb?
Should I then instantiate a new C_C507 object?
Also, using the code as you mention it outputs me an error telling that it's cannot be converted into a generic list,of S_DTM.

I'm not quite grasping the object concept behind EdiFabric and that is most likely the problem.

Here is a screenshot:
Image
Coordinator
Jan 10, 2014 at 1:53 PM
Can you send me the definition file for D98A OSTRPT ?
Jan 10, 2014 at 2:01 PM
Sure!

Here is is:
http://we.tl/LeyrmnMmEp (weTransfer link)
Coordinator
Jan 10, 2014 at 2:34 PM
I got it now, thanks.
It is a bug - in serializing a collection of segments. I need to look into this, will let you know if any work around.
Coordinator
Jan 10, 2014 at 2:44 PM
A quick work around will be to decorate the segment lists with XmlElement attribute, aka in the definition file to have:

[XmlElement("S_DTM")]
public List<S_DTM> S_DTM {
        get {
            return this.s_DTMField;
        }
        set {
            this.s_DTMField = value;
        }
    }
Jan 10, 2014 at 3:02 PM
BTW Kamen,

Is it the same bug that causes different NAD segments in a INSDES message to be placed inside a G_NAD for each?

Example of the XML output of an INSDES message:
<G_NAD>
                            <S_NAD>
                                <D_3035_1>BY</D_3035_1>
                                <C_C082>
                                    <D_3039_1>298076</D_3039_1>
                                    <D_3055_3>91</D_3055_3>
                                </C_C082>
                                <C_C080>
                                    <D_3036_1>Agrupamento Vertical de Escolas</D_3036_1>
                                </C_C080>
                            </S_NAD>
                            <G_RFF_2>
                                <S_RFF_2>
                                    <C_C506_2>
                                        <D_1153_1>VA</D_1153_1>
                                        <D_1154_2>PT600077250</D_1154_2>
                                    </C_C506_2>
                                </S_RFF_2>
                            </G_RFF_2>
                        </G_NAD>
                        <G_NAD>
                            <S_NAD>
                                <D_3035_1>SU</D_3035_1>
                                <C_C082>
                                    <D_3039_1>5600000768143</D_3039_1>
                                    <D_3055_3>9</D_3055_3>
                                </C_C082>
                                <C_C080>
                                    <D_3036_1>Nutricafés - Cafés e Restauração SA</D_3036_1>
                                </C_C080>
                            </S_NAD>
                            <G_CTA>
                                <S_CTA>
                                    <D_3139_1>DL</D_3139_1>
                                    <C_C056>
                                        <D_3412_2>Agrupamento Vertical de Escolas</D_3412_2>
                                    </C_C056>
                                </S_CTA>
                                <S_COM>
                                    <C_C076>
                                        <D_3148_1>212590736</D_3148_1>
                                        <D_3155_2>TE</D_3155_2>
                                    </C_C076>
                                </S_COM>
                            </G_CTA>
                        </G_NAD>
Coordinator
Jan 10, 2014 at 3:21 PM
Edited Jan 10, 2014 at 4:03 PM
G_NAD is a group, so it should be fine. It's only for lists of segments, where you have
public List<S_XXX> S_XXX {