Microsoft .NET Remoting (Pro-Developer)
Message Flows
Examining the message exchange between the JobClient and JobServer applications at various points of interaction can be quite instructive. Because we ve chosen the HTTP channel with the default SOAP formatter, we can view the messages in a mostly human-readable form by using a tracing tool. Because the messages can be large, we ll try to break some of them into chunks that are easier to explain.
The JobClient application instantiates a proxy to the JobServerImpl type when the application first starts. Because the application configures the JobServerImpl type as a well-known object, the client doesn t need to send a message to the server application until the client application accesses the remote object instance in some way for example, via a property or a method call.
The add_JobEvent Request Message
The client first accesses the remote object instance when it subscribes to the JobEvent event, resulting in the following message exchange:
JobClient sends an add_JobEvent request message to JobServer.
JobServer sends an add_JobEvent response message to JobClient.
The compiler generates the add_JobEvent and remove_JobEvent methods on the JobServerImpl class because the class defines the JobEvent event member. The request message consists of an HTTP POST request message containing application data defining a SOAP message.
The following listing shows the HTTP header portion of the request message:
POST /JobServer/JobURI HTTP/1.1User-Agent: Mozilla/4.0+(compatible; MSIE 6.0; Windows 5.0.2195.0; MS .NET Remoting; MS .NET CLR 1.0.3705.0 ) Content-Type: text/xml; charset="utf-8" SOAPAction: "http://schemas.microsoft.com/clr/nsassem/ JobServerLib.IJobServer/JobServerLib#add_JobEvent" Content-Length: 6833 Expect: 100-continue Connection: Keep-Alive Host: localhost
Although it s not evident in the HTTP request message headers, the JobClient application sends the message to the endpoint URL that we specified when configuring the JobServerImpl type as a server-activated object. Notice that the URL of the HTTP request message is /JobServer/JobURI. This directly correlates to the URL that we specified when configuring the JobServerImpl type as a server-activated type. The server-side host application s .NET Remoting infrastructure uses this information to route the message to the associated object instance.
The SOAPAction header signifies that the HTTP request message contains a SOAP message in the body pertaining to the add_JobEvent method.
The following listing shows the SOAP <Envelope> element portion of the message, which remains the same for all messages:
<SOAP-ENV:Envelope xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xmlns:xsd=http://www.w3.org/2001/XMLSchema xmlns:SOAP-ENC=http://schemas.xmlsoap.org/soap/encoding/ xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr=http://schemas.microsoft.com/soap/encoding/clr/1.0 SOAP-ENV:encoding>
The <Body> portion of the SOAP message follows:
<SOAP-ENV:Body> <i2:add_JobEvent xmlns:i2="http://schemas.microsoft.com/clr/nsassem/ JobServerLib.IJobServer/JobServerLib"> <value href="#ref-3"/> </i2:add_JobEvent>
The <i2:add_JobEvent> element specifies that this SOAP message encapsulates an RPC on the IJobServer.add_JobEvent method. The element contains a <value> element that represents the value of the parameter passed to the method. The following listing shows the definition for the <a1:DelegateSerializationHolder> element to which the <value> element refers:
<a1:DelegateSerializationHolder xmlns:a1="http://schemas.microsoft.com/clr/ns/System"> <Delegate href="#ref-4"/> <target0 href="#ref-5"/> </a1:DelegateSerializationHolder>
The <a1:DelegateSerializationHolder> element is a serialized instance of the System.DelegateSerializationHolder class. The serialized instance contains two members, one of which is the <Delegate> element which references the following element:
<a1:DelegateSerializationHolder_x002B_DelegateEntry xmlns:a1="http://schemas.microsoft.com/clr/ns/System"> <type >JobServerLib.JobEventHandler</type> <assembly >JobServerLib, Version=1.0.807.36861, Culture=neutral, PublicKeyToken=null</assembly> <target xsi:type="SOAP-ENC:string">target0</target> <targetTypeAssembly >JobClient, Version=1.0.807.36865, Culture=neutral, PublicKeyToken=null</targetTypeAssembly> <targetTypeName >JobClient.Form1</targetTypeName> <methodName >MyJobEventHandler</methodName> <delegateEntry xsi:null="1"/> </a1:DelegateSerializationHolder_x002B_DelegateEntry>
This element defines the delegate s type and assembly information in this case, JobServerLib.JobEventHandler in the JobServerLib assembly. The element also defines the target s type information: the MyJobEventHandler method of the JobClient.Form1 class defined in the JobClient assembly.
The second member of the <a1:DelegateSerializationHolder> is the <target0> element, which specifies the target object instance of the delegate:
<a2:ObjRef xmlns:a2="http://schemas.microsoft.com/ clr/ns/System.Runtime.Remoting"> <uri > /16e04fb4_ad6d_47ec_b584_22624cf6c808/96410280_1.rem </uri> <objrefFlags>0</objrefFlags> <typeInfo href="#ref-13"/> <envoyInfo xsi:null="1"/> <channelInfo href="#ref-14"/> </a2:ObjRef>
Notice that the <target0> element refers to the <a2:ObjRef> element. The <a2:ObjRef> element is the serialized System.ObjRef instance representing the target object instance of the delegate. Recall from Chapter 2, Understanding the .NET Remoting Architecture, that an ObjRef contains the type information for each type in the derivation hierarchy of the type derived from MarshalByRef Object. Because JobClient.Form1 is a Windows.Forms.Form type, the serialized ObjRef describes a number of interfaces and concrete types. The remainder of the message defines each of the elements contained by the <a2:ObjRef> element. These elements include the marshaled object instance s URI; context identifier, application domain identifier, and process identifier information for the Marshal ByRefObject; and channel information such as transport type (HTTP), IP address, and listening ports:
<a2:TypeInfo xmlns:a2="http://schemas.microsoft.com/ clr/ns/System.Runtime.Remoting"> <serverType >JobClient.Form1, JobClient, Version=1.0.807.36865, Culture=neutral, PublicKeyToken=null </serverType> <serverHierarchy href="#ref-16"/> <interfacesImplemented href="#ref-17"/> </a2:TypeInfo> <a2:ChannelInfo xmlns:a2="http://schemas.microsoft.com/ clr/ns/System.Runtime.Remoting"> <channelData href="#ref-18"/> </a2:ChannelInfo>
The following element is an array of strings that represent the complete derivation hierarchy up to but not including System.MarshalByRefObject:
<SOAP-ENC:Array SOAP-ENC:arrayType="xsd:string[5]"> <item >System.Windows.Forms.Form, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 </item> <item >System.Windows.Forms.ContainerControl, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item >System.Windows.Forms.ScrollableControl, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item >System.Windows.Forms.Control, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 </item> <item >System.ComponentModel.Component, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 </item> </SOAP-ENC:Array>
The next element is a string array containing all the interfaces that the marshaled type implements:
<SOAP-ENC:Array SOAP-ENC:arrayType="xsd:string[18]"> <item >System.ComponentModel.IComponent, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 </item> <item >System.IDisposable, mscorlib, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item > System.Windows.Forms.UnsafeNativeMethods+IOleControl, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item > System.Windows.Forms.UnsafeNativeMethods+IOleObject, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item > System.Windows.Forms.UnsafeNativeMethods+IOleInPlaceObject, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item > System.Windows.Forms.UnsafeNativeMethods+IOleInPlaceActiveObject, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item > System.Windows.Forms.UnsafeNativeMethods+IOleWindow, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item > System.Windows.Forms.UnsafeNativeMethods+IViewObject, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item > System.Windows.Forms.UnsafeNativeMethods+IViewObject2, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item >System.Windows.Forms.UnsafeNativeMethods+IPersist, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item > System.Windows.Forms.UnsafeNativeMethods+IPersistStreamInit, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item > System.Windows.Forms.UnsafeNativeMethods+IPersistPropertyBag, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item > System.Windows.Forms.UnsafeNativeMethods+IPersistStorage, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item > System.Windows.Forms.UnsafeNativeMethods+IQuickActivate, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item >System.ComponentModel.ISynchronizeInvoke, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 </item> <item >System.Windows.Forms.IWin32Window, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item >System.Windows.Forms.IContainerControl, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item >System.Runtime.Remoting.Lifetime.ISponsor, mscorlib, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> </SOAP-ENC:Array>
Finally, the message contains information identifying the calling application domain, context, and process as well as information about channels that the sending application domain is publishing. This content enables the recipient of the message to establish a communications channel if needed:
<SOAP-ENC:Array SOAP-ENC:arrayType="xsd:anyType[2]"> <item href="#ref-42"/> <item href="#ref-43"/> </SOAP-ENC:Array> <a3:CrossAppDomainData xmlns:a3="http://schemas.microsoft.com/clr/ns/ System.Runtime.Remoting.Channels"> <_ContextID>1300872</_ContextID> <_DomainID>1</_DomainID> <_processGuid > 20c23b9b_4d09_46a8_bc29_10037f04f46f </_processGuid> </a3:CrossAppDomainData> <a3:ChannelDataStore xmlns:a3="http://schemas.microsoft.com/clr/ns/ System.Runtime.Remoting.Channels"> <_channelURIs href="#ref-45"/> <_extraData xsi:null="1"/> </a3:ChannelDataStore> <SOAP-ENC:Array SOAP-ENC:arrayType="xsd:string[1]"> <item >http://66.156.56.215:1958</item> </SOAP-ENC:Array> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
The add_JobEvent Response Message
Once the add_Delegate method finishes, the server-side .NET Remoting infrastructure will package the result of the method call into a response message and return it to the client. The following listing shows the HTTP response message for the add_Delegate method:
HTTP/1.1 200 OK Content-Type: text/xml; charset="utf-8" Server: MS .NET Remoting, MS .NET CLR 1.0.3705.0 Content-Length: 580 <SOAP-ENV:Envelope ...> <SOAP-ENV:Body> <i2:add_JobEventResponse xmlns:i2="http://schemas.microsoft.com/clr/nsassem/ JobServerLib.IJobServer/JobServerLib"> </i2:add_JobEventResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
The GetJobs Request Message
When the client calls the IJobServer.GetJobs method on the remote JobServerImpl instance, the .NET Remoting infrastructure sends a GetJobs request message to the server:
POST /JobServer/JobURI HTTP/1.1User-Agent: Mozilla/4.0+(compatible; MSIE 6.0; Windows 5.0.2195.0; MS .NET Remoting; MS .NET CLR 1.0.3705.0 ) Content-Type: text/xml; charset="utf-8" SOAPAction: "http://schemas.microsoft.com/clr/nsassem/ JobServerLib.IJobServer/JobServerLib#GetJobs"Content-Length: 554 Expect: 100-continue Host: localhost <SOAP-ENV:Envelope > <SOAP-ENV:Body> <i2:GetJobs xmlns:i2="http://schemas.microsoft.com/ clr/nsassem/JobServerLib.IJobServer/JobServerLib"> </i2:GetJobs> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
The GetJobs Response Message
In response to the GetJobs request message, the server sends a GetJobs response message to the client. This message contains the serialized return result, an ArrayList of JobInfo instances containing all currently defined jobs:
HTTP/1.1 200 OKContent-Type: text/xml; charset="utf-8" Server: MS .NET Remoting, MS .NET CLR 1.0.3705.0 Content-Length: 1991 <SOAP-ENV:Envelope ...> <SOAP-ENV:Body> <i2:GetJobsResponse xmlns:i2="http://schemas.microsoft.com/clr/nsassem/ JobServerLib.IJobServer/JobServerLib"> <return href="#ref-3"/> </i2:GetJobsResponse> <a1:ArrayList xmlns:a1="http://schemas.microsoft.com/clr/ns/ System.Collections"> <_items href="#ref-4"/> <_size>3</_size> <_version>6</_version> </a1:ArrayList> <SOAP-ENC:Array SOAP-ENC:arrayType="xsd:anyType[16]"> <item xsi:type="a3:JobInfo" xmlns:a3="http://schemas.microsoft.com/clr/nsassem/ JobServerLib/JobServerLib%2C%20 Version%3D1.0.819.24637%2C%20Culture%3Dneutral%2C%20 PublicKeyToken%3Dnull"> <m_nID>0</m_nID> <m_sDescription >Wash Windows</m_sDescription> <m_sAssignedUser > Administrator</m_sAssignedUser> <m_sStatus >Assigned</m_sStatus> </item> <item xsi:type="a3:JobInfo" xmlns:a3="http://schemas.microsoft.com/clr/nsassem/ JobServerLib/JobServerLib%2C%20 Version%3D1.0.819.24637%2C%20Culture%3Dneutral%2C%20 PublicKeyToken%3Dnull"> <m_nID>1</m_nID> <m_sDescription >Fix door</m_sDescription> <m_sAssignedUser > Administrator</m_sAssignedUser> <m_sStatus >Assigned</m_sStatus> </item> <item xsi:type="a3:JobInfo" xmlns:a3="http://schemas.microsoft.com/clr/nsassem/ JobServerLib/JobServerLib%2C%20 Version%3D1.0.819.24637%2C%20Culture%3Dneutral%2C%20 PublicKeyToken%3Dnull"> <m_nID>2</m_nID> <m_sDescription > Clean carpets</m_sDescription> <m_sAssignedUser > Administrator</m_sAssignedUser> <m_sStatus >Completed</m_sStatus> </item> </SOAP-ENC:Array> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
The CreateJob Request Message
The client application sends a CreateJob request message to the server when the client calls the IJobServer.CreateJob method on the remote JobServerImpl instance. The IJobServer.CreateJob method takes one parameter, the description for the new job. The following message creates a job with the description Wash Windows:
POST /JobServer/JobURI HTTP/1.1User-Agent: Mozilla/4.0+(compatible; MSIE 6.0; Windows 5.0.2195.0; MS .NET Remoting; MS .NET CLR 1.0.3705.0 ) Content-Type: text/xml; charset="utf-8" SOAPAction: "http://schemas.microsoft.com/clr/nsassem/ JobServerLib.IJobServer/JobServerLib#CreateJob"Content-Length: 612 Expect: 100-continue Host: localhost <SOAP-ENV:Envelope ...> <SOAP-ENV:Body> <i2:CreateJob xmlns:i2="http://schemas.microsoft.com/clr/nsassem/ JobServerLib.IJobServer/JobServerLib"> <sDescription >Wash Windows</sDescription> </i2:CreateJob> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
The CreateJob Response Message
Because the CreateJob method s return type is void and doesn t define any output parameters, the CreateJob response message is essentially an acknowledgment to the sender that the method call has finished:
HTTP/1.1 200 OKContent-Type: text/xml; charset="utf-8" Server: MS .NET Remoting, MS .NET CLR 1.0.3705.0 Content-Length: 574 <SOAP-ENV:Envelope ...> <SOAP-ENV:Body> <i2:CreateJobResponse xmlns:i2="http://schemas.microsoft.com/clr/nsassem/ JobServerLib.IJobServer/JobServerLib"> </i2:CreateJobResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
The UpdateJobState Request Message
The following message results from the JobClient application calling the UpdateJobState method passing as parameters the values 2, Administrator, and Completed:
POST /JobServer/JobURI HTTP/1.1User-Agent: Mozilla/4.0+(compatible; MSIE 6.0; Windows 5.0.2195.0; MS .NET Remoting; MS .NET CLR 1.0.3705.0 ) Content-Type: text/xml; charset="utf-8" SOAPAction: "http://schemas.microsoft.com/clr/nsassem/ JobServerLib.IJobServer/JobServerLib#UpdateJobState"Content-Length: 670 Expect: 100-continue Host: localhost <SOAP-ENV:Envelope ...> <SOAP-ENV:Body> <i2:UpdateJobState xmlns:i2="http://schemas.microsoft.com/clr/nsassem/ JobServerLib.IJobServer/JobServerLib"> <nJobID>2</nJobID> <sUser >Administrator</sUser> <sStatus >Completed</sStatus> </i2:UpdateJobState> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
The UpdateJobState Response Message
Like the CreateJob response message, the UpdateJobState response message is essentially an acknowledgment to inform the sender that the method call has finished:
HTTP/1.1 200 OKContent-Type: text/xml; charset="utf-8" Server: MS .NET Remoting, MS .NET CLR 1.0.3705.0 Content-Length: 584 <SOAP-ENV:Envelope ...> <SOAP-ENV:Body> <i2:UpdateJobStateResponse xmlns:i2="http://schemas.microsoft.com/clr/nsassem/ JobServerLib.IJobServer/JobServerLib"> </i2:UpdateJobStateResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
The JobNotes Activation Request Message
When the JobClient application creates an instance of a JobNotes class, the .NET Remoting infrastructure sends an Activate request message to the JobServer application:
POST /RemoteActivationService.rem HTTP/1.1User-Agent: Mozilla/4.0+(compatible; MSIE 6.0; Windows 5.0.2195.0; MS .NET Remoting; MS .NET CLR 1.0.3705.0 ) Content-Type: text/xml; charset="utf-8" SOAPAction: "http://schemas.microsoft.com/clr/ns/ System.Runtime.Remoting.Activation.IActivator#Activate"Content-Length: 2126 Expect: 100-continue Host: localhost <SOAP-ENV:Envelope ...> <SOAP-ENV:Body> <i2:Activate xmlns:i2="http://schemas.microsoft.com/clr/ns/ System.Runtime.Remoting.Activation.IActivator"> <msg href="#ref-3"/> </i2:Activate> <a1:ConstructionCall xmlns:a1="http://schemas.microsoft.com/clr/ns/ System.Runtime.Remoting.Messaging"> <__Uri xsi:type="xsd:anyType" xsi:null="1"/> <__MethodName >.ctor</__MethodName> <__MethodSignature href="#ref-5"/> <__TypeName >JobServerLib.JobNotes, JobServerLib, Version=1.0.819.24637, Culture=neutral, PublicKeyToken=null</__TypeName> <__Args href="#ref-7"/> <__CallContext xsi:type="xsd:anyType" xsi:null="1"/> <__CallSiteActivationAttributes xsi:type="xsd:anyType" xsi:null="1"/> <__ActivationType xsi:type="xsd:anyType" xsi:null="1"/> <__ContextProperties href="#ref-8"/> <__Activator href="#ref-9"/> <__ActivationTypeName href="#ref-6"/> </a1:ConstructionCall> <SOAP-ENC:Array SOAP-ENC:arrayType="a2:Type[0]" xmlns:a2="http://schemas.microsoft.com/clr/ns/System"> </SOAP-ENC:Array> <SOAP-ENC:Array SOAP-ENC:arrayType="xsd:anyType[0]"> </SOAP-ENC:Array> <a3:ArrayList xmlns:a3="http://schemas.microsoft.com/clr/ns/ System.Collections"> <_items href="#ref-10"/> <_size>0</_size> <_version>0</_version> </a3:ArrayList> <a4:ContextLevelActivator xmlns:a4="http://schemas.microsoft.com/clr/ns/ System.Runtime.Remoting.Activation"> <m_NextActivator href="#ref-11"/> </a4:ContextLevelActivator> <SOAP-ENC:Array SOAP-ENC:arrayType="xsd:anyType[16]"> </SOAP-ENC:Array> <a4:ConstructionLevelActivator xmlns:a4="http://schemas.microsoft.com/clr/ns/ System.Runtime.Remoting.Activation"> </a4:ConstructionLevelActivator> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
The JobNotes Activation Response Message
After activating a JobNotes instance, the .NET Remoting infrastructure sends an ActivateResponse message to the JobClient application. The message contains a serialized System.ObjRef that represents the new JobNotes instance residing in the JobServer application domain:
HTTP/1.1 200 OKContent-Type: text/xml; charset="utf-8" Server: MS .NET Remoting, MS .NET CLR 1.0.3705.0 Content-Length: 2723 <SOAP-ENV:Envelope ...> <SOAP-ENV:Body> <i2:ActivateResponse xmlns:i2="http://schemas.microsoft.com/clr/ns/ System.Runtime.Remoting.Activation.IActivator"> <return href="#ref-3"/> </i2:ActivateResponse> <a1:ConstructionResponse xmlns:a1="http://schemas.microsoft.com/clr/ns/ System.Runtime.Remoting.Messaging"> <__Uri xsi:type="xsd:anyType" xsi:null="1"/> <__MethodName >.ctor</__MethodName> <__TypeName >JobServerLib.JobNotes, JobServerLib, Version=1.0.830.37588, Culture=neutral, PublicKeyToken=null</__TypeName> <__Return href="#ref-6"/> <__OutArgs href="#ref-7"/> <__CallContext xsi:type="xsd:anyType" xsi:null="1"/> </a1:ConstructionResponse> <a3:ObjRef xmlns:a3="http://schemas.microsoft.com/clr/ns/ System.Runtime.Remoting"> <uri > /cf2825b9_2974_4f5c_9810_2f96945b529d/16921141_1.rem</uri> <objrefFlags>0</objrefFlags> <typeInfo href="#ref-9"/> <envoyInfo xsi:null="1"/> <channelInfo href="#ref-10"/> <fIsMarshalled>0</fIsMarshalled> </a3:ObjRef> <SOAP-ENC:Array SOAP-ENC:arrayType="xsd:anyType[0]"> </SOAP-ENC:Array> <a3:TypeInfo xmlns:a3="http://schemas.microsoft.com/clr/ns/ System.Runtime.Remoting"> <serverType >JobServerLib.JobNotes, JobServerLib, Version=1.0.830.37588, Culture=neutral, PublicKeyToken=null</serverType> <serverHierarchy xsi:null="1"/> <interfacesImplemented xsi:null="1"/> </a3:TypeInfo> <a3:ChannelInfo xmlns:a3="http://schemas.microsoft.com/clr/ns/ System.Runtime.Remoting"> <channelData href="#ref-12"/> </a3:ChannelInfo> <SOAP-ENC:Array SOAP-ENC:arrayType="xsd:anyType[2]"> <item href="#ref-13"/> <item href="#ref-14"/> </SOAP-ENC:Array> <a4:CrossAppDomainData xmlns:a4="http://schemas.microsoft.com/clr/ns/ System.Runtime.Remoting.Channels"> <_ContextID>1299232</_ContextID> <_DomainID>1</_DomainID> <_processGuid > efbc85bf_b165_4953_ab00_f37d49bbffb4</_processGuid> </a4:CrossAppDomainData> <a4:ChannelDataStore xmlns:a4="http://schemas.microsoft.com/clr/ns/ System.Runtime.Remoting.Channels"> <_channelURIs href="#ref-16"/> <_extraData xsi:null="1"/> </a4:ChannelDataStore> <SOAP-ENC:Array SOAP-ENC:arrayType="xsd:string[1]"> <item >http://66.156.71.188:4000</item> </SOAP-ENC:Array> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
The remove_JobEvent Request Message
The last interaction that the JobClient application has with the remote JobServerImpl instance is to unsubscribe the JobClient.Form1 instance from the JobEvent. This results in a call to the remove_JobEvent method, which the .NET Remoting infrastructure converts into a remove_JobEvent request message. This message is essentially identical to the add_JobEvent request message because the methods have the same signatures. As with the add_JobEvent request message, the remove_JobEvent message contains a serialized delegate instance. In this case, the target of the delegate is an instance of the JobClient.Form1 type, which is a type derived from MarshalByRefObject. Thus, the message includes a serialized System.ObjRef instance representing the JobClient.Form1 class instance that unsubscribes from the event. The following listing shows the remove_JobEvent request message:
POST /JobServer/JobURI HTTP/1.1 User-Agent: Mozilla/4.0+(compatible; MSIE 6.0; Windows 5.0.2195.0; MS .NET Remoting; MS .NET CLR 1.0.3705.0 ) Content-Type: text/xml; charset="utf-8" SOAPAction: "http://schemas.microsoft.com/clr/nsassem/ JobServerLib.IJobServer/JobServerLib#remove_JobEvent" Content-Length: 6839 Expect: 100-continue Host: localhost <SOAP-ENV:Envelope ...> <SOAP-ENV:Body> <i2:remove_JobEvent xmlns:i2="http://schemas.microsoft.com/clr/nsassem/ JobServerLib.IJobServer/JobServerLib"> <value href="#ref-3"/> </i2:remove_JobEvent> <a1:DelegateSerializationHolder xmlns:a1="http://schemas.microsoft.com/clr/ns/System"> <Delegate href="#ref-4"/> <target0 href="#ref-5"/> </a1:DelegateSerializationHolder> <a1:DelegateSerializationHolder_x002B_DelegateEntry xmlns:a1="http://schemas.microsoft.com/clr/ns/System"> <type >JobServerLib.JobEventHandler</type> <assembly >JobServerLib, Version=1.0.819.24637, Culture=neutral, PublicKeyToken=null</assembly> <target xsi:type="SOAP-ENC:string"> target0</target> <targetTypeAssembly >JobClient, Version=1.0.829.36775, Culture=neutral, PublicKeyToken=null</targetTypeAssembly> <targetTypeName >JobClient.Form1</targetTypeName> <methodName >MyJobEventHandler</methodName> <delegateEntry xsi:null="1"/> </a1:DelegateSerializationHolder_x002B_DelegateEntry> <a2:ObjRef xmlns:a2="http://schemas.microsoft.com/clr/ns/ System.Runtime.Remoting"> <uri > /295e2d43_876a_4511_a774_12e7a65d96bc/13636498_1.rem</uri> <objrefFlags>0</objrefFlags> <typeInfo href="#ref-13"/> <envoyInfo xsi:null="1"/> <channelInfo href="#ref-14"/> </a2:ObjRef> <a2:TypeInfo xmlns:a2="http://schemas.microsoft.com/clr/ns/ System.Runtime.Remoting"> <serverType >JobClient.Form1, JobClient, Version=1.0.829.36775, Culture=neutral, PublicKeyToken=null</serverType> <serverHierarchy href="#ref-16"/> <interfacesImplemented href="#ref-17"/> </a2:TypeInfo> <a2:ChannelInfo xmlns:a2="http://schemas.microsoft.com/clr/ns/ System.Runtime.Remoting"> <channelData href="#ref-18"/> </a2:ChannelInfo> <SOAP-ENC:Array emphasis">ref-16" SOAP-ENC:arrayType="xsd:string[5]"> <item >System.Windows.Forms.Form, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item >System.Windows.Forms.ContainerControl, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item >System.Windows.Forms.ScrollableControl, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item >System.Windows.Forms.Control, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item >System.ComponentModel.Component, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> </SOAP-ENC:Array> <SOAP-ENC:Array emphasis">ref-17" SOAP-ENC:arrayType="xsd:string[18]"> <item >System.ComponentModel.IComponent, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item >System.IDisposable, mscorlib, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item > System.Windows.Forms.UnsafeNativeMethods+IOleControl, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item > System.Windows.Forms.UnsafeNativeMethods+IOleObject, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item >System.Windows.Forms. UnsafeNativeMethods+IOleInPlaceObject, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item >System.Windows.Forms. UnsafeNativeMethods+IOleInPlaceActiveObject, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item > System.Windows.Forms.UnsafeNativeMethods+IOleWindow, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item > System.Windows.Forms.UnsafeNativeMethods+IViewObject, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item > System.Windows.Forms.UnsafeNativeMethods+IViewObject2, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item > System.Windows.Forms.UnsafeNativeMethods+IPersist, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item >System.Windows.Forms. UnsafeNativeMethods+IPersistStreamInit, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item >System.Windows.Forms. UnsafeNativeMethods+IPersistPropertyBag, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item > System.Windows.Forms.UnsafeNativeMethods+IPersistStorage, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item > System.Windows.Forms.UnsafeNativeMethods+IQuickActivate, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item >System.ComponentModel.ISynchronizeInvoke, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item >System.Windows.Forms.IWin32Window, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item >System.Windows.Forms.IContainerControl, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> <item >System.Runtime.Remoting.Lifetime.ISponsor, mscorlib, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</item> </SOAP-ENC:Array> <SOAP-ENC:Array SOAP-ENC:arrayType="xsd:anyType[2]"> <item href="#ref-42"/> <item href="#ref-43"/> </SOAP-ENC:Array> <a3:CrossAppDomainData xmlns:a3="http://schemas.microsoft.com/clr/ns/ System.Runtime.Remoting.Channels"> <_ContextID>1300872</_ContextID> <_DomainID>1</_DomainID> <_processGuid > 20c23b9b_4d09_46a8_bc29_10037f04f46f </_processGuid> </a3:CrossAppDomainData> <a3:ChannelDataStore xmlns:a3="http://schemas.microsoft.com/clr/ns/ System.Runtime.Remoting.Channels"> <_channelURIs href="#ref-45"/> <_extraData xsi:null="1"/> </a3:ChannelDataStore> <SOAP-ENC:Array SOAP-ENC:arrayType="xsd:string[1]"> <item >http://66.156.56.215:1958</item> </SOAP-ENC:Array> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
The remove_JobEvent Response Message
Once the remove_JobEvent method returns, the .NET Remoting infrastructure sends the following message to the JobClient application to indicate the method call has finished:
HTTP/1.1 200 OK Content-Type: text/xml; charset="utf-8" Server: MS .NET Remoting, MS .NET CLR 1.0.3705.0 Content-Length: 586 <SOAP-ENV:Envelope ...> <SOAP-ENV:Body> <i2:remove_JobEventResponse xmlns:i2="http://schemas.microsoft.com/clr/nsassem/ JobServerLib.IJobServer/JobServerLib"> </i2:remove_JobEventResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope>