<div class="gmail_quote">On Thu, Dec 15, 2011 at 2:57 PM, Robert Jordan <span dir="ltr">&lt;<a href="mailto:robertj@gmx.net">robertj@gmx.net</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi Andrey,<br>
<br>
Do you have a test case for these issues?<br>
<br>
Thanks<br>
Robert<br><br></blockquote><div><pre>                                           
Hello Robert!

Thank you for your quick reply.

After an additional research I&#39;ve decided to cancel patch#1. This issue (different behavior in .NET and Mono) takes place, but suggested patch is incorrect. 
I will try to find workaround in my application.

Below is the test case for patch#2 (patch.return-value.diff, link: <a href="https://gist.github.com/1480249">https://gist.github.com/1480249</a>).

Issue
=====
Mono doesn&#39;t send the results of remote method execution to IDinamicMessageSink.ProcessMessageFinish().
.NET Framework (2.0 and 4.0) sends to IDinamicMessageSink.ProcessMessageFinish() an instance of ReturnMessage class that implements IMethodReturnMessage interface.  
This interface contains all necessary information (return vlaue, exception, out args and modified call context).  
Mono sends an istance of MethodCall class, exactly the same as to IDinamicMessageSink.ProcessMessageStart().
It seems to be a bug in Mono sources and I have suggested the patch.


Test application
================
This test application illustrates an issue in Mono runtime. 
Server and client objects are created in a single application (for the simplification of an example).
They interoperate through Remoting using IPC channel.
Class MyDynamicMessageSink implements dynamic message sink to handle remoting method execution. 


Source code
===========
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Contexts;

namespace Patch2_Test
{
  class Program
  {
    static void Main(string[] args)
    {
      // Initialize server side remoting 
      ChannelServices.RegisterChannel(new IpcChannel(&quot;ipc_test&quot;), false);
      RemotingConfiguration.RegisterWellKnownServiceType(typeof(TestServer), &quot;TestService&quot;, WellKnownObjectMode.Singleton);
      Context.RegisterDynamicProperty(new MyDynamicSinkProvider(), null, Context.DefaultContext);

      // Get proxy to remote server
      TestServer server = (TestServer)Activator.GetObject(typeof(TestServer), &quot;ipc://ipc_test/TestService&quot;);

      // Execute remote method without exception
      server.TestMethod(false);

      // Execute remote method raising exception
      try { server.TestMethod(true); }
      catch { }
    }

    // Server class
    class TestServer : MarshalByRefObject
    {
      public string TestMethod(bool throwException)
      {
        if (throwException)
          throw new Exception(&quot;TestException&quot;);
        return &quot;Hello&quot;;
      }
    }

    // Dynamic message sink 
    public class MyDynamicMessageSink : IDynamicMessageSink
    {
      public void ProcessMessageStart(IMessage reqMsg, bool bCliSide, bool bAsync)
      { }

      public void ProcessMessageFinish(IMessage replyMsg, bool bCliSide, bool bAsync)
      {
        // Don&#39;t handle messages on client side
        if (bCliSide) return;

        Console.WriteLine(&quot;*** Executing IDynamicMessageSink.ProcessMessageFinish()&quot;);

        // Check replyMsg type
        Console.WriteLine(&quot;replyMsg is instance of &quot; + (replyMsg as object).GetType().Name);

        // Get return value and exception 
        IMethodReturnMessage returnMessage = replyMsg as IMethodReturnMessage;
        if (returnMessage != null)
        {
          Console.WriteLine(&quot;ReturnValue: &quot; + (returnMessage.ReturnValue != null ? returnMessage.ReturnValue.ToString() : &quot;NULL&quot;));
          Exception e = returnMessage.Exception;
          Console.WriteLine(&quot;Exception: &quot; + (returnMessage.Exception != null ? returnMessage.Exception.Message : &quot;NULL&quot;));
        }
        else
          Console.WriteLine(&quot;replyMsg doesn&#39;t support IMethodReturnMessage&quot;);

        // Try to get return value from replyMsg properties
        Console.WriteLine(&quot;replyMsg.Properties[\&quot;__Return\&quot;]: &quot; + (replyMsg.Properties[&quot;__Return&quot;] != null ? replyMsg.Properties[&quot;__Return&quot;].ToString() : &quot;&lt;none&gt;&quot;));
        Console.WriteLine();
      }
    }

    // Dynamic message sink provider
    public class MyDynamicSinkProvider : IDynamicProperty, IContributeDynamicSink
    {
      IDynamicMessageSink IContributeDynamicSink.GetDynamicSink()
      { return new MyDynamicMessageSink(); }

      string IDynamicProperty.Name
      { get { return &quot;MyDynamicSinkProvider&quot;; } }
    }

  }
}


Program output in .NET Framework 4.0
=============================================
*** Executing IDynamicMessageSink.ProcessMessageFinish()
replyMsg is instance of ReturnMessage
ReturnValue: Hello
Exception: NULL
replyMsg.Properties[&quot;__Return&quot;]: Hello

*** Executing IDynamicMessageSink.ProcessMessageFinish()
replyMsg is instance of ReturnMessage
ReturnValue: NULL
Exception: TestException
replyMsg.Properties[&quot;__Return&quot;]: &lt;none&gt;

 
Program output in Mono 2.10.6
=============================================
*** Executing IDynamicMessageSink.ProcessMessageFinish()
replyMsg is instance of MethodCall
replyMsg doesn&#39;t support IMethodReturnMessage
replyMsg.Properties[&quot;__Return&quot;]: &lt;none&gt;

*** Executing IDynamicMessageSink.ProcessMessageFinish()
replyMsg is instance of MethodCall
replyMsg doesn&#39;t support IMethodReturnMessage
replyMsg.Properties[&quot;__Return&quot;]: &lt;none&gt;


Program output under Mono 2.10.6 with patch
==============================================
The same as in .NET Framework 4.0
                                       

<br>-- <br>Andrey Chernomyrdin<br></pre></div></div>