[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 583
  • Last Modified:

Problem passing exception from AppDomain

I have an application that calls a routine within an AppDomain.  The AppDomain will raise an event outside the AppDomain called StatusUpdate.  It will possibly pass back a SystemException object.

In general, this works fine.  However, if I call the AppDomain routine from a form (versus a console app or a windows service), then the exception will not properly pass back all pieces of a Soap Exception.

Specifically, I want the Detail attribute of the Soap Exception.  I can see that it has a value in the AppDomain but when this value is passed back via the event call, the detail gets lost.

I attached the code for a small app that demonstrates the problem.  Here is the output of the application:

Inside AppDomain
   Message: test
   Detail:  <A>1</A>
Outside AppDomain
   Message: test
   Detail:  Nothing


I am not all that well-versed in AppDomains and would appreciate any ideas that might help me get to the bottom of the problem.

Thanks,
Chris
Imports System.Web.Services.Protocols

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim exeAssembly As String = System.Reflection.Assembly.GetExecutingAssembly().FullName

        Dim ads As New AppDomainSetup()
        ads.ApplicationBase = System.Environment.CurrentDirectory
        ads.DisallowBindingRedirects = False
        ads.DisallowCodeDownload = True
        ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile

        Dim ad2 As AppDomain = AppDomain.CreateDomain("TestMapAppDomain", Nothing, ads)

        Dim mbrt As MarshalByRefType = CType(ad2.CreateInstanceAndUnwrap(exeAssembly, GetType(MarshalByRefType).FullName), MarshalByRefType)

        AddHandler mbrt.StatusUpdate, AddressOf ProcessQueueRecord_StatusUpdate

        mbrt.RunTest()

        End

    End Sub

    Private Sub ProcessQueueRecord_StatusUpdate(ByVal ex As Exception)

        Console.WriteLine("Outside AppDomain")
        Dim soapex As SoapException = CType(ex.GetBaseException, SoapException)
        Console.WriteLine("   Message: " & soapex.Message)
        If soapex.Detail IsNot Nothing Then
            Console.WriteLine("   Detail:  " & soapex.Detail.OuterXml)
        Else
            Console.WriteLine("   Detail:  Nothing")
        End If

        Console.WriteLine(ex.Message)

    End Sub


    Public Class MarshalByRefType
        Inherits MarshalByRefObject

        Public Event StatusUpdate(ByVal ex As Exception)

        Sub RunTest()

            Try
                Dim xmldoc As New Xml.XmlDocument
                xmldoc.LoadXml("<A>1</A>")
                Throw New System.Web.Services.Protocols.SoapException("test", New System.Xml.XmlQualifiedName(), "", xmldoc.FirstChild)
            Catch ex As Exception
                Console.WriteLine("Inside AppDomain")
                Dim soapex As SoapException = CType(ex.GetBaseException, SoapException)
                Console.WriteLine("   Message: " & soapex.Message)
                If soapex.Detail IsNot Nothing Then
                    Console.WriteLine("   Detail:  " & soapex.Detail.OuterXml)
                Else
                    Console.WriteLine("   Detail:  Nothing")
                End If
                RaiseEvent StatusUpdate(ex)
            End Try

        End Sub

    End Class

End Class

Open in new window

0
chlade
Asked:
chlade
  • 2
1 Solution
 
DabasCommented:
Interesting.
At first I thought that your code does not work because your line 63 returns ex and not soapex but when I changed all of the relevant code snippets from Exception to SoapException, the details still got lost.

My code below has a workaround by returning an extra parameter in the StatusUpdate event.
It might, or might not, be acceptable for your purposes

Dabas
Imports System.Web.Services.Protocols

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim exeAssembly As String = System.Reflection.Assembly.GetExecutingAssembly().FullName

        Dim ads As New AppDomainSetup()
        ads.ApplicationBase = System.Environment.CurrentDirectory
        ads.DisallowBindingRedirects = False
        ads.DisallowCodeDownload = True
        ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile

        Dim ad2 As AppDomain = AppDomain.CreateDomain("TestMapAppDomain", Nothing, ads)

        Dim mbrt As MarshalByRefType = CType(ad2.CreateInstanceAndUnwrap(exeAssembly, GetType(MarshalByRefType).FullName), MarshalByRefType)

        AddHandler mbrt.StatusUpdate, AddressOf ProcessQueueRecord_StatusUpdate

        mbrt.RunTest()

        End

    End Sub

    Private Sub ProcessQueueRecord_StatusUpdate(ByVal ex As Exception, ByVal detailxml As String)

        Console.WriteLine("Outside AppDomain")
        Dim soapex As SoapException = CType(ex.GetBaseException, SoapException)
        Console.WriteLine("   Message: " & soapex.Message)
        If detailxml IsNot Nothing Then
            Console.WriteLine("   Detail:  " & detailxml)
        Else
            Console.WriteLine("   Detail:  Nothing")
        End If

        Console.WriteLine(ex.Message)

    End Sub


    Public Class MarshalByRefType
        Inherits MarshalByRefObject

        Public Event StatusUpdate(ByVal ex As Exception, ByVal detail As String)

        Sub RunTest()

            Try
                Dim xmldoc As New Xml.XmlDocument
                xmldoc.LoadXml("<A>1</A>")
                Throw New System.Web.Services.Protocols.SoapException("test", New System.Xml.XmlQualifiedName(), "", xmldoc.FirstChild)
            Catch ex As Exception
                Console.WriteLine("Inside AppDomain")
                Dim soapex As SoapException = CType(ex.GetBaseException, SoapException)
                Console.WriteLine("   Message: " & soapex.Message)
                If soapex.Detail IsNot Nothing Then
                    Console.WriteLine("   Detail:  " & soapex.Detail.OuterXml)
                Else
                    Console.WriteLine("   Detail:  Nothing")
                End If
                RaiseEvent StatusUpdate(ex, soapex.Detail.OuterXml)
            End Try

        End Sub

    End Class

End Class

Open in new window

0
 
chladeAuthor Commented:
Thanks.  Yeah, unfortunately that won't really help me.  In my actual application, the AppDomain actually calls a user-defined "plug in" dll.  It won't only be Soap exceptions.  I just want to make sure that all exceptions of all types are passed back in their entirety so that the main application can report them accurately.

What is interesting is that if you put the logic in the Form Load and skip the AppDomain altogether, it works fine.  As a test I put this code in the Form Load event and it works fine.
Try
            Try
                Try
                    Dim xmldoc As New Xml.XmlDocument
                    xmldoc.LoadXml("<A>1</A>")
                    Throw New System.Web.Services.Protocols.SoapException("test", New System.Xml.XmlQualifiedName(), "", xmldoc.FirstChild)
                Catch ex As Exception
                    Throw New Exception(ex.Message, ex)
                End Try
            Catch ex As Exception
                Throw New Exception(ex.Message, ex)
            End Try
        Catch ex As Exception
            Dim soapex As SoapException = CType(ex.GetBaseException, SoapException)
            Console.WriteLine("   Message: " & soapex.Message)
            If soapex.Detail IsNot Nothing Then
                Console.WriteLine("   Detail:  " & soapex.Detail.OuterXml)
            Else
                Console.WriteLine("   Detail:  Nothing")
            End If
        End Try

Open in new window

0
 
DabasCommented:
That does not come as a surprise.
This code is not crossing between domains.
That is where things are getting lost
0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now