Friday, July 3, 2009

The ABCs Of Programming Windows Communication Foundation

Learn The ABCs Of Programming Windows Communication Foundation



 The WCF programming model
 Defining contracts and behavior
 Hosting a service and defining endpoints
 Creating and configuring clients

THIS ARTICLE USES THE FOLLOWING TECHNOLOGIES:
.NET Framework 2.0, WCF, WSDL, SOAP

WCF Programming Model
Service Contracts and Dispatch Behavior
Data Contracts
Message and Service Contracts
Implementing Service Contracts
Hosting the Service and Defining Endpoints
Choosing and Customizing Bindings
Opening the Host
Configuring Service Endpoints
Using Activation Services
Programming Clients
Configuring Client Endpoints
Generating Client Proxies
Logging Messages


Conclusion
Windows® Communication Foundation (WCF), formerly code-named "Indigo," is about to radically change the face of distributed programming for developers using the Microsoft® .NET Framework. WCF unifies the existing suite of .NET distributed technologies into a single programming model that improves the overall developer experience through a consistent architecture, new levels of functionality and interoperability, and all the extensibility points you could want. This article introduces you to WCF programming and shows you how to get started.
As its name suggests, WCF provides the .NET Framework with a basis for writing code to communicate across components, applications, and systems. WCF was designed according to the tenets of service orientation. A service is a piece of code you interact with through messages. Services are passive. They wait for incoming messages before doing any work. Clients are the initiators. Clients send messages to services to request work.




Figure 1 Services and Endpoints
Services expose one or more endpoints where messages can be sent. Each endpoint consists of an address, a binding, and a contract (see Figure 1). The address specifies where to send messages. The binding describes how to send messages. And the contract describes what the messages contain. Clients need to know this information before they can access a service.
Services can package up endpoint descriptions to share with clients, typically by using Web Services Description Language (WSDL). Then clients can use the provided service description to generate code within their environment capable of sending and receiving the proper messages (see Figure 2).





Figure 2 Sharing Endpoint Descriptions
Windows Communication Foundation provides a new library of classes found in the System.ServiceModel namespace that bring these service-oriented concepts to life. This is what's typically referred to as the WCF programming model.

WCF Programming Model
With WCF, you're either writing services that expose endpoints or you're writing clients that interact with endpoints. Hence, endpoints are central to the WCF programming model and infrastructure. WCF models endpoints with the .NET classes and interfaces shown in Figure 3. This mapping is true whether you're writing WCF clients or services.

Figure 3 WCF Classes and Interfaces

Element Class or Interface
Endpoint System.ServiceModel.ServiceEndpoint
Address System.Uri
Binding System.ServiceModel.Binding
Contract Interfaces annotated with System.ServiceModel attributes
When building a WCF service, you typically start by defining a .NET interface definition to serve as the service contract. Then you implement the service contract in a .NET class, known as the service type, and configure its behavior. Next, you define the endpoints the service will expose, specifying the address, binding, and contract for each one. Finally, you host the service type in an application using the WCF hosting infrastructure. Once the service type is hosted, clients can retrieve its endpoint descriptions and begin integrating with it.
When building a WCF client, you first need the description of the target endpoint you want to access. The endpoint description can be used to dynamically create a typed proxy. WCF provides a tool named SvcUtil.exe for automating this process. Then you can write code against the typed proxy to access the service by sending the appropriate messages to the target endpoint.

Service Contracts and Dispatch Behavior
You model service contracts in .NET using traditional C# interface definitions. You can use any .NET interface as a starting point, such as the one shown here:

namespace ServiceLibrary
{
public interface IEchoService
{
string Echo(string msg);
}
}
To make this a WCF service contract, you must annotate the interface itself with [ServiceContract] and each operation you want to expose with [OperationContract]:


using System.ServiceModel;

namespace ServiceLibrary
{
[ServiceContract(Namespace="http://example.org/echo/")]
public interface IEchoService
{
[OperationContract]
string Echo(string msg);
}
}
These attributes influence the mapping between the worlds of .NET and SOAP. WCF uses the information found in the service contract to perform dispatching and serialization. Dispatching is the process of deciding which method to call for an incoming SOAP message. Serialization is the process of mapping between the data found in a SOAP message and the corresponding .NET objects used in the method invocation. This mapping is controlled by an operation's data contract.
WCF dispatches based on the message action. Each method in a service contract is automatically assigned an action value based on the service namespace and method name. For example, the default action for the Echo method just shown is http://example.org/echo/Echo. You can customize the action value for each method using [OperationContract]. A value of * can be used for any action when a specific match doesn't exist.
In the following example, WCF will dispatch messages with an action of urn:echo:string to the Echo method. Messages with any other action are dispatched to the EchoMessage method:


[ServiceContract(Namespace="http://example.org/echo/")]
public interface IEchoService
{
[OperationContract(Action="urn:echo:string")]
string Echo(string msg);

[OperationContract(Action="*")]
Message EchoMessage(Message msg);
}

Data Contracts
Once the target method has been determined based on the action, WCF relies on the method's data contract to perform serialization. The data contract is defined by the types used in the method signature. In the previous example, EchoMessage is generic and could be used to process a variety of incoming SOAP messages. Therefore I've used Message to model the input and output. Message is a special type used to represent all messages flowing through WCF. When using Message, WCF does not perform type-based serialization. Instead, it just gives you direct access to what's found in the SOAP message.
When Message is not used, WCF performs serialization to map between the data found in the SOAP message and the corresponding .NET objects needed to invoke the method. For example, in the case of Echo, WCF maps the SOAP payload to a .NET string. WCF provides an implicit mapping for all .NET primitive types (string, int, double, and so on).
The way WCF serializes .NET classes depends on the serialization engine in use. The default serialization engine is known as DataContract, a simplified version of XmlSerializer, the default serialization engine used in ASMX today. DataContract defines attributes for annotating class definitions to influence the serialization process. Here's an example of it in use:


