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 |
---|
.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
Save all the files in a directory named RemoteIIS.
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
Create a \bin subdirectory and copy
ServiceClass.dll
into that directory.Create an application in IIS. Make the application alias "HttpBinary" and set the source directory to the "RemoteIIS" directory.
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 andGetServerString
will return"***unavailable***"
for the user alias. To prevent this from occuring, deselect anonymous access.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)