Remoting Example: Hosting in Internet Information Services (IIS)

This topic is specific to a legacy technology that is retained for backward compatibility with existing applications and is not recommended for new development. Distributed applications should now be developed using the Windows Communication Foundation (WCF).

The following sample implements a basic Web service with a few complications. The BinaryFormatter is used because the payload is more compact and the system takes less time to serialize and deserialize the stream. In addition, if Internet Information Services (IIS) is using Windows Integrated Authentication (also known as NTLM authentication), the server authenticates the client and then returns to the client the identity that IIS was able to authenticate. Finally, you can help protect your Web service by changing the URL in the client configuration file to use "https" as the protocol scheme and configuring IIS to require Secure Sockets Layer (SSL) encryption for that virtual directory (the sample does not demonstrate this process).

Caution noteCaution

.NET Framework remoting does not do authentication or encryption by default. Therefore, it is recommended that you take all necessary steps to make certain of the identity of clients or servers before interacting with them remotely. Because .NET Framework remoting applications require FullTrust permissions to execute, if an unauthorized client were granted access on your server, the client could execute code as though it were fully trusted. Always authenticate your endpoints and encrypt the communication streams, either by hosting your remoted types in IIS or by building a custom channel sink pair to do this work.

To compile and run this sample

  1. Save all the files in a directory named RemoteIIS.

  2. Compile the entire sample by typing the following commands at the command prompt:

    [Visual Basic]

    vbc /t:library ServiceClass.vb
    vbc /r:System.Runtime.Remoting.dll /r:ServiceClass.dll Client.vb
    

    [C#]

    csc /t:library ServiceClass.cs
    csc /r:System.Runtime.Remoting.dll /r:ServiceClass.dll Client.cs
    
  3. Create a \bin subdirectory and copy ServiceClass.dll into that directory.

  4. Create an application in IIS. Make the application alias "HttpBinary" and set the source directory to the "RemoteIIS" directory.

  5. Set the authentication method for this virtual directory to Integrated Windows Authentication (formerly NTLM authentication). If anonymous access is selected, HttpContext.Current.User.Identity.Name will be null and GetServerString will return "***unavailable***" for the user alias. To prevent this from occuring, deselect anonymous access.

  6. Make sure that IIS is started; at the command prompt in the "RemoteIIS" directory, type client.

This application runs on a single computer or across a network. If you want to run this application over a network, you must replace "localhost" in the client configuration with the name of the remote computer.

ServiceClass

[Visual Basic]

Imports System
Imports System.Runtime.Remoting
Imports System.Web

Public Interface IService
    Function GetServerTime() As DateTime
    Function GetServerString() As String
End Interface

Public Class ServiceClass
    Inherits MarshalByRefObject
    Implements IService

    Private InstanceHash As Integer

    Public Sub New()
        InstanceHash = Me.GetHashCode()
    End Sub

    Public Function GetServerTime() As Date Implements IService.GetServerTime
        Return DateTime.Now
    End Function

    Public Function GetServerString() As String Implements IService.GetServerString
        ' Use the HttpContext to acquire what IIS thinks the client's identity is.
        Dim temp As String = HttpContext.Current.User.Identity.Name

        If (temp Is Nothing Or temp.Equals(String.Empty)) Then
            temp = "**unavailable**"
        End If

        Return "Hi there. You are being served by instance number: " _
            & InstanceHash.ToString() _
            & ". Your alias is: " _
            & temp
    End Function
End Class

[C#]

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Threading;
using System.Web;

public interface IService
{
   DateTime GetServerTime();
   string GetServerString();
}

// IService exists to demonstrate the possibility of publishing only the interface.
public class ServiceClass : MarshalByRefObject, IService
{
   private int InstanceHash;

   public ServiceClass()
   {
      InstanceHash = this.GetHashCode();
   }

   public DateTime GetServerTime()
   {
      return DateTime.Now;
   }

   public string GetServerString()
   {
      // Use the HttpContext to acquire what IIS thinks the client's identity is.
      string temp = HttpContext.Current.User.Identity.Name;
      if (temp == null || temp.Equals(string.Empty))
         temp = "**unavailable**";
      return "Hi there. You are being served by instance number: " 
         + InstanceHash.ToString() 
         + ". Your alias is: " 
         + temp;
   }
}

Web.config

<configuration>
   <system.runtime.remoting>
      <application>
         <service>
            <wellknown 
               mode="SingleCall" objectUri="SAService.rem"
               type="ServiceClass, ServiceClass"/>
         </service>
         <channels>
            <channel ref="http"/>
         </channels>
      </application>
   </system.runtime.remoting>
</configuration>

Client

[Visual Basic]

Imports System
Imports System.Collections
Imports System.Net
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Security.Principal

Public Class Client

    Public Shared Sub Main()
        ' Tells the system about the remote object and customizes the HttpChannel
        ' to use the binary formatter (which understands that base64 encoding is needed).
        RemotingConfiguration.Configure("Client.exe.config", False)

        ' New proxy for the ServiceClass.
        ' If you publish only the IService interface, you must use Activator.GetObject.
        Dim service As ServiceClass = New ServiceClass()

        ' Programmatically customizes the properties given to the channel. This sample uses the
        '  application configuration file.
        Dim Props As IDictionary = ChannelServices.GetChannelSinkProperties(service)
        Props.Item("credentials") = CredentialCache.DefaultCredentials

        ' Reports the client identity name.
        Console.WriteLine("ConsoleIdentity: " & WindowsIdentity.GetCurrent().Name)

        ' Writes what the server returned.
        Console.WriteLine("The server says : " & service.GetServerString())
        Console.WriteLine("Server time is: " & service.GetServerTime())
    End Sub
End Class

[C#]

using System;
using System.Collections;
using System.Net;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Security.Principal;

class Client
{
    static void Main(string[] args)
    {
        // Tells the system about the remote object and customizes the HttpChannel
        // to use the binary formatter (which understands that base64 encoding is needed).
        RemotingConfiguration.Configure("Client.exe.config", false);

        // New proxy for the ServiceClass.
        // If you publish only the IService interface, you must use Activator.GetObject.
        ServiceClass service = new ServiceClass();

        // Programmatically customizes the properties given to the channel. This sample uses the
        // application configuration file.
        IDictionary Props = ChannelServices.GetChannelSinkProperties(service);
        Props["credentials"] = CredentialCache.DefaultCredentials;

        // Reports the client identity name.
        Console.WriteLine("ConsoleIdentity: " + WindowsIdentity.GetCurrent().Name);

        // Writes what the server returned.
        Console.WriteLine("The server says : " + service.GetServerString());
        Console.WriteLine("Server time is: " + service.GetServerTime());
    }
}

Client.exe.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.runtime.remoting>
    <application>
      <channels>
        <channel ref="http" useDefaultCredentials="true" port="0">
          <clientProviders>
            <formatter 
               ref="binary"
                  />
          </clientProviders>
        </channel>
      </channels>
      <client>
        <wellknown 
           url="https://localhost:80/HttpBinary/SAService.rem"
           type="ServiceClass, ServiceClass"
            />
      </client>
    </application>
  </system.runtime.remoting>
</configuration>

See Also

Concepts

Configuration of Remote Applications
Hosting Remote Objects in Internet Information Services (IIS)

Other Resources

Remoting Examples