[DataContract(Namespace="http://example.org/person")]
public class Person
{
[DataMember(Name="first", Order=0)]
public string First;
[DataMember(Name="last", Order=1)]
public string Last;
[DataMember(IsRequired=false, Order=2)]
private string id;
...
}
With DataContract, only fields marked with DataMember will be serialized. And you can serialize private fields. This is much different from the way XmlSerializer works. Now you can use Person in an operation contract:

[ServiceContract(Namespace="http://example.org/echo/")]
public interface IEchoService
{
... // previous methods omitted

[OperationContract]
Person EchoPerson(Person p);
}
When EchoPerson is invoked, WCF will serialize Person instances according to the DataContract attributes specified on the Person class. DataContract produces a very simple XML structure—a sequence of elements. You can control the name of each element, the order, and whether a particular element is required, but that's about it.
If you need to do anything more sophisticated, WCF lets you fall back to using XmlSerializer. You indicate your desire to use XmlSerializer by annotating the interface with [XmlSerializerFormat]:

[ServiceContract]
[XmlSerializerFormat]
public interface IEchoService { ... }
This tells WCF to use XmlSerializer for all types in the contract, according to the XmlSerializer defaults and the various System.Xml.Serialization customization attributes. This makes it much easier to move existing ASMX services forward to WCF.
WCF also supports serializing types marked with [Serializable], which allows .NET remoting types to work with WCF without change. WCF provides an implicit mapping for [Serializable] types where all public/private fields are automatically serialized.

Message and Service Contracts
All of the examples up to this point have relied on WCF to automatically map the method signature to the SOAP message. The parameter list and return type are always mapped to the SOAP body for the request and response, respectively. If you need to support headers, you can write another class that models the structure of the entire SOAP envelope for the particular operation, specifying which fields map to headers versus the body. You define this mapping with the [MessageContract] attributes:


[MessageContract]
public class EchoPersonMessage
{
[MessageBody]
public Person Person;
[MessageHeader]
public Authorization Authorization;
}
In this example, the Person field is mapped to the SOAP body while the Authorization field is mapped to a SOAP header. Now you can use EchoPersonMessage in an operation contract:


[ServiceContract]
public interface IEchoService
{
... // previous methods omitted

[OperationContract]
void EchoPerson(EchoPersonMessage msg);
}
Using MessageContract is a more advanced technique that is only necessary when you need direct control over the SOAP contract.

Implementing Service Contracts
Now you can implement the service contract by simply implementing the .NET interface in a class:

using System.ServiceModel;
namespace ServiceLibrary
{
public class EchoService : IEchoService
{
public string Echo(string msg)
{
return msg;
}
... // remaining methods omitted
}
}
By doing this, EchoService is guaranteed to support the service contract defined by IEchoService. When using an interface to define the service contract, you don't need any contract-related attributes on the class definition. However, you may want to use [ServiceBehavior] to influence its local behavior:


using System.ServiceModel;

