Professional Documents
Culture Documents
Migrasi Dari Net Remoting Ke WCF
Migrasi Dari Net Remoting Ke WCF
Applies to:
Migration
Summary: This article describes how to migrate an application that uses .NET Remoting to use Windows
Communication Foundation (WCF). It compares similar concepts between these products and then
describes how to accomplish several common Remoting scenarios in WCF.
Contents
Introduction .................................................................................................................................................. 2
Comparing .NET Remoting to WCF ............................................................................................................... 2
Server Implementation Comparison......................................................................................................... 2
Creating a Server in .NET Remoting ...................................................................................................... 2
Creating a Server in WCF ...................................................................................................................... 3
Client Implementation Comparison.......................................................................................................... 4
Creating a Client in .NET Remoting ....................................................................................................... 4
Creating a Client in WCF ....................................................................................................................... 4
Serialization Usage .................................................................................................................................... 5
Serialization in .NET Remoting .............................................................................................................. 5
Serialization in WCF .............................................................................................................................. 6
Exception Handling Capabilities ................................................................................................................ 6
Exceptions in .NET Remoting ................................................................................................................ 6
Exceptions and Faults in WCF ............................................................................................................... 7
Security Considerations ............................................................................................................................ 8
Security in .NET Remoting..................................................................................................................... 8
Security in WCF ..................................................................................................................................... 8
Migrating to WCF .......................................................................................................................................... 8
Why Migrate from Remoting to WCF? ..................................................................................................... 8
Migration Recommendations ................................................................................................................... 8
Migration Scenarios .................................................................................................................................. 9
Scenario 1: Service Returns an Object by Value ................................................................................. 10
Scenario 2: Server Returns an Object By Reference ........................................................................... 12
Scenario 3: Client Sends Server a By-Value Instance .......................................................................... 16
Summary ..................................................................................................................................................... 17
Introduction
.NET Remoting is a legacy product that is supported only for backward compatibility. It is not secure
across mixed-trust environments because it cannot maintain the separate trust levels between client
and server. For example, you should never expose a .NET Remoting endpoint to the Internet or to
untrusted clients. We recommend existing Remoting applications be migrated to newer and more
secure technologies. If the application’s design uses only Http and is RESTful, we recommend ASP.NET
Web API. Learn more at ASP.NET Web API. If the application is based on SOAP or requires non-Http
protocols such as TCP, we recommend WCF. Learn more at Windows Communication Foundation.
This article compares the two technologies and provides recommendations for migrating to WCF.
The following chart summarizes the main similarities and differences between .NET Remoting and WCF.
The public methods of this server type become the public contract available to clients. There is no
separation between the server’s public interface and its implementation – one type handles both.
Once the server type has been defined, it can be made available to clients like this:
TcpChannel channel = new TcpChannel(8080);
ChannelServices.RegisterChannel(channel, ensureSecurity : true);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(RemotingServer),
"RemotingServer",
WellKnownObjectMode.Singleton);
Console.WriteLine("RemotingServer is running. Press ENTER to terminate...");
Console.ReadLine();
There are many ways to make the Remoting type available as a server, including using configuration
files. This is just one example.
Once these types have been defined, the WCF server can be made available to clients like this1:
NetTcpBinding binding = new NetTcpBinding();
Uri baseAddress = new Uri("net.tcp://localhost:8000/wcfserver");
1
We use TCP in both examples to keep them as similar as possible. Refer to the scenario walk-throughs for use of
Http.
}
There are many ways to configure and to host WCF services. This is just one example, known as “self-
hosted”. Refer to these topics for more details:
Configuring WCF
Hosting WCF
This example shows programming at the “channel level” because it is most similar to the Remoting
example. Also available is the “Add Service Reference” approach in Visual Studio that generates code to
simplify client programming.
Serialization Usage
Both .NET Remoting and WCF use serialization to send objects between client and server, but they differ
in these important ways:
By value – the values of the object are serialized across tier boundaries, and a new instance of
that object is created on the other tier. Any calls to methods or properties of that new instance
execute only locally and do not affect the original object or tier.
By reference – a special “object reference” is serialized across tier boundaries. When one tier
interacts with methods or properties of that object, it communicates back to the original object
on the original tier. By-reference objects can flow in either direction – server to client, or client
to server.
By-value types in Remoting are marked with the [Serializable] attribute or implement ISerializable, like
this:
[Serializable]
public class RemotingCustomer
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int CustomerId { get; set; }
}
For this reason, the use of .NET Remoting is recommended only within fully trusted environments.
Exposing a public .NET Remoting endpoint to untrusted clients will make a Remoting server vulnerable
to attack.
Serialization in WCF
WCF supports only by-value serialization. The most common way to define a type to exchange between
client and server is like this:
[DataContract]
public class WCFCustomer
{
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
[DataMember]
public int CustomerId { get; set; }
}
The [DataContract] attribute identifies this type as one that can be serialized and deserialized between
client and server. The [DataMember] attribute identifies the individual properties or fields to serialize.
When WCF sends an object across tiers, it serializes only the values and creates a new instance of the
object on the other tier. Any interactions with the values of the object occur only locally – they do not
communicate with the other tier the way .NET Remoting by-reference objects do.
Though this design is convenient during development, server-side information can inadvertently be
disclosed to the client. This is one of many reasons Remoting should be used only in fully trusted
environments.
Exceptions and Faults in WCF
WCF does not allow arbitrary exception types to be returned from the server to the client because it
could lead to inadvertent information disclosure. If some service operation throws an unexpected
exception, it causes a general purpose FaultException to be thrown on the client. This exception does
not carry any information why or where the problem occurred, and for some applications this is
sufficient.
Applications that need to communicate richer error information to the client do this by defining a “fault
contract”. To do this, first create a [DataContract] type to carry the fault information, like this:
[DataContract]
public class CustomerServiceFault
{
[DataMember]
public string ErrorMessage { get; set; }
[DataMember]
public int CustomerId {get;set;}
}
And specify the fault contract to use for each service operation, like this:
[ServiceContract]
public interface IWCFServer
{
[OperationContract]
[FaultContract(typeof(CustomerServiceFault))]
Customer GetCustomer(int customerId);
}
Whenever the client makes a request to the server, it can catch faults as normal exceptions, like this:
try
{
Customer customer = server.GetCustomer(-1);
}
catch (FaultException<CustomerServiceFault> fault)
{
Console.WriteLine(String.Format("Fault received: {0}",
fault.Detail.ErrorMessage));
}
Despite this support, you should consider .NET Remoting an unsecure communication protocol and use
it only within fully trusted environments. Never expose a public Remoting endpoint to the Internet or
untrusted clients.
Security in WCF
WCF was designed with security in mind, in part to address the kinds of vulnerabilities found in .NET
Remoting. WCF offers security at both the transport and message level, and offers many options for
authentication, authorization, encryption, etc.
Migrating to WCF
Why Migrate from Remoting to WCF?
.NET Remoting is a legacy product
As described in .NET Remoting, it is considered a legacy product and is not recommended for
new development. WCF or ASP.NET Web API are recommended for new and existing
applications.
Migration Recommendations
Following are the recommended steps to migrate from Remoting to WCF.
Create the service contract
Define your service interface types, and mark them with the [ServiceContract] attribute.
Mark all the methods the clients will be allowed to call with [OperationContract].
Once a Remoting application has been migrated to WCF, it is still important to remove dependencies on
.NET Remoting. This ensures that any Remoting vulnerabilities are removed from the application. These
steps include:
Migration Scenarios
Now let’s put the pieces together to see how to accomplish these common Remoting scenarios in WCF:
Sending an object by-reference from the client to the server is not allowed in WCF.
To discuss these scenarios, assume our baseline interfaces for .NET Remoting look like the following
example. The .NET Remoting implementation is not important here because we want to illustrate only
how to use WCF to implement equivalent functionality.
public class RemotingServer : MarshalByRefObject
{
// Demonstrates server returning object by-value
public Customer GetCustomer(int customerId) {…}
[OperationContract]
bool UpdateCustomer(Customer customer);
}
If we want derived types to be allowed, we must use the [KnownType] attribute to identify them. The
only types WCF will allow to be serialized or deserialized for this service are those in the service
interface and these “known types”. Attempting to exchange any other type not in this list will be
rejected.
[DataContract]
[KnownType(typeof(PremiumCustomer))]
public class Customer
{
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
[DataMember]
public int CustomerId { get; set; }
}
[DataContract]
public class PremiumCustomer : Customer
{
[DataMember]
public int AccountId { get; set; }
}
And the WCF service can be started with code like this:
ServiceHost customerServiceHost = new ServiceHost(typeof(CustomerService));
customerServiceHost.Open();
When this ServiceHost is started, it uses the web.config file to establish the proper contract, binding and
endpoint. Learn more about configuration files at Configuring Services Using Configuration Files
This style of starting the server is known as self-hosting and is just one example. To learn more about
other choices for hosting WCF services, refer to Hosting Services .
Learn more about “Add Service Reference” at How to: Add, Update, or Remove a Service Reference.
Summary
Objects returned by WCF from the server to the client are always by value. The objects are deserialized
copies of the data sent by the server. The client can call methods on these local copies without any
danger of invoking server code through callbacks.
As mentioned above, objects returned by a WCF service are always by value, so there is no direct
equivalent of a by-reference object. But it is possible to achieve something similar to by-reference
semantics using an EndpointAddress10 object. This is a serializable by-value object that can be used by
the client to obtain a session-full by-reference object on the server. This enables the scenario of having
multiple clients with independent session-full server-side objects.
[OperationContract]
void SetCurrentValue(string value);
}
Notice that the session-full object is itself marked with [ServiceContract], making it a normal WCF
service interface. Setting the SessionMode property indicates it will be a session-full service. In WCF, a
session is a way of correlating multiple messages sent between two endpoints. This means that once a
client obtains a connection to this service, a session will be established between the client and the
server. The client will use a single unique instance of the server-side object for all its interactions within
this single session.
Next, we need to provide the implementation of this service interface. By marking it with
[ServiceBehavior] and setting the InstanceContextMode, we tell WCF we want to use a unique instance
of this type for an each session.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class MySessionBoundObject : ISessionBoundObject
{
private string _value;
Step 2: Define the WCF Factory Service for this Session-Full Object
Now we need a way to obtain an instance of this session-full object. We do this by creating another
WCF service interface that returns an EndpointAddress10 object. This is a serializable form of an
endpoint that the client can use to create the session-full object.
[ServiceContract]
public interface ISessionBoundFactory
{
[OperationContract]
EndpointAddress10 GetInstanceAddress();
}
public SessionBoundFactory()
{
}
This implementation maintains a singleton channel factory to create session-full objects. When
GetInstanceAddress() is called, it creates a channel and creates an EndpointAddress10 object that
effectively points to the remote address associated with this channel. EndpointAddress10 is just a data
type that can be returned to the client by-value.
1. Declare a <client> section that describes the endpoint for the session-full object. This is
necessary because the server also acts as a client in this situation.
2. Declare endpoints for the factory and session-full object. This is necessary to allow the client to
communicate with the service endpoints to acquire the EndpointAddress10 and to create the
session-full channel.
<configuration>
<system.serviceModel>
<client>
<endpoint name="sessionbound"
address="net.tcp://localhost:8081/SessionBoundObject"
binding="netTcpBinding"
contract="Shared.ISessionBoundObject"/>
</client>
<services>
<service name="Server.CustomerService">
<endpoint address="http://localhost:8083/CustomerService"
binding="basicHttpBinding"
contract="Shared.ICustomerService" />
</service>
<service name="Server.MySessionBoundObject">
<endpoint address="net.tcp://localhost:8081/SessionBoundObject"
binding="netTcpBinding"
contract="Shared.ISessionBoundObject" />
</service>
<service name="Server.SessionBoundFactory">
<endpoint address="net.tcp://localhost:8081/SessionBoundFactory"
binding="netTcpBinding"
contract="Shared.ISessionBoundFactory" />
</service>
</services>
</system.serviceModel>
</configuration>
ChannelFactory<ISessionBoundFactory> channelFactory =
new ChannelFactory<ISessionBoundFactory>("factory");
ISessionBoundFactory sessionFactory = channelFactory.CreateChannel();
EndpointAddress10 address1 = sessionFactory.GetInstanceAddress();
EndpointAddress10 address2 = sessionFactory.GetInstanceAddress();
ChannelFactory<ISessionBoundObject> sessionObjectFactory1 =
new ChannelFactory<ISessionBoundObject>(new NetTcpBinding(),
address1.ToEndpointAddress());
ChannelFactory<ISessionBoundObject> sessionObjectFactory2 =
new ChannelFactory<ISessionBoundObject>(new NetTcpBinding(),
address2.ToEndpointAddress());
sessionInstance1.SetCurrentValue("Hello");
sessionInstance2.SetCurrentValue("World");
Summary
WCF always returns objects by value, but it is possible to support the equivalent of by-reference
semantics through the use of EndpointAddress10. This permits the client to request a session-full WCF
service instance, after which it can interact with it like any other WCF service.
ChannelFactory<ICustomerService> factory =
new ChannelFactory<ICustomerService>("customerservice");
ICustomerService service = factory.CreateChannel();
PremiumCustomer customer = new PremiumCustomer {
FirstName = "Bob",
LastName = "Jones",
CustomerId = 43,
AccountId = 99 };
bool success = service.UpdateCustomer(customer);
Console.WriteLine(String.Format(" Server returned {0}.", success));
The customer object will be serialized, and sent to the server, where it is deserialized into a new copy of
that object. Note that this code also illustrates sending a derived type (PremiumCustomer). The service
interface expects a Customer object, but the [KnownType] attribute on the Customer class indicated
PremiumCustomer was also allowed. WCF will fail any attempt to serialize or deserialize any other type
through this service interface.
Summary
Normal WCF exchanges of data are by value. This guarantees that invoking methods on one of these
data objects executes only locally – it will not invoke code on the other tier.
And while it is possible to achieve something like by-reference objects returned from the server, it is not
possible for a client to pass a by-reference object to the server.
A scenario that requires a conversation back and forth between client and server can be achieve in WCF
using a “duplex” service. Read more about that at Duplex Services.
Summary
.NET Remoting is a communication framework intended to be used only within fully trusted
environments. It is a legacy product and supported only for backward compatibility. It should not be
used to build new applications.
WCF, on the other hand, was designed with security in mind and is recommended for new and existing
applications.
Microsoft recommends that existing Remoting applications be migrated to use WCF or ASP.NET Web API
instead.