Calling Method on Client from Method on Server

AaronP

New member
Joined
Oct 10, 2007
Messages
1
Programming Experience
1-3
The code below is for a simple Client Activated Object. What I am trying to do is initiate a call to a method on the client from a method on the server. In this case the method on the server is sub simpletest.

Specifically, I want sub simpletest to raise a messagebox on the client and return the dialog result back to simpletest.

I have seen a number of "Broadcast/Listener" and "Teleconference" examples, but I can't seem to make the leap from these application examples to what I am trying to do. I think the difference is that the call to the client in my case is initiated from the server, and I need the call from the server to go to a specific client. To clarify, the client will call simpletest on the server, and simpletest will call the method on the client to raise the messagebox. From my readings, it seems that a CallContext is needed to ensure that I get to the calling client. On the other hand, it seems to me that if I am working with a CAO, then the client should be known to the server since each client will create it's own instance of simpletest.

Any help would be appreciated.



Here is the very simple code I am running:

************* Interface:

VB.NET:
Option Explicit On 
Option Strict On 

Imports System 
Imports System.Runtime.Remoting.Messaging 

Public Interface ISimpleInterface 

    Function simpletest(ByVal _int As Integer) As Integer 

End Interface

********** Server:
VB.NET:
Imports System 
Imports System.Runtime.Remoting 
Imports System.Runtime.Remoting.Channels.Http 
Imports System.Runtime.Remoting.Channels.tcp 
Imports System.Runtime.Remoting.Channels 
Imports SimpleInterface 



Public Class TestServer 
    Inherits MarshalByRefObject 
    Implements ISimpleInterface 



    Public Function simpletest(ByVal _int As Integer) As Integer Implements ISimpleInterface.simpletest 
        Console.WriteLine("Start Function Simple Test: " & _int.ToString & Chr(10)) 

        Dim NewInt As Integer 
        '***************** 
        'Need to add code here that will call or raise messagebox.show on the client 
        'the dialogresult will then need to be passed back to the server. 
        'Ideally the call will be a function on the client. 
        'for example, dialogresult may affect the final value of NewInt. 
        '***************** 
        'Dim dr As DialogResult 
        'If dr = DialogResult.No Then 
        'NewInt = _int * 10 
        'else if dr = DialogResult.Yes then 

        NewInt = _int * 1000 

        'end if 

        Return NewInt 

    End Function 

End Class 


Module ServerStartup 

    Sub main() 
        Console.WriteLine("GetGuiTest Server Startup Module Invoked") 


        Dim serverProv As BinaryServerFormatterSinkProvider = New BinaryServerFormatterSinkProvider 
        serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full 

        Dim clientProv As BinaryClientFormatterSinkProvider = New BinaryClientFormatterSinkProvider 

        Dim props As IDictionary = New Hashtable 
        props.Add("port", 1234) 
        'Dim chnl As New HttpChannel(1234) 
        Dim chnl As HttpChannel = New HttpChannel(props, clientProv, serverProv) 
        ChannelServices.RegisterChannel(chnl) 
        RemotingConfiguration.ApplicationName = "MyServer" 
        RemotingConfiguration.RegisterActivatedServiceType( _ 
        GetType(TestServer)) 


        Console.ReadLine() 
    End Sub 


End Module

I created the shared generated_metadata.dll for the client using Soapsuds with the following command:
soapsuds -ia:Server -nowp -oa:generated_metadata.dll



*************** Client Code

VB.NET:
Imports System 
Imports System.Runtime.Remoting 
Imports System.Runtime.Remoting.Channels.http 
Imports System.Runtime.Remoting.Channels.tcp 
Imports System.Runtime.Remoting.Channels 
Imports System.Reflection 
Imports System.text 


Public Class Form1 
    Inherits System.Windows.Forms.Form 
    Public Shared CAOServer As Server.TestServer 