namespace ServiceLibrary
{
... // interface definition omitted

[ServiceBehavior(
InstanceContextMode=InstanceContextMode.Single,
ConcurrencyMode=ConcurrencyMode.Multiple)]
public class EchoService : IEchoService
{
...
This particular example tells WCF to manage a singleton instance of the service type and to allow multithreaded access to the instance. There is also an [OperationBehavior] attribute for controlling operation-level behavior.
Behaviors influence processing within the host, but have no impact on the service contract whatsoever. Behaviors are one of the primary WCF extensibility points. Any class that implements IServiceBehavior can be applied to a service through the use of a custom attribute or configuration element.

Hosting the Service and Defining Endpoints
To use EchoService, you need to host it in a .NET-based application. The ServiceHost class gives you direct control over the WCF hosting infrastructure. You instantiate ServiceHost based on a particular service type. The following code shows how to do this in a console application:

using System;
using System.ServiceModel;
using ServiceLibrary;

class Program
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(
typeof(EchoService), new Uri("http://localhost:8080/echo")))
{
...
In addition to specifying the service type, you also specify the base addresses for the different transports you plan to use. In this example, I've specified a base address of http://localhost:8080/echo. This will be used as the base for any relative HTTP addresses I might specify when adding endpoints. The base HTTP address is also used as the default for retrieving the service description.
You then add the service endpoints. Again, a service may have one or more endpoints and each endpoint consists of an address, a binding, and a contract. You provide this information to your ServiceHost by calling AddServiceEndpoint. This is where you specify the service contract you defined earlier (IEchoService). For the binding, you typically choose from one of the many predefined bindings that ship with WCF and an appropriate address given the binding's transport. Here's an example:


host.AddServiceEndpoint(typeof(IEchoService),
new BasicHttpBinding(), "svc");
host.AddServiceEndpoint(typeof(IEchoService),
new NetTcpBinding(), "net.tcp://localhost:8081/echo/svc");
In this particular example, I've specified IEchoService as the contract for both endpoints, but with each endpoint using a different binding and address. The first endpoint uses the BasicHttpBinding and a relative HTTP address of svc (which would make its absolute address http://localhost:8080/echo/svc). The second endpoint uses the NetTcpBinding and an address of net.tcp://localhost:8081/echo/svc. Therefore, this service allows consumers to communicate with it over either HTTP or TCP using different WS-* protocols, as defined by each binding.

Choosing and Customizing Bindings
The WCF infrastructure relies heavily on endpoint definitions to control how messages are processed. In fact, WCF uses the endpoint definitions to dynamically build the appropriate message processing runtime within hosts and clients. The binding has the most significant influence on this process.
The binding controls three aspects of message communication: the suite of WS-* protocols, including WS-Security, WS-ReliableMessaging, and so on; the message encoding, such as XML 1.0, Message Transmission Optimization Mechanism (MTOM), and binary; and the transport protocol, including HTTP, TCP, and Microsoft Message Queuing (MSMQ). A given binding specifies one message encoding and one transport, but it can specify numerous WS-* protocols. Given that, there are an overwhelming number of permutations that could be used. To simplify things, WCF provides a set of predefined bindings that fit the most common use cases. Figure 4 lists some of these and describes what they embody.
Figure 4 Predefined WCF Bindings

Class Name Element Name Transport Encoding WS-* Protocols
BasicHttpBinding basicHttpBinding HTTP XML 1.0 WS-I Basic Profile 1.1
WSHttpBinding wsHttpBinding HTTP XML 1.0 Message security, reliable sessions, and transactions
WSDualHttpBinding wsDualHttpBinding HTTP XML 1.0 Message security, reliable sessions, and transactions
NetTcpBinding netTcpBinding TCP Binary Transport security, reliable sessions, and transactions
NetNamedPipeBinding netNamedPipeBinding Named Pipes Binary Transport security, reliable sessions, and transactions
NetMsmqBinding netMsmqBinding MSMQ Binary Transport security and queue transactions
Developers who care primarily about interoperability and don't need WS-* functionality will typically use BasicHttpBinding. Developers who care about interoperability, but also need message-based security, reliable messaging, and transactions will typically choose WSHttpBinding. Developers using WCF on both sides (client and service) can choose from NetTcpBinding and NetNamedPipeBinding, which provide significant optimizations. Those building asynchronous systems can choose NetMsmqBinding. There are also a few bindings that aren't listed here, such as MsmqIntegrationBinding for integrating with existing MSMQ applications, NetPeerTcpBinding for building peer-to-peer services, and WSFederationBinding for federated security. A service can support any combination of these bindings.
Once you choose a binding and instantiate it, you can customize some of its characteristics through the properties exposed on the binding class. The following example shows how to enable transport-based security on the BasicHttpBinding:


BasicHttpBinding b = new BasicHttpBinding();
b.Security.Mode = BasicHttpSecurityMode.Transport;
b.Security.Transport.ClientCredentialType =
HttpClientCredentialType.Basic;
host.AddServiceEndpoint(typeof(IEchoService), b, "svc");
If the predefined bindings and their customizations still don't fit your needs, you can also write a custom binding by implementing a class that derives from Binding.

Opening the Host
Now that you've configured the host with endpoint information, WCF can build the runtime needed to support your configuration. This occurs when you call Open on a particular ServiceHost:


host.Open();
Once the call to Open returns, the WCF runtime is built and ready to receive messages at the addresses specified by each endpoint. During this process, WCF generates an endpoint listener for each supplied endpoint and the code needed to support the WS-* protocols specified by the binding. (An endpoint listener is the piece of code that actually listens for incoming messages using the specified transport and address.)
You can retrieve information about the service at run time through the object model exposed by ServiceHost. This allows you to retrieve anything you might want to know about the initialized service, such as what endpoints it exposes and what endpoint listeners are currently active.
Figure 5 shows a complete example of the console application that hosts EchoService. Figure 6 shows the output. Notice there are two additional endpoint listener addresses that I didn't specify in a ServiceEndpoint. WCF automatically provided these using the base HTTP address for retrieving the service description.
Figure 5 Console App Hosting EchoService


class Program
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(
typeof(EchoService), new Uri("http://localhost:8080/echo")))
{
// define the service endpoints
host.AddServiceEndpoint(typeof(IEchoService),
new BasicHttpBinding(), "svc");
host.AddServiceEndpoint(typeof(IEchoService),
new NetTcpBinding(), "net.tcp://localhost:8081/echo/svc");
host.Open();

Console.WriteLine(
"{0} is open and has the following endpoints:\n",
host.Description.ServiceType);

int i=1;
foreach (ServiceEndpoint end in host.Description.Endpoints)
{
Console.WriteLine("Endpoint #{0}", i++);
Console.WriteLine("Address: {0}",
end.Address.Uri.AbsoluteUri);
Console.WriteLine("Binding: {0}",
end.Binding.Name);
Console.WriteLine("Contract: {0}\n",
end.Contract.Name);
}

Console.WriteLine(
"The following EndpointListeners are active:\n");
foreach (EndpointListener l in host.EndpointListeners)
Console.WriteLine(l.Listener.Uri.AbsoluteUri);

// keep the process alive
Console.ReadLine();
}
}
}

Figure 6 Output of Console App
If you browse to http://localhost:8080/echo, you'll see the default WCF help page (see Figure 7) and if you browse to http://localhost:8080/echo?wsdl, you'll see the generated WSDL definition. The other endpoint listener (http://localhost:8080/echo/mex) knows how to speak WS-MetadataExchange. It's important to note that this sample is not using IIS in any way. WCF provides built-in integration with httpsys, which allows any application to automatically become an HTTP listener.

Figure 7 EchoService Help Page

Configuring Service Endpoints
Hardcoding endpoint information into the host application is not ideal since endpoint details may change over time. It's not hard to imagine how you could store the endpoint information in a configuration file or database and read it while initializing ServiceHost. Since this is a common need, WCF automatically provides this functionality through the predefined configuration section.
The following configuration file defines the same two endpoints that were specified by calling AddServiceEndpoint:






contract="ServiceLibrary.IEchoService"/>
binding="netTcpBinding"
contract="ServiceLibrary.IEchoService"/>




If you add this configuration file to the host application shown in Figure 5 and comment out the calls to AddServiceEndpoint, you'll see the same results in the output. This increases deployment flexibility since the communication details are completely factored out of the compiled code. You can also configure bindings within . Figure 8 shows how to configure basicHttpBinding to use transport security like I had done in code.
Figure 8 Configuring Transport Security






address="https://localhost:8082/echo/svc"
binding="basicHttpBinding"
bindingConfiguration="MyBindingConfiguration"
contract="ServiceLibrary.IEchoService"/>
...













You can even define new custom bindings from scratch using the element, which would be equivalent to deriving a new class from Binding. When it comes to configuring endpoints, bindings, and even behaviors, anything you can do in code, you can also do through configuration.

Figure 9 Using the GUI to Define an Endpoint
Although IntelliSense® for the configuration file works well in Visual Studio® 2005, some developers still prefer to avoid XML altogether. The WinFX® SDK includes a tool called SvcConfigEditor, which provides a graphical interface for working with the various settings. Figure 9 shows how to configure endpoints using this tool.

