locked
Cannot access a disposed Object RRS feed

  • Question

  • Hi all

    Why should the code below be producing an error "Cannot access a disposed Object"
    I believe the problem lies on the inmsg.BodyPart method..
    A better way to access this method using StreamReader will be appreciated.

     #region Generierung des neuen Filenamens für die Ausgangsdatei
    
                    string eFileType = ".xml";
                  
                    string enewFileName = string.Empty;
                    string eSpecifier = string.Empty;
    
                    
    
    
                    System.IO.Stream st = inmsg.BodyPart.GetOriginalDataStream();
                    System.IO.StreamReader reader = new System.IO.StreamReader(st);
                    string parseInvResult = reader.ReadToEnd();
                    
                   
    
                    int start = parseInvResult.IndexOf("<Sub>") + 18;
                    int end = parseInvResult.IndexOf("</Sub>");
                    string extractedString = parseInvResult.Substring(start, end - start);
    
                    // DateString         
                  
                    eSpecifier = extractedString;
                    enewFileName = string.Format("{0}{1}", eSpecifier, eFileType);
    
                    #endregion
                    reader.Dispose();
    
                    #region Property ReceivedFileName überschreiben, damit das File mit %SourceFileName% geschrieben werden kann
                    inmsg.Context.Write("ReceivedFileName", FILEadapterTargetNamespace, enewFileName);
                    #endregion
                   


    AKE
    Wednesday, February 3, 2010 8:16 PM

Answers

  • Hi Mohan

    Get it working at last..

    This is what I did

    ASCIIEncoding ASCIIEncoding = new ASCIIEncoding();

                    
                    byte[] firstString = ASCIIEncoding.GetBytes(parseInvResult);
                    MemoryStream memStream = new MemoryStream(100);
                   
                    memStream.Write(firstString, 0, firstString.Length);

                              
                    memStream.Position = 0;

                   
                    bodyPart.Data = memStream;

                    
                    pc.ResourceTracker.AddResource(memStream); // this is one of the key factor I have been missing all the time

    Thanks for your help


    AKE
    • Marked as answer by Akaschmid Saturday, February 6, 2010 4:22 PM
    Saturday, February 6, 2010 4:22 PM