#Region " Windows Form Designer generated code " 

    Public Sub New() 
        MyBase.New() 

        'This call is required by the Windows Form Designer. 
        InitializeComponent() 

        'Add any initialization after the InitializeComponent() call 
        Dim serverProv As BinaryServerFormatterSinkProvider = New BinaryServerFormatterSinkProvider 
        serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full 

        Dim clientProv As BinaryClientFormatterSinkProvider = New BinaryClientFormatterSinkProvider 

        Dim props As IDictionary = New Hashtable 
        props.Add("port", 0) 
        Dim channel As HttpChannel = New HttpChannel(props, clientProv, serverProv) 
        'Dim channel As New HttpChannel 
        ChannelServices.RegisterChannel(channel) 
        RemotingConfiguration.RegisterActivatedClientType( _ 
                      GetType(Server.TestServer), "http://AARONDEVL:1234/MyServer") 

        '************* 

        CAOServer = New Server.TestServer 

    End Sub 

    'Form overrides dispose to clean up the component list. 
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean) 
        If disposing Then 
            If Not (components Is Nothing) Then 
                components.Dispose() 
            End If 
        End If 
        MyBase.Dispose(disposing) 
    End Sub 

    'Required by the Windows Form Designer 
    Private components As System.ComponentModel.IContainer 

    'NOTE: The following procedure is required by the Windows Form Designer 
    'It can be modified using the Windows Form Designer. 
    'Do not modify it using the code editor. 
    Friend WithEvents Button1 As System.Windows.Forms.Button 
    Friend WithEvents TextBox1 As System.Windows.Forms.TextBox 
    Friend WithEvents TextBox2 As System.Windows.Forms.TextBox 
    Friend WithEvents TextBox3 As System.Windows.Forms.TextBox 
    Friend WithEvents Button2 As System.Windows.Forms.Button 
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent() 
        Me.Button1 = New System.Windows.Forms.Button 
        Me.TextBox1 = New System.Windows.Forms.TextBox 
        Me.TextBox2 = New System.Windows.Forms.TextBox 
        Me.TextBox3 = New System.Windows.Forms.TextBox 
        Me.Button2 = New System.Windows.Forms.Button 
        Me.SuspendLayout() 
        ' 
        'Button1 
        ' 
        Me.Button1.Location = New System.Drawing.Point(24, 16) 
        Me.Button1.Name = "Button1" 
        Me.Button1.TabIndex = 0 
        Me.Button1.Text = "Button1" 
        ' 
        'TextBox1 
        ' 
        Me.TextBox1.Location = New System.Drawing.Point(24, 48) 
        Me.TextBox1.Name = "TextBox1" 
        Me.TextBox1.TabIndex = 1 
        Me.TextBox1.Text = "100" 
        ' 
        'TextBox2 
        ' 
        Me.TextBox2.Location = New System.Drawing.Point(24, 80) 
        Me.TextBox2.Name = "TextBox2" 
        Me.TextBox2.TabIndex = 2 
        Me.TextBox2.Text = "TextBox2" 
        ' 
        'TextBox3 
        ' 
        Me.TextBox3.Location = New System.Drawing.Point(24, 112) 
        Me.TextBox3.Multiline = True 
        Me.TextBox3.Name = "TextBox3" 
        Me.TextBox3.Size = New System.Drawing.Size(240, 128) 
        Me.TextBox3.TabIndex = 4 
        Me.TextBox3.Text = "TextBox3" 
        ' 
        'Button2 
        ' 
        Me.Button2.Location = New System.Drawing.Point(176, 16) 
        Me.Button2.Name = "Button2" 
        Me.Button2.TabIndex = 5 
        Me.Button2.Text = "Button2" 
        ' 
        'Form1 
        ' 
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13) 
        Me.ClientSize = New System.Drawing.Size(292, 273) 
        Me.Controls.Add(Me.Button2) 
        Me.Controls.Add(Me.TextBox3) 
        Me.Controls.Add(Me.TextBox2) 
        Me.Controls.Add(Me.TextBox1) 
        Me.Controls.Add(Me.Button1) 
        Me.Name = "Form1" 
        Me.Text = "Form1" 
        Me.ResumeLayout(False) 

    End Sub 

#End Region 

    Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click 

        Me.TextBox2.Text = CAOServer.simpletest(CType(Me.TextBox1.Text, Integer)).ToString 

    End Sub 



    'Private Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click 
    ' MessageBox.Show("xxx?", _ 
    ' "Question for You", _ 
    ' MessageBoxButtons.YesNo, _ 
    ' MessageBoxIcon.Question, _ 
    ' MessageBoxDefaultButton.Button1, _ 
    ' MessageBoxOptions.RightAlign) 
    'End Sub 
End Class
 
Last edited by a moderator:
What you're askin can be done, but I don't think it is a good idea at all. You'd have to make another interface that the client implements, and either pass the entire client to the server and have it call the method on the interface, or pass a delegate pointing the function to the server. Very dodge.

Why arn't you just messageboxing before you call simpletest, and passing the result as another parameter.

Or, if you need information from simpletest to display in the MessageBox, just have two functions on the server interface.

ie

Call GetInfoFromServer on server
MessageBox that Info
Call Simpletest and pass the result from the message box aswell as your testbox number.
 
Back
Top