Using Activation Services
Although I've been experimenting with console applications, ServiceHost makes it easy to host WCF services in a variety of applications, including Windows Forms applications and managed Windows Services. In all of these application scenarios, you're responsible for managing the process hosting WCF. This is known as self-hosting in WCF terms.
In addition to self-hosting, WCF also makes it possible to activate services by using IIS along with traditional Web hosting techniques. You can accomplish this by using a .svc file (similar to .asmx) that specifies the service type to host:


<%@Service class="ServiceLibrary.EchoService" %>
You place this file in a virtual directory and deploy your service type to its \bin directory or the Global Assembly Cache (GAC). When using this technique you specify the service endpoint in the web.config, but you don't need to specify the address since it's implied by the location of the .svc file.





contract="ServiceLibrary.IEchoService"/>

...
Now if you browse to the .svc file, you'll notice the help page is displayed, showing that a ServiceHost was automatically created within an ASP.NET application domain. This is accomplished by an HTTP module that filters incoming .svc requests and automatically builds and opens the appropriate ServiceHost when needed.
If you install the WinFX extensions for Visual Studio 2005, you'll find a new Web Site project template called Indigo Service (this name will change). When you create a new Web site based on this template, it automatically gives you the .svc file along with the corresponding implementation class (found in App_Code). It also comes with a default endpoint configuration in web.config.
On IIS versions 5.1 and 6.0 the WCF activation model is tied to the ASP.NET pipeline, and therefore to HTTP. IIS 7.0, which is planned for release with Windows Vista™, introduces a transport-neutral activation mechanism known as Windows Activation Services (WAS). With WAS, you'll be able to leverage .svc-like activation over any transport.

Programming Clients
Programming WCF clients involves sending messages to a service endpoint according to its address, binding, and contract. To accomplish this, you first create a ServiceEndpoint representing the target endpoint. The following example shows how to create a ServiceEndpoint, based on the service's HTTP endpoint, in a client console application:


using System;
using System.ServiceModel;
using ServiceLibrary;