All replies

  • Hi Mohan

    I did not see any StreamReader in the link/code you pasted .. 
    I must use StreamReader in the code

    Thanks for your help



    AKE
    Wednesday, February 3, 2010 8:40 PM
  • Hi A

    I inserted the st.Seek(0, SeekOrigin.Begin);
    inmsg.BodyPart.Data = st;

    Still did not work..

    getting the error CEventingReadStream error



    AKE
    Thursday, February 4, 2010 8:08 AM
  • Hi,

    The error is probably raised by the next component trying to read the stream. I think this is because you explicitly dispose the reader. From your code it appears you just need a value from the incoming xml and use that a as a value for a promoted property. To be able to do this you read the stream yourself. I think this is not necessary. I think you better let something else down the stream (next component, or messaging engine) read the stream. The only thing you have to do is monitor the stream passing by. If the element your interested in (<sub>) passes by you get the value.

    There a are a couple of ways to do this. You can use the XPathMutatorStream which raises an event whenever your element is triggered. Or you can implement your own XMLReader. Those approaches allow you to watch the stream without reading it yourself. This is also better in terms of performance.

    Yossi's post might be helpful: http://www.sabratech.co.uk/blogs/yossidahan/2008/03/extracting-values-from-message-in.html


    HTH,

    Randal van Splunteren - MVP, MCTS BizTalk Server
    http://biztalkmessages.vansplunteren.net

    Please mark as answered if this answers your question.

    Check out the PowerShell provider for BizTalk: http://psbiztalk.codeplex.com
    Thursday, February 4, 2010 8:25 AM
    Moderator
  • Hi AKE,

    I think in sample above that you forgot reader.close(), before you dispose it.

    Regards,

    Steef-Jan Wiggers
    MCTS BizTalk Server
    http://soa-thoughts.blogspot.com/
    BizTalk Server
    Thursday, February 4, 2010 8:33 AM
    Moderator
  • Hi Jan

    I have tried that already.
    reader.close() and also reader.dispose();

    Even I have left out the two methods..
    Still getting the error..

    From the error log.. I can see the value I am looking for..  i.e the value in Sub..

    Some how I need to pass the inmsg.BodyPart.Data back to the next component

    Below is the complete code.

    I will try Splunteren Idea and see what will come out of it
    public Microsoft.BizTalk.Message.Interop.IBaseMessage Execute(Microsoft.BizTalk.Component.Interop.IPipelineContext pc, Microsoft.BizTalk.Message.Interop.IBaseMessage inmsg)
            {
                // 
                // TODO: implement component logic
               
                string EventApp = "Application";
                string EventSourceA = "ACC.ABC.OUT";
    
    
                if (!EventLog.SourceExists(EventSourceA))
                {
                    EventLog.CreateEventSource(EventSourceA, EventApp);
                }
    
                EventLog errorLog = new EventLog();
                errorLog.Source = EventSourceA;
    
                try
                {
                    
    
                    // Get Promoted Propertys from Message Property
                    IBaseMessageContext context = inmsg.Context;
                    const string FILEadapterTargetNamespace = "http://schemas.microsoft.com/BizTalk/2003/file-properties";
                    string sBizTalkMessageID = context.Read("InterchangeID", "http://schemas.microsoft.com/BizTalk/2003/system-properties").ToString();
                   
                    string sReceivedFileName = string.Empty;
                    //string sOriginalFileDateTime = string.Empty;
    
    
    
                   
                    try
                    {
                        sReceivedFileName = inmsg.Context.Read("ReceivedFileName", FILEadapterTargetNamespace).ToString();
                        // sOriginalFileDateTime = inmsg.Context.Read("FileCreationTime", FILEadapterTargetNamespace).ToString();
    
                        //AdapterReceiveCompleteTime
    
                        int CTT = sReceivedFileName.LastIndexOf(@"\");
                        if (CTT != -1)
                        {
                            sReceivedFileName = sReceivedFileName.Substring(CTT + 1, sReceivedFileName.Length - (CTT + 1));
                        }
                    }
                    catch (Exception ex)
                    {
    
                        errorLog.WriteEntry(ex.ToString(), EventLogEntryType.Warning, 100);
                    }
                    #endregion
    
    
                    #region Generierung des neuen Filenamens für die Ausgangsdatei
    
                    string eFileType = ".xml";
                  
                    string enewFileName = string.Empty;
                    string eSpecifier = string.Empty;
                    string parseInvResult = string.Empty;
    
                   
                    
                    //Get Body Part of inmsg
                    IBaseMessagePart bodyPart = inmsg.BodyPart;
                    Stream originalStream = bodyPart.Data;
    
                   
                   using(StreamReader reader = new StreamReader(originalStream))
                    
                    {
                        parseInvResult = reader.ReadToEnd();
                    }
    
                    
                    int start = parseInvResult.IndexOf("<Sub>") + 18;
                    int end = parseInvResult.IndexOf("</Sub>");
                    string VLVID = parseInvResult.Substring(start, end - start);
    
                    EventLog.CreateEventSource(VLVID, EventApp);
                    // DateString         
                  
                    eSpecifier = VLVID;
                    enewFileName = string.Format("{0}{1}", eSpecifier, eFileType);
    
                    #endregion
                  
    
                    #region Property ReceivedFileName überschreiben, damit das File mit %SourceFileName% geschrieben werden kann
                    inmsg.Context.Write("ReceivedFileName", FILEadapterTargetNamespace, enewFileName);
                    #endregion
    
                    originalStream.Seek(0, SeekOrigin.Begin);
                    inmsg.BodyPart.Data = originalStream;
                  
    				reader.close();
                    
                }
    
                catch (Exception e)
                {
    
                    //Debug info start
                    errorLog.WriteEntry(e.ToString(), EventLogEntryType.Error, 100);
                    //Console.WriteLine(e.ToString());
                }
    
                // EventLog schliessen
                errorLog.Close();
    
                // this way, it's a passthrough pipeline component
                
               
                return inmsg;
            }
            #endregion
    
               
        }


    AKE
    Thursday, February 4, 2010 8:53 AM
  • Are you getting any syntax error while compiling this code?

    I am not sure how you can use reader.close(); since you are declaring reader for using block.
    Thanks. Mo
    Thursday, February 4, 2010 9:20 AM
  • Hi A

    I am getting Cannot access a disposed object 
    Object name "CEventingReadStream"

    I removed the reader.close() method from the project..
    I am still getting the error..

    The problem lines in the StreamReader ... 

    If I remove the StreamReader section the code run without problem

    AKE
    Thursday, February 4, 2010 9:30 AM
  • Hi AKE,

    What version of BizTalk Server are you running? This code is executed in a pipeline a assume?

    Could you let me know?

    Regards,

    Steef-Jan
    BizTalk Server
    Thursday, February 4, 2010 10:23 AM
    Moderator
  • Just found an interesting link

    http://msdn.microsoft.com/en-us/library/ee377071(BTS.10).aspx

    AKE
    Thursday, February 4, 2010 10:24 AM
  • Hi,

    The content in this link is in line with my previous comment on your question. Use one of the stream helpers provided out of the box with BizTalk. I'm not sure what actually causes the error in your current scenario but when you use the different (wrapped stream) approach you probably won't see the error anymore. Also this has the benefit that you don't have to read the whole stream in a string variable like you do now. In my opinion reading the whole stream is not a very good design and should only be used when absolutely necessary. It is very resource intensive and might give you problems when processing big messages.

    HTH,

    Randal van Splunteren - MVP, MCTS BizTalk Server
    http://biztalkmessages.vansplunteren.net

    Please mark as answered if this answers your question.

    Check out the PowerShell provider for BizTalk: http://psbiztalk.codeplex.com
    Thursday, February 4, 2010 10:49 AM
    Moderator
  • Hi Akas,

    There shouldnot be a problem using StreamReader unless the message stream is okay for next component.

    Can you just check if this works?

    inmsg.BodyPart.Data = originalStream;
    inmsg.BodyPart.Data.Position = 0;







    Thanks. Mo
    Thursday, February 4, 2010 12:41 PM
  • Hi Mohan A

    I have no outMsg declared in my class 
    is this a mistake?

    AKE
    Thursday, February 4, 2010 1:43 PM
  • Sorry, it is mistake, it should be inmsg insted.
    Thanks. Mo
    Thursday, February 4, 2010 2:02 PM
  • Hi Splunteren

    I have tried your suggestion

    The problem I ran into is that XPathCollection class is only available in Biztalk 2009

    We are running Biztalk 2006.

    I believe my only option now is to implement the whole solution using Orchestration.. 
    Pipeline makes not sense for the problem at hand.



    AKE
    Thursday, February 4, 2010 2:07 PM
  • Hi Mohan

    Try that also did not work..

    I think I am doing something wrong.. 

    I can read the stream, get my values.. but I cannot return the original message back to the next component..

    May be I just need to make a copy of the original message.. somehow

    Regards


    AKE
    • Marked as answer by Akaschmid Saturday, February 6, 2010 4:22 PM
    • Unmarked as answer by Akaschmid Saturday, February 6, 2010 4:22 PM
    Thursday, February 4, 2010 2:10 PM
  • May be I just need to make a copy of the original message.. somehow


    Try creating new object of type MemoryStream to hold the original message, and assign that back to inmsg.BodyPart.Data later.
    Thanks. Mo
    Friday, February 5, 2010 7:25 AM
  • Hi Mohan

    Get it working at last..

    This is what I did

    ASCIIEncoding ASCIIEncoding = new ASCIIEncoding();

                    
                    byte[] firstString = ASCIIEncoding.GetBytes(parseInvResult);
                    MemoryStream memStream = new MemoryStream(100);
                   
                    memStream.Write(firstString, 0, firstString.Length);

                              
                    memStream.Position = 0;

                   
                    bodyPart.Data = memStream;

                    
                    pc.ResourceTracker.AddResource(memStream); // this is one of the key factor I have been missing all the time

    Thanks for your help


    AKE
    • Marked as answer by Akaschmid Saturday, February 6, 2010 4:22 PM
    Saturday, February 6, 2010 4:22 PM