class Program
{
static void Main(string[] args)
{
ServiceEndpoint httpEndpoint = new ServiceEndpoint(
ContractDescription.GetContract(typeof(IEchoService)),
new BasicHttpBinding(), new EndpointAddress(
"http://localhost:8080/echo/svc");
This code assumes that the client has access to the same IEchoService interface definition that the service used and that the client knows what binding and address to use. Then you can create a ChannelFactory based on the ServiceEndpoint:


ChannelFactory factory =
new ChannelFactory(httpEndpoint);
ChannelFactory creates typed proxies. In this case, it creates proxies of type IEchoService, which you can use to invoke the operations defined by the contract:

Copy Code
IEchoService svc = factory.CreateChannel();
Console.WriteLine(svc.Echo("Hello, world"));
If the service requires a customized binding, you will need to create the binding and customize it before creating ServiceEndpoint. If you want to access the TCP endpoint, simply create another ServiceEndpoint specifying the TCP endpoint details and supply it to ChannelFactory instead of the HTTP endpoint. Everything else would work the same.
The proxy shields you from the different addresses and bindings in use, allowing you to write application code against the service contract. Figure 10 shows the complete client console application.
Figure 10 EchoService Client App


using System;
using System.ServiceModel;
using ServiceLibrary;

class Program
{
static void Main(string[] args)
{
try
{
// define service endpoints on client
ServiceEndpoint httpEndpoint = new ServiceEndpoint(
ContractDescription.GetContract(
typeof(IEchoService)),new BasicHttpBinding(),
new EndpointAddress("http://localhost:8080/echo/svc"));

ServiceEndpoint tcpEndpoint= new ServiceEndpoint(
ContractDescription.GetContract(
typeof(IEchoService)),
new NetTcpBinding(), new EndpointAddress(
"net.tcp://localhost:8081/echo/svc"));

IEchoService svc = null;

// create channel factory based on HTTP endpoint
using (ChannelFactory httpFactory =
new ChannelFactory(httpEndpoint))
{
// create channel proxy for endpoint
svc = httpFactory.CreateChannel();
// invoke service operation
Console.WriteLine("Invoking HTTP endpoint: {0}",
svc.Echo("Hello, world"));
}

// create channel factory based on TCP endpoint
using (ChannelFactory tcpFactory =
new ChannelFactory(tcpEndpoint))
{
// create channel proxy for endpoint
svc = tcpFactory.CreateChannel();
// invoke service operation
Console.WriteLine("Invoking TCP endpoint: {0}",
svc.Echo("Hello, world"));
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}

Configuring Client Endpoints
Hardcoding endpoint information into client code is also less than ideal. So WCF provides a similar configuration mechanism for specifying client endpoints within . The following application configuration file specifies the same client endpoint details used in the code:





address="http://localhost:8080/echo/svc"
binding="basicHttpBinding"
contract="ServiceLibrary.IEchoService"/>
address="net.tcp://localhost:8081/echo/svc"
binding="netTcpBinding"
contract="ServiceLibrary.IEchoService"/>



Notice that I've given each client endpoint a name. You can use this name in your code when creating a ChannelFactory, as illustrated in the following code:


using (ChannelFactory httpFactory =
new ChannelFactory("httpEndpoint"))
{
svc = httpFactory.CreateChannel();
Console.WriteLine("Invoking HTTP endpoint: {0}",
svc.Echo("Hello, world"));
}
Now when you want to create a ChannelFactory for the TCP endpoint, you can simply change the configuration name to tcpEndpoint. You can also configure bindings in the client configuration file just like I did in the service configuration file.
If you add this configuration file to the client console application shown in Figure 10, comment out the code to create the ServiceEndpoint objects, and specify the endpoint names when constructing each ChannelFactory, the result will be the same.

Generating Client Proxies
The preceding examples assumed the client had access to the same interface definition used to implement the service. This is common when .NET is used to implement both sides (in traditional .NET remoting scenarios), but that's not always the case, and it's never the case when the service wasn't implemented with the .NET Framework. The preceding examples also assumed the client knew the precise endpoint details in advance, which isn't always common either.
When clients don't have access to such information, they can discover it using the WS-MetadataExchange specification. Services share endpoint descriptions with clients through WSDL definitions. Most service platforms provide tools for generating client-side code from WSDL definitions. The WinFX SDK provides SvcUtil.exe for this purpose.
When executing SvcUtil.exe, you specify the URL of the WSDL definition and it will generate the necessary .NET code and configuration elements that define the endpoints and bindings used by the service endpoints. Figure 11 shows the output of running SvcUtil.exe against http://localhost:8080/echo. Notice that it generates two files: EchoService.cs and output.config.

Figure 11 SvcUtil.exe Output
EchoService.cs contains a .NET interface definition equivalent to the one the service implemented. Output.config contains the client endpoint information needed to access the service (similar to what I just wrote manually). You'll need to merge the contents of output.config with your application configuration file manually. With this in place, you can write client code using the same techniques shown in the previous examples, only using the generated interface and configuration file.
In general, the WCF client programming model is explicit about the service boundary. You create a typed channel against a specific service endpoint and then send messages through it. Although this helps emphasize the tenets of service orientation, it can be tedious to work at this level all the time. To help you, SvcUtil.exe also generates a proxy class that completely hides the ChannelFactory and ServiceEndpoint creation details. If you open EchoService.cs, you'll find the following class definition:


public partial class EchoServiceProxy :
System.ServiceModel.ClientBase, IEchoService
{
public EchoServiceProxy()
{
}
public EchoServiceProxy(string endpointConfigurationName) :
base(endpointConfigurationName)
{
}
...
This proxy class can simplify your client application code. All you have to do is instantiate the proxy, specify the name of the endpoint configuration, and make method calls. Here's an example:


using (EchoServiceProxy proxy = new EchoServiceProxy("IEchoService"))
{
// invoke service operation
Console.WriteLine("Invoking HTTP endpoint: {0}",
proxy.Echo("Hello, world"));
}
using (EchoServiceProxy proxy = new EchoServiceProxy("IEchoService1"))
{
// invoke service operation
Console.WriteLine("Invoking TCP endpoint: {0}",
proxy.Echo("Hello, world"));
}
The generated configuration file (output.config) defines the IEchoService and IEchoService1 endpoint configurations.

Logging Messages
As you begin working with the WCF programming model, you may find it useful to trace the SOAP messages traveling between clients and services. Windows Communication Foundation provides built-in support for message logging, which can be turned on through your application configuration file.

Figure 12 SvcTraceViewer.exe
SvcConfigEditor provides a Diagnostics tab where you can enable the messaging logging features. Once you enable messaging logging and rerun the app, you'll see the trace file appear in the specified location. The WinFX SDK also provides SvcTraceViewer.exe for viewing the information in a trace file (see Figure 12).

Conclusion
WCF is a new step in distributed programming for developers using the .NET Framework. If you currently build systems using any of today's .NET distributed technologies, it's time to start paying attention to WCF and the future it holds. It's only a matter of time before all .NET-targeted code related to communications will be written using WCF.

Thursday, July 2, 2009

North Indian Wife Vs South Indian Wife ( EVERYONE SHOUD READ)

*** WHAT IT MEANS TO HAVE A North Indian GIRL as WIFE ***

1. At the time of marriage, a north Indian girl has more boyfriends
than her age.

2. Before marriage, she looks almost like a bollywood heroine and
after marriage you have to go around her twice to completely hug
her.

3. By the time she professes her undevoted love to you, you are
bankrupt because of the number of times you had to take her out
to movies, theatres and restaurants. And you wait longingly for her
dowry.

4. The only dishes she can think of to cook is paneer butter
masala, aloo sabji, aloo Gobi sabji, aloo matar, aloo paneer, that
after eating all those paneer and aloos you are either in the bed
with chronic cholestrol or chronic gas disorder.

5. The only growth that you see later in your career is the rise in your monthly phone bill.

6. You are blinded by her love that you think that she is a blonde.
Only later do you come to know that it is because of the mehandhi
that she applies to cover her grey hair.

7. When you come home from office she is very busy watching
"Kyonki saas bhi kabi bahu thi" that you either end up eating
outside or cooking yourself.

8. You are a very "ESpecial" person to her.

9. She always thought that Madras is a state and covers the whole
of south India until she met you.

10. When she says she is going to "work out" she means she is
going to " walk out"

11. She has greater number of relatives than the number of people
you have in your home town.

12. The only two sentences in English that she knows are "Thank
you" and "How are you"


*** WHAT IT MEANS TO HAVE A South Indian GIRL as WIFE
***

1.Her mother looks down at you because you didn't study in IIT or
Madras / Anna University .

2. Her father starts or ends every conversation with " ... I say..."

3. She shudders if you use four letter words.

4. She has long hair, neatly oiled and braided (The Dubai based Oil
Well Company will negotiate with her on a 25 year contract to
extract coconut oil from her hair.)

5. She uses the word 'Super' as her only superlative.

6. Her name is another name for a Goddess or a flower.

7. Her first name is longer than your first name, middle name and
surname combined (unless you are from Andhra)

8. When she mixes milk/curd and rice you are never sure whether it
is for the dog or for herself.

9. For weddings, she sports a mini jasmine garden on her head and
wears silk saris in the Madras heat without looking too
uncomfortable while you are melting in your singlet.

10. Her favourite cricketer is Krishnamachari Srikkanth.

11. Her favourite food is dosa though she has tried North Indian
snacks like Chats (pronounced like the slang for 'conversation')

12. She bores you by telling you which raaga each song you hear is
based on.

13. You have to give her jewellery, though she has already got
plenty of it ..

14. Her Mangal Sutra weighs more than the championship belts
worn by WWF wrestlers.

15. Her father thinks she is much smarter than you.

Jokes

Sardars Funny Collection

Sardar: My mobile bill how much?
Call centre girl: sir, just dial 123to know current bill status
Sardar: Stupid, not CURRENT BILL my MOBILE BILL.
*****************************************
Sardar built 2 Swimming Pools. And he left one of them unfilled y?
When asked him, he said,
"Oye, that’s for those who don’t know Swimming.
*****************************************
A sardarji Doctor falls in Love with a Nurse.He writes a love letter
to the Nurse :- I Love U sister...
****************************
Sardar: I think that girl is deaf..
Friend: How do u know?
Sardar: I told I Love her, but she said her chappals are new
******************************************
Judge: Don't U have shame? It is d 3rd time U R coming to court.
Sardar to judge: U R coming daily, don't U have shame?
*****************************************
Sardar in airplane going 2 Bombay .. While its landing he shouted: "
Bombay ... Bombay "
Air hostess said: "B silent."
Sardar: "Ok. Ombay. Ombay"
*****************************
Sardar got a sms from his girl friend:
"I MISS YOU"
Sardarji replied:
"I Mr YOU" !!.
**************************
Sardar: Doctor! My Son swallowed a key
Doctor: When?
Sardar: 3 Months Ago
Dr: Wat were u doing till now?
Sardar: We were using duplicate key
Dr: So why did you come today?
Sardar: We lost the duplicate key!!
*******************************

After finishing MBBS Sardar started his practice.
He Checked 1st Patient's Eyes, Tongue & Ears with a Torch & Finally Said:
"Oye, Torch is okay"
)))))))))))))))))))))))))))))))))))))))))))))))))) ))
Teacher: "What is common between JESUS, RAM, GANDHI and BUDHA?"
Sardar: "All are born on government holidays...!!!

C# serialzation

Binary Serialization
1. Which class is responsible for binary serialization?

The BinaryFormater is the class responsible for the binary serialization and It's commonly used for the .Net Remoting.
2. What does it take to make my object serializable?

Your class must have the attribute SerializableAttribute and all its members must also be serializable, except if they are ignored with the attribute NonSerializedAttribute. Private and public fields are serialized by default.
[Serializable]
public class Invoice {
private string clientName;
private DateTime date;
private double total;

[NonSerialized]
private string internalCode;

public string ClientName {
get {
return clientName;
}
set {
clientName = value;
}
}

public DateTime Date {
get {
return date;
}
set {
date = value;
}
}

public String Tag {
get {
return tag;
}
set {
tag = value;
}
}

public double Total {
get {
return total;
}
set {
total = value;
}
}
}
3. What are the main advantages of binary serialization?
• Smaller
• Faster
• More powerful (support complex objects and read only properties)
4. How do you encapsulate the binary serialization?
public static void SerializeBinary( object aObject, string aFileName) {
using (FileStream _FileStream = new FileStream(aFileName, FileMode.Create)) {
BinaryFormatter _Formatter = new BinaryFormatter ();
_Formatter.Serialize(_FileStream, aObject);
}
}
5. How do you encapsulate the binary deserialization method?
public static object DeserializeBinary(string aFileName) {
using (FileStream _FileStream = new FileStream(aFileName, FileMode.Open)) {
BinaryFormatter _Formatter = new BinaryFormatter ();
return _Formatter.Deserialize(_FileStream);
}
}
6. Will my read only properties be serialized?

Yes if the properties encapsulate a field. By default all the private and public fields are serialized. Binary serialization is not related to properties.
7. Is it possible to have circular reference?

Yes it is, you can have circular reference and the binary serialization process will work fine. .Net generate the object graph before the executing the serialization and finally generate the stream. Unlike Xml serialization process, the BinaryFormater has no problem with the circular reference.
8. Why my Dataset is so big when it's serialized in binary?

By default the DataSet is serialized in Xml and the binary stream only wraps the Xml Data inside it. That's mean that the size is similar to the Xml size. .Net 2.0 add a new property named RemotingFormat used to change the binary serialization format of the DataSet. SerializationFormat.Binary will generate a better result.
For previous version, it's also possible to download the DataSetSurrogate to reduce the size and increase the performance.
9. How do I serialize a Dataset in binary?

See answer above.

10. How can I implement a custom serialization?

If you need to control the serialization process of your class, you can implement the ISerializable interface which contains a method GetObjectData and a special constructor . Why use custom serialization ? By using it you will be able to handle version change in your class or get a better performance result. An exception of type SerializationException is raised if the fields does not exists.
#region ISerializable Members

//Special constructor
protected CustomInvoice(SerializationInfo info, StreamingContext context) {
clientName = info.GetString("clientName");
date = info.GetDateTime("date");
total = info.GetDouble("total");
}

[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
public void GetObjectData(SerializationInfo info, StreamingContext context) {
info.AddValue("clientName", clientName);
info.AddValue("date", date);
info.AddValue("total", total);
}

#endregion

11. When does a change in my object break the deserialization?

Binary serialization is not tolerant to version change. There is no problem when a new field is added but if a field is missing, an exception is throw. New field will get the default value. .Net 2.0 include a new attribute named OptionalFieldAttribute. For previous version, you must implement your own custom serialization and handle manually the changes.
12. When does a change in my object NOT break the deserialization?

Version fault exception are only checked if the assembly is signed, all version change are ignored otherwise.
13. How can I make my object version tolerant?

Use the OptionalFieldAttribute or implement your own custom serialization with ISerializable.
14. Why set VersionAdded of OptionalFieldAttribute since it's a free text?

The parameter is only for informative purpose. .Net never checked it by default but it could be used in a custom serialization. Use the reflection to get the attribute of field and check the added version value.

15. Does BinaryFormatter from .Net 1.1 is compatible with the BinaryFormatter 2.0?
Absolutely, the BinaryFormatter 2.0 is 100% with other version, but it's not the case with the SoapFormatter.
16. How can I modify a value just before the serialization or just after the deserialization?
You can add custom attribute to some method. Your marked method will get called a the right time. This is usefull to initialize a property after the deserialization or to clean up your instance before the serialization.
• OnDeserializingAttribute :This event happens before deserialization
• OnDeserializedAttribute :This event happens after deserialization
• OnSerializingAttribute :This event happens before serialization
• OnSerializedAttribute :This even happens after serialization
[Serializable]
public class SecurityToken {
private string password;
private string userName;

private string Decrypt(string aPassword) {
// Decrypt the password here !!!
return password;
}

private string Encrypt(string aPassword) {
// Encrypt the password here !!!
return password;
}

[OnSerializing()]
internal void OnSerializingMethod(StreamingContext context) {
password = Encrypt(password);
}

[OnDeserialized()]
internal void OnDeserializedMethod(StreamingContext context) {
password = Decrypt(password);

// Set the default
if (userName == null) {
userName = Environment.UserName;
}
}

public string Password {
get {
return password;
}
set {
password = value;
}
}

public string UserName {
get {
return userName;
}
set {
userName = value;
}
}
}
17. How can I create a generic Binary deserialization method?
// Binary deserialization (generic version with the return value casted)
public static T DeserializeBinary(string aFileName) {
using (FileStream _FileStream = new FileStream(aFileName, FileMode.Open)) {
BinaryFormatter _Formatter = new BinaryFormatter();
return (T)_Formatter.Deserialize(_FileStream);
}
}
Xml Serialization
1. Which class is responsible for Xml serialization?

XmlSerializer is responsible of the Xml serialization.
2. What is the difference between the SoapFormatter and the XmlSerializer?

SoapFormatter is used to create a Soap envelop and use an object graph to generate the result. The XmlSerializer process use only the public data and the result is a more common xml file. The Web Service in .Net use an XmlSerializer to generate the output contained in the Soap message. The SoapFormatter and the BinaryFormatter are used in the .Net Remoting serialization process.
3. What does it take to make my object serializable?

Nothing, but there is some constraint :
• Your object must have a public empty constructor.
• Field or property must be public
• Their return type must also respect serialization rules.
• Property must be read write.
4. What are the main advantages of Xml serialization?
• Based on international standard (XML).
• Cross platforms.
• Readable and can be edited easily.
5. How do I encapsulate the Xml serialization method?
public static void SerializeXml( object aObject, string aFileName) {
using (FileStream _FileStream = new FileStream(aFileName, FileMode.Create)) {
XmlSerializer _Serializer = new XmlSerializer ( aObject.GetType());
_Serializer.Serialize(_FileStream, aObject);
}
}
6. How do I encapsulate the Xml deserialization method?
public static object DeserializeXml( string aFileName, Type aType) {
using (FileStream _FileStream = new FileStream(aFileName, FileMode.Create)) {
XmlSerializer _Serializer = new XmlSerializer (aType);
return _Serializer.Deserialize(_FileStream);
}
}
7. How can I create a generic Xml deserialization method?
public static T DeserializeXml(string aFileName) {
using (FileStream _FileStream = new FileStream(aFileName, FileMode.Open)) {
XmlSerializer _Serializer = new XmlSerializer (typeof(T));
return (T)_Serializer.Deserialize(_FileStream);
}
}
8. How can I ignore a property in serialization?

If you use a XmlSerializer, mark your property with the custom attribute XmlIgnoreAttribute and if you use a SoapFormatter, use a SoapIgnoreAttribute instead.

9. How can I rename a field or a property in the Xml output?

Use the attribute XmlElementAttribute or XmlAttributeAttribute with the new name as parameter. To rename a class, use the XmlTypeAttribute.
[XmlType("city")]
public class Town {
private string name;
private string state;

[XmlElement("townname")]
public string Name {
get {
return name;
}
set {
name = value;
}
}

[XmlAttribute("state")]
public string State {
get {
return state;
}
set {
state = value;
}
}
}
Result:


Los Angeles

10. How can I read a field from an Xml stream without deserializing it?

XPath can do the job.. This is an example where we read the town name (Xml element) )and the state attribute from the Xml file:
XmlDocument document = new XmlDocument();
document.Load("town.xml");

//Select an element
string _TownName = document.SelectSingleNode("//city/townname").InnerText;

//Select an attribute
string _State =
document.SelectSingleNode("//city").Attributes["state"].InnerText;

MessageBox.Show(_TownName + " is in " + _State);
This is an example where we read an application setting from a web config file.
XmlDocument configDocument = new XmlDocument();
configDocument.Load("web.config");

// Add the namespace with .Net web.config
XmlNamespaceManager nsmgr = new XmlNamespaceManager(configDocument.NameTable);
nsmgr.AddNamespace("ms", "http://schemas.microsoft.com/.NetConfiguration/v2.0");

string appSetting = configDocument.SelectSingleNode(
"/ms:configuration/ms:appSettings/ms:add[@key='DatabaseName']",
nsmgr).Attributes["value"].InnerText;
The orignal config file:






Note, you don't need the XmlNamespaceManager if you don't have a default namespace. Web.config in the ealier version does not contain a default namespace.
11. How can I serialize a property as an Xml attribute?

By default properties are serialized as Xml elements, but if you add an XmlAttributeAttribute to a property, .Net will generate an attribute instead. It's must be type compatible with an Xml attribute. See example here
...
[XmlAttribute("state")]
public string State {
get {
return state;
}
set {
state = value;
}
}

12. How can I implement custom serialization?

You need to Implement the interface IXmlSerializable. This class is available in the .Net 1.X but it's was not documented. It's now official available with .Net 2.0. With custom serialization, it's possible to optimize the output and generate only what is needed. In this example, we generate only the non empty properties
public class SessionInfo : IXmlSerializable {

#region IXmlSerializable Members

public System.Xml.Schema.XmlSchema GetSchema() {
return null;
}

public void ReadXml(XmlReader reader) {
UserName = reader.GetAttribute("UserName");

while (reader.Read()) {
if (reader.IsStartElement()) {
if (!reader.IsEmptyElement) {
string _ElementName = reader.Name;
reader.Read(); // Read the start tag.

if(_ElementName == "MachineName") {
MachineName = reader.ReadString();
} else {
reader.Read();
}
}
}
}
}

public void WriteXml(XmlWriter writer) {
if (!String.IsNullOrEmpty(UserName))
writer.WriteAttributeString("UserName", UserName);

if (!String.IsNullOrEmpty(MachineName))
writer.WriteElementString("MachineName", MachineName);
}

#endregion

private string machineName;
private string userName;

public string MachineName {
get {
return machineName;
}
set {
machineName = value;
}
}

public string UserName {
get {
return userName;
}
set {
userName = value;
}
}
}
The output could be something like that if UserName and Machine are not empty :


MyMachine

or it could be like that if MachineName is empty :


13. How can I serialize a property array?

Array are compatible with the serialization, but all elements must be of the same type. If not all types must be specified, see below.

14. How can I serialize an array with different types?

It's possible to tag the array with all the possible type. Use XmlInclude on the class containing the array or XmlArrayItem. All the possible types must be specified with the attributes. Array types must be known because of the Xml schema. XmlInclude could be used for property that returned differente types. It's complicate object inheritance since all types must be known.
This example will fail with a message "There was an error generating the XML document." because the Cars could contain undefined types.
public class Car {}

public class Ford : Car{}

public class Honda: Car {}

public class Toyota: Car {}

public class CarSeller {
private List cars = new List();

public List Cars {
get {
return cars;
}
set {
cars = value;
}
}
}

...
Ford _Ford = new Ford();
Honda _Honda = new Honda();
Toyota _Toyota = new Toyota();

CarSeller _Seller = new CarSeller();
_Seller.Cars.Add(_Ford);
_Seller.Cars.Add(_Honda);
_Seller.Cars.Add(_Toyota);

SerializationHelper.SerializeXml(_Seller, @"seller.xml");
Three possible solutions:
#1 Add XmlIncludeAttribute to the Seller class:
[XmlInclude(typeof(Ford))]
[XmlInclude(typeof(Honda))]
[XmlInclude(typeof(Toyota))]
public class CarSeller {
private List cars = new List();

public List Cars {
get {
return cars;
}
set {
cars = value;
}
}
}
with this result








#2 Add XmlArrayItem to the property named Cars:
public class CarSeller {
private List cars = new List();

[XmlArrayItem(typeof(Ford))]
[XmlArrayItem(typeof(Honda))]
[XmlArrayItem(typeof(Toyota))]
public List Cars {
get {
return cars;
}
set {
cars = value;
}
}
}
with this result








#3 Implement our own serialization with IXmlSerializable :
see items above

15. How can I serialize a collection?

Collection are serialized correctly, but they must contains only object of same types. Read only properties of type ArrayList, List and other collections will be serialized and deserialized correctly.
public class Role {
private string name;

public string Name
{
get { return name; }
set { name = value; }
}
}

public class UserAccount {
private string userName;

public string UserName {
get {
return userName;
}
set {
userName = value;
}
}

// Generic version
private List roles = new List();

public List Roles {
get {
return roles;
}
}

// ArrayList version
private ArrayList roleList = new ArrayList();

public ArrayList RoleList {
get {
return roleList;
}
}

// String collection version
private StringCollection roleNames = new StringCollection();

public StringCollection RoleNames {
get {
return roleNames;
}
}
UserAccount _UserAccount = new UserAccount();
_UserAccount.UserName = "dhervieux";

Role _RoleAdmin = new Role();
_RoleAdmin.Name = "Admin";

Role _RoleSales = new Role();
_RoleSales.Name = "Sales";

_UserAccount.RoleList.Add(_RoleAdmin);
_UserAccount.RoleList.Add(_RoleSales);
_UserAccount.Roles.Add(_RoleAdmin);
_UserAccount.Roles.Add(_RoleSales);
_UserAccount.RoleNames.Add("Admin");
_UserAccount.RoleNames.Add("Sales");

SerializationHelper.SerializeXml(_UserAccount, @"useraccount.xml");
UserAccount _Result =
SerializationHelper.DeserializeXml(@"useraccount.xml");
will produce:


dhervieux


Admin


Sales




Admin


Sales



Admin
Sales


16. Why is the first serialization of each type of object is so long?

XmlSerializer generate an assembly in memory optimized for each type. That's explain why the first call to a Web Service is so long. In .Net 2.0, there is an option in the project properties of Visual Studio to generate the Xml serialization assembly. Use it directly in the IDE or use sgen.exe, this tools come with the .Net Framework SDK.
17. How can I optimize the serialization process?

Pregenerate your serialization assembly with Visual Studio or sgen.exe. See details in answer above. Implementing your own serialization could also increase the performance.
18. How can I serialize an array directly to stream?

Yes it possible. .Net will name the Array and save the content. All the data must be of the same type.
bool[] _BoolArray = new bool[] { true, false, false, true };

// Serialization
SerializationHelper.SerializeXml(_BoolArray, @"boolarray.xml");

//Deserialization
_Result = SerializationHelper.DeserializeXml(@"directboolarray.xml");
will produce:


true
false
false
true

19. Which serializer is used by a Web Services?

Web Services are using SOAP to communicate, but returned objets or parameters are serialized with the XmlSerializer. Write unit test to be sure that your objects are serializable.
20. Does read only properties are serialized?

No, they are not, except for collections.
21. How can I serialize a multidimensional array

You need to encapsulate your array in a structure or a class an serialize it. Multidimensional array are not serializable by default.
22. How can I avoid serialization for an empty list or property with a default value?

There is an undocumented way of doing that, you need to create a method named ShouldSerialize where is replaced by the property name. This method should return a boolean that indicate if the property must be serialized or not. For exemple, if you have list with no item, there is no need to serialize an empty list.
public class Registration {
private string[] users = new string[0];

public bool ShouldSerializeUsers() {
return users.Length > 0;
}

public string[] Users {
get {
return users;
}
set {
users = value;
}
}
}
Result :


Without the ShouldSerializeUsers :





23. Why my object is marked as Serializable (like SortedList) and it's does not work?

The SerializationAttribute is only used for the binary serialization. That does not mean that it will work with an XmlSerializer. That's the case of the SortedList.
24. How to remove the default namespace in the serialization?

It's possible to remove the xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" and xmlns:xsd="http://www.w3.org/2001/XMLSchema" from the serialization result, it's possible to add an XmlSerializerNamespaces with an empty namespace mapping.
User _User = new User(new string[] { "Admin", "Manager" });

using (FileStream _FileStream = new FileStream("user.xml", FileMode.Create)) {
XmlSerializer _Serializer = new XmlSerializer(_User.GetType());

XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");

_Serializer.Serialize(_FileStream, _User, ns);
}

Search This Blog