Вы находитесь на странице: 1из 167

Introduction

Windows Communication Foundation (WCF) is an extension of the .NET framework to


build and run connected systems. Windows Communication Foundation provides a
unified framework for building secure and reliable transacted Web services. Windows
Communication Foundation combines and extends the capabilities of Distributed
Systems, Microsoft .NET Remoting, Web Services, and Web Services Enhancements
(WSE), to develop and deliver unified secured systems. The WCF framework builds
loosely-coupled applications on a service oriented architecture that interoperates
more securely and reliably across platforms.

WCF simplifies the development effort to make service oriented applications by


combining the technologies together, leading to higher development productivity.
Also, it reduces the complexity of applications by unifying Enterprise Services,
Messaging, .NET Remoting, Web Services, and WSE. WCF builds applications with an
attributed programming model, leading to higher developer productivity. WCF was
introduced as part of the .NET 3.0 Runtime components. The Windows
Communication Foundation provides a service oriented programming model to build
service oriented applications that interoperate across organizational and platform
boundaries. It supports a broad range of Web Service standards like XML, XSD,
SOAP, XPath, WSDL, and advanced standards and specifications like WS-Addressing,
WS-Policy, WS-Security, WS-Trust, WS-Secure Conversation, WS-Reliable
Messaging, WS-Atomic Transaction, WS-Coordination, and WS-Policy. The following
diagram depicts the Windows Communication Foundation (WCF) framework model:

WCF Communication Model


Windows Communication Foundation (WCF) follows a client–server model to
establish communication between applications. Client applications can directly access
services through Endpoints exposed by the service. Endpoints are nothing but
locations defined, through which messages can be sent or received, and a service
can have multiple endpoints.

A WCF Service is comprised of the following major components. The diagram below
shows how the components are related to each other:

 Service Contract
 Operation Contract
 Data Contract
 Data Member

Service Contract

Service contract is a contract that specifies the direction and type of the messages in
a conversation. It is an interface or a class that defines the service contract in a
Windows Communication Foundation (WCF) application. A service contract is the
gateway to a service for external applications to make use of the service functions,
and at least one service contract should be available in a service. A service contract
is defined as follows:

Collapse Copy Code


// Student ServiceContract
[ServiceContract]
public interface IStudentService
{
// Define the OperationContact here….
}

The ServiceContract attribute of the interface defines the service contract in the
service interface. The service contract defines the operations available in the service,
operations like web service methods in a web service. IstudentService is a
student service interface which exposes all the operation contracts or methods in this
service to external systems.

Operation Contract

An operation contract defines the methods of the service that are accessible by
external systems. The OperationContract attribute needs to be applied for all
these methods, these are also like web methods in a web service. Operation
contracts are defined as follows:

Collapse Copy Code


// Student ServiceContract
[ServiceContract]
public interface IStudentService
{
// Define the GetStudentFullName OperationContact here….
[OperationContract]
String GetStudentFullName (int studentId);

// Define the GetStudentInfo OperationContact here….


[OperationContract]
StudentInformation GetStudentInfo (int studentId);

Data Contract

A data contract defines a type with a set of data members or fields that will be used
as the composite type in a service contract. It is a loosely-coupled model that is
defined outside the implementation of the service and accessible by services in other
platforms. To define a data contract, apply the DataContract attribute to the class
to serialize the class by a serializer, and apply the DataMember attribute to the fields
in the class that must be serialized. A StudentInformation data contract can be
defined as follows:

Collapse Copy Code


[DataContract]
public class StudentInformation
{
// Define the Datamembers here….
}

Data Member

A data member specifies the type which is part of a data contract used as a
composite type member of the contract. To define a data member, apply the
DataMember attribute to the fields that must be serialized. The DataMember
attribute can be applied to private properties, but they will be serialized and
deserialized, and will be accessible to the user or process. The code below shows
how to define a data member in a data contract:

Collapse Copy Code


[DataContract]
public class StudentInformation
{
_studentId = studId;

[DataMember]
public int StudentId
{
get { return _studentId; }
set { _studentId = value; }
}

Creating WCF Applications with Visual Studio 2008

These are the steps needed to be followed to create a WCF application with Visual
Studio 2008:

1. Open Visual Studio 2008.


2. Click on New Project in the File menu.
3. Expand the Visual C# node in the Project types tree, and select the Web
node.
4. Select WCF Service Application.
5. Choose the folder where the application is to be saved and click the OK
button.
6. The project will be created with the default files, which are IService1.cs,
Service1.svc, Service1.svc.cs, and web.config.

You can see the ServiceContract attribute with IService1, and the methods
exposed are defined with the OperationContract attribute. Service1 is the
concrete class for the implementation of IService1. Endpoints and other behavioral
properties are defined in the system.serviceModel section of the Web.Config file.

You need to make the necessary changes in the above section of Web.Config if you
are renaming the services; otherwise, external systems can not identify the services.

Customizing the Default WCF Service

Now, we need to make the necessary changes in the default WCF application
according to our requirements. The first step is renaming the existing service files or
deleting the existing files and create new ones. In this example, I would go ahead
with the first approach, renaming the existing files.

Rename the project to WcfStudentService, the file Iservice1.cs to IstudentService.cs,


Service.svc to StudentService.svc. Note that the code file Service.svc.cs will also be
renamed to Service.svc.cs. Make the corresponding changes in the Web.Config file.
Remove the existing code from IstudentService and add the following code. The
OperationContract attribute should be applies to the methods which are
accessible to external systems. DataContract should be applied to the
StudentInformation class, and fields in the StudentInformation attributed
with DataMember since StudentInformation is using as composite type in
IstudentService.

Collapse Copy Code


namespace WcfStudentService
{
// Defines IStudentService here
[ServiceContract ]
public interface IStudentService
{
// Define the GetStudentFullName OperationContact here….
[OperationContract]
String GetStudentFullName(int studentId);

// Define the GetStudentInfo OperationContact here….


[OperationContract]
IEnumerable<studentinformation> GetStudentInfo(int studentId);
}

// Use a data contract as illustrated in the sample below to add


// composite types to service operations.
[DataContract]
public class StudentInformation
{
int _studentId ;
string _lastName;
string _firstName;

public StudentInformation(int studId, string firstname, string lastName)


{
_studentId = studId;
_lastName = lastName;
_firstName = firstname;
}

[DataMember]
public int StudentId
{
get { return _studentId; }
set { _studentId = value; }
}

[DataMember]
public string FirstName
{
get { return _firstName; }
set { _firstName = value; }
}

[DataMember]
public string LastName
{
get { return _lastName; }
set { _lastName = value; }
}
}
}

Note that StudentInformation is an independent class and accessible to external


systems since it declared as public.

StudentService is the concrete class implemented from IstudentService. Add


the following code in the service class:

Collapse Copy Code


namespace WcfStudentService
{
// StudentService is the concrete implmentation of IStudentService.
public class StudentService : IStudentService
{

List<studentinformation> Students = new List<studentinformation>() ;

// Create list of students


public StudentService()
{
Students.Add(new StudentInformation(1001, "Nikhil",
"Vinod"));
Students.Add(new StudentInformation(1002, "Joshua",
"Hunter"));
Students.Add(new StudentInformation(1003, "David",
"Sam"));
}

// Method returning the Full name of the student for the studentId
public string GetStudentFullName(int studentId)
{
IEnumerable<string> Student
= from student in Students
where student.StudentId == studentId
select student.FirstName + " " + student.LastName;

return Student.Count() != 0 ? Student.First() : string.Empty;


}

// Method returning the details of the student for the studentId


public IEnumerable<studentinformation> GetStudentInfo(int studentId)
{

IEnumerable<studentinformation> Student = from student in Students


where student.StudentId == studentId
select student ;
return Student;
}
}

Hosting and Testing the WCF Service

The WCF service can be hosted in Internet Information Service (IIS), and Windows
Activation Service (WAS) with Vista and IIS 7.0. In this example, IIS is used for
hosting the WCF service. Build the service project, and run it by pressing F5 to run
from Visual Studio 2008. By default, it would take IIS as the hosting service. You can
select the StudentService.svc file from the list of files displayed in the browser
window, and the page will be displayed as follows:
You can not directly test the WCF service with out a client, as we do in a web service.

There is an interface provided by Microsoft to test the service in an easy way, which
is the WcfTestClient utility. The WcfTestClient window will be opened if the service is
hosted by the WCF Service Host (WcfSvcHost.exe), from Visual Studio, or you can
explicitly run the WcfTestClient utility from the command prompt. You can run it as
follows:

Collapse Copy Code


C :\> WcfTestClient http://localhost:4489/StudentService.svc

http://localhost:4489/StudentService.svc should be the name of the service to be


tested. WcfTestClient displays the service with the exposed methods on the left side
pane; it also provide the options to enter the parameter values on the right top
pane. When you enter the values in the parameter box and click the Invoke button,
it displays the results on the right bottom pane of this utility.
Consuming the WCF Service

The WCF service can be communicated through a WCF client from a client
application. The first step of consuming a WCF service is to create a WCF client and
the related configuration files. The Service Model Metadata Utility Tool (Svcutil.exe)
is a command-line tool and one of its options is to create a WCF Client. The other
option is to create a WCF Client by adding the service reference in the Windows
project. The second option is used in this example to create the WCF Client.

Also, add a Windows application with a form which has Buttons, Labels, a
TextBox, and a DataGridView to display the student information.

Create the WCF Client

To add the service reference to the Windows application, follow these steps:

1. Open Solution Explorer.


2. Right click on References of the Windows application, or right click on Service
References and select Add Service Reference.
3. And Service Reference window will pop up.
4. Click on Discover, select the Services in the Solution in the Discover
dropdown.
5. It would search and display the services in the solution as shown below:
6. Rename Namespace to StudentServiceReference, select StudentService, and
click the OK button.
7. The proxy is created and added to the service reference, and is ready to
consume the service in the application with the StudentService reference.
Using the WCF Client

Create the instance of the WCF client to communicate to the service. The following
line create the service client proxy:

Collapse Copy Code


// create the proxy to access the service
StudentServiceClient studClient =
new StudentServiceClient("WSHttpBinding_IStudentService");

StudentServiceClient is the WCF client class generated when the service


reference is added to the project. WSHttpBinding is the endpoint binding method
specified in the web.config file of the service, and IStudentService is the service
to be communicated.

After creating the proxy or instance of the WCF client, we can access the methods of
the service like accessing the methods of a web service in the previous versions of
.NET. The GetStudentFullName and GetStudentInfo methods of the service can
be called as follows:

Collapse Copy Code


// Get Fullname of the Student through the proxy from service
lblFullName.Text = studClient.GetStudentFullName(
Convert.ToInt16(textBox1.Text));

// Get details of the Student through the proxy from service


IEnumerable<studentinformation> x =
studClient.GetStudentInfo(Convert.ToInt16(textBox1.Text));
dataGridView1.DataSource = x;

In the form, if you enter the student ID and click on the Display Student Info button,
you will call the service methods and populate the Fullname label and The
DataGridView with the details.

Conclusion

This is just an introduction to the Windows Communication Foundation framework. I


will include details about configuring a service and a client for different types of
communication in my next article.

Introduction

I�m impressed! And that�s not an easy thing to do. I�ve been playing with the CTP
(February 2006) release for a while now, and believe it or not, I think we may
actually have something here. I have not had the time to explore the other
�Foundation� members (of WinFX), but from what I�ve seen of the Windows
Communication Foundation (WCF), it really is a very nice package. Yes, I know that
each time there is a new technology released, there is always some neat features.
But in the past, I always thought that we were paying more (in complexity) than
what we were getting (in functionality), can you spell COM? This time, it feels like we
are getting the whole thing for free. It�s possible that it may be just my na�ve
perspective, but hey it�s all about me anyway.

I like to preface my articles with a disclaimer. The content in this article is simply my
impressions and interpretation, and it should be read in that context. Even though
the prose may at times seem like I know what I�m talking about, any similarity to
actual facts may simply be coincidence. Enjoy the journey.

Why can�t we just talk?

The minute we stepped out of the DOS box, we realized that we were not alone any
more, and we needed to learn to get along and communicate with the other
inhabitants of the virtual world. DDE, OLE, COM, DCOM, and Remoting have been
some of the attempts at providing mechanisms for two applications to be able to talk
to each other. Remember how OLE and COM were described when first introduced?
As the �foundation for all future products�. With hindsight, we can see that they
were really just baby steps. Each one solved only a small part of the whole problem.
So if they were baby steps, then WCF is certainly a giant leap. WCF provides a
complete solution to the communication problem. And it does it with elegance and
simplicity. Can you tell that I�m just a little enthusiastic?

Whether your requirement is to communicate with another module on the same


machine, or another module implemented in a different language, or you need to
communicate with a module that�s on a machine on the other side of the world, or
you want to communicate with a module running on a different platform, or even
communicate with a module that�s not even running!, yup, you can do it under
WCF.

In my opinion, the beauty of WCF is that it is an �all-inclusive� solution. It is the


first one to provide a complete end-to-end solution covering the scope and depth of
the problem. It is also the simplest from a programmer's point of view; you are
always just making a method call. Yeah, I am sure that there is quite a bit of magic
going on under the covers to support that simplicity of use.

Now, I have not explored every nook and cranny, or option, or possibility, but from
what I�ve seen, it�s an excellent solution. At least for me, and as I said before�

What is a service?

Let�s see how much trouble I can get myself into here. I think that, in its most
elemental form, a service is simply some functionality (code) running in some
external process that is made available to other processes in a standard way.
That�s pretty much the crux of it, except that in a standard way also
encompasses platform and language neutrality.

So, by the above definition, a service really has two parts. First is the code that must
be running somewhere in order to provide some functionality to clients. And second,
there must be some generic mechanism that can be used by any process, regardless
of the platform, language, or locality, that makes the service accessible. That generic
mechanism has turned out to be XML and SOAP. Of course, there are some
additional facilities required in order for a client to be able to know (or discover)
what functionality the service makes available. But I think of those as supporting
technologies.

There is also some glue that is required in order to tie the two parts of a service
together. That glue is the code that will support the communication medium
(transport) that is being used by the service and the client to talk to each other.
Being lazy�I mean smart, we�ve come up with some generic glue also. This way,
each service implementation does not have to re-invent the wheel. For Web
Services, the generic glue is a Web Server. So, a Web Server provides a hosting
environment for services that use HTTP as their transport mechanism. I would also
like to suggest that Web Services are a special implementation of a service as
defined above.

Here are the things that we will be examining in the rest of this article. How do you
define a service? How do you implement a service? How do you host a service? How
do you access and use a service? Once we have the basics nailed down, we�ll look
at some of the more complex communication options that WCF facilitates.

So what is WCF?

Here is what WCF is for me:

WCF is an inter-application communication platform. It provides a common API that


hides the underlying communication medium. It can be platform neutral, and it
provides for locality indifference. Essentially, under WCF, I, as a programmer, do
not need to know or care where the other end is or how the actual communication
is taking place. To me, that is beautiful!

WCF is services based technology. It has, as its roots, Web Services, and thus XML
and SOAP are its core technologies. WCF took the concept of Web Services and
super-charged it. Much of the look and feel of WCF behaves like traditional Web
Services. In fact, I like to think of WCF services as Web Services on steroids. You
define WCF services much like Web Services. You can interrogate a known service
for its methods with the same protocols that are available for Web Services. And you
have very similar infrastructure requirements as are for Web Services. The main
difference is that WCF has expanded the transports that are available to include
TCP/IP, IPC (named pipes), and message queue-ing, in addition to HTTP. I think the
focus of Web Services is to solve the interoperability problem, and the focus of WCF
is to solve the much broader communication problem. And it has done this while still
maintaining a uniform API as well providing more efficient mechanisms.

The most important feature from a developer perspective is that you don�t have to
be concerned with what or how you are communicating. The code is the same, no
matter what the final transport mechanism or locality of service might be.

Service Contracts-exposing functionality

Our WCF journey starts with how services define the functionality that they expose.
Much of the infrastructure required to implement services under WCF is specified
using declarative programming. That means, using attributes to specify functionality.
The following shows how to declare an interface that will be exposed as a service:

Collapse Copy Code


[ServiceContract]
public interface ILocalTime
{
[OperationContract]
string GetLocalTime();
}

public class LocalTimeService : ILocalTime


{
...
}

The ServiceContract attribute specifies that the interface defines the functionality
of a service. OperationContract is used to decorate each method that is to be
exposed as part of the service. That is all that is required to create a WCF service.
Just slightly more is required to actually deploy the service, which we�ll cover later
on.

By the way, you don�t have to use interfaces when implementing a service, just like
you don�t have to use an interface to define a class. You do have to specify what
you want exposed through a service, explicitly. You can define anything else you
want or need as part of the interface, but only methods, and only methods that get
decorated with [OperationContract], will be exposed by the service.

Data Contracts-exposing data types


WCF also allows you to expose custom data types so that you are not restricted to
simple data types of the CLR. These are simple structs with no methods associated
with it. This can be a little confusing sometimes, because the same syntax is used for
both services as well as for CLR definitions. Here�s an example of a DataContract
that we will use.

Collapse Copy Code


[DataContract]
public class SensorTemp
{
[DataMember]
public int probeID;
[DataMember]
public int temp;
}

DataContract specifies the data type that you are exposing and, DataMember
specifies the members that are part of the data type. As is the case with
ServiceContract, you have to explicitly declare which members are to be exposed
to external clients, using DataMember. What that means is that you can include
anything else that you may want (or need) as part of the class definition, but only
the members decorated with DataMember will be visible to clients.

Coding options in WCF

As we saw above, one of the options available to specify functionality under WCF is
to use attributes. Attributes are translated by the compiler to generate much of the
infrastructure required by WCF in order for us to create and use services.

The second way you can specify many of the options is through configuration files.
This allows you to make changes without having to re-compile. Many of the WCF
classes will automatically use default values from the config file. Here�s an example
of an endpoint specified using config data (endpoints will be described shortly). First,
the config file, then the code statement referencing the config file data:

Collapse Copy Code


<endpoint name ="LocalTimeService"
address="net.pipe://localhost/LocalTimeService"
binding="netNamedPipeBinding"
contract="ILocalTime" />
Collapse Copy Code
LocalTimeProxy proxy = new LocalTimeProxy("LocalTimeService");
Finally, the third way of coding functionality is, of course, programmatically. Many of
the things that you can do via attributes or config files can also be done
programmatically. Here is the previous endpoint, defined programmatically:

Collapse Copy Code


Uri baseAddress = new
Uri(ConfigurationManager.AppSettings["basePipeTimeService"]);
baseAddress = new Uri(ConfigurationManager.AppSettings["basePipeTimeService"]);
serviceHost.AddServiceEndpoint(typeof(ILocalTime),
new NetNamedPipeBinding(), baseAddress);

Endpoints

Endpoints are the �identity� of a service. They define all the information that we
need in order to establish and communicate successfully with a service. Endpoints
are made up of three pieces of information: Address, Binding, and Contract. The
address is obviously the location of the service, such as
�net.pipe://localhost/LocalTimeService�. The binding specifies security options,
encoding options, and transport options, which means a lot of options! Luckily, there
is a collection of pre-defined bindings provided with WCF that we can use to make
our life simpler. And finally, the contract is the actual interface that the service
implements.

Implementing a WCF Service

So, a service is nothing more than a regular class that gets decorated with some
special attributes. The attributes are then translated by the compiler to generate the
special infrastructure code required to expose the class as a service to the world. In
the following code, we first define an interface that has one method that returns the
local time of where the service has been deployed. The LocalTimeService class
then implements the interface, and thus exposes the functionality to the world, or at
least to whomever is interested.

Collapse Copy Code


[ServiceContract]
public interface ILocalTime
{
[OperationContract]
string GetLocalTime();
}

[ServiceBehavior(InstanceContextMode =
InstanceContextMode.PerCall)]
public class LocalTimeService : ILocalTime
{
public string GetLocalTime()
{
return DateTime.Now.ToShortTimeString();
}
}

That�s all that�s needed to create a WCF service. If you compile the above code
into a DLL (a library), you will have created a service. Of course, there is a little
more needed in order to have something that�s useable. We need two other pieces
in order to complete the service. We need something that will be able to load the
service DLL when a client requests the functionality of the service. And we need
something that will be able to listen on a communication port, and look through
everything that is being received to see if it matches what we are responsible for,
our service contract.

Deploying a WCF Service

There are a number of ways to deploy our service. First, if we implement our service
to support HTTP, then we could deploy our service just like a regular Web Service,
using IIS. If we want to support some of the other transports, then we could deploy
the service using Windows Activation Service (WAS), which is an enhancement
available in IIS 7.0. If either of these is not suitable or we want more control over
the service, then the other solution is to build our own hosting environment by using
ServiceHost. ServiceHost is a class available in WCF to host services, almost
like a mini IIS, just for our service. We can implement ServiceHost in any housing
available under Windows, in a console app, a Windows executable, or a Windows
service (formerly NT service).

ServiceHost will listen on whatever channel we specify for our service, using
whatever protocol we specify, and call our service whenever a client request for our
specific service comes in. That�s a lot of bang for just a couple of lines of code. All
that we need to do is tell ServiceHost the endpoint that it is responsible for and
the class that it should instantiate when a matching message is received. Here�s the
code that�s required to host the LocalTimeService in a console app:

Collapse Copy Code


class TimeService
{
static void Main(string[] args)
{
Uri baseAddress = new Uri(
ConfigurationManager.AppSettings["basePipeTimeService"]);
ServiceHost serviceHost = new ServiceHost(typeof(LocalTimeService),
baseAddress);
serviceHost.Open();
Console.WriteLine("Service is running....press any key to terminate.");
Console.ReadKey();
serviceHost.Close();
}
}

You can now compile the service. However, if you try to run it, you�ll get an error
message indicating that you haven�t provided ServiceHost with an endpoint. As
we saw above, you can specify endpoints either programmatically, or by using the
configuration file. The nice thing about using configuration is that you can change it
at any time and you don�t have to recompile. As we�ll see later, you can specify
multiple endpoints for a service, depending on the clients that you want to support.
And if at some point later, you decide to not support a specific transport, you just
have to edit the configuration file.

Here�s the config file that we�ll need for the LocalTimeService:

Collapse Copy Code


<configuration>
<appSettings>
<add key="basePipeTimeService"
value="net.pipe://localhost/LocalTimeService" />
</appSettings>
<system.serviceModel>
<services>
<service name="LocalTimeService">
<endpoint
address=""
binding="netNamedPipeBinding"
contract="ILocalTime"
/>
</service>
</services>
</system.serviceModel>
</configuration>

Let�s examine the entries in the config file. You should note that there could be as
many entries as needed. For example, there could be several endpoints that the
service supports (different transports). There is also only one service being specified
in this example, but there could be several services provided in the same housing.
You can see that the endpoint has three properties: address, binding, and contract.
The binding indicated is referencing the standard netNamedPipeBinding provided
in WCF. There are various default binding classes provided for each transport. You
can see the options for each in the docs.
I will say here that you too will encounter the �zero application (non-infrastructure)
endpoints� exception at some point. There won�t be too many clues as to what
exactly is not matching up, so you�ll have to scrutinize the text. Make sure that you
have the correct namespaces specified.

Now you can execute the application, and the service will be available to any client
that knows how to communicate with it.

Proxies

Just by saying we want to go to New York and we are going to go by car, does not
get us there. We need a car to actually get us there. Having a completely defined
endpoint is not enough. We need something (code) that will actually take the
endpoint as a parameter and allow us to do what we want to do, call a method. And
that something is a proxy.

As was the case in the past with COM, proxies take care of all the low level plumbing
(serializing and packaging our parameters) so that we just need to make the call. We
don�t care how they are forced through the �spigot� or how they are pulled out on
the other side.

And as we�ve also had in the past, there is a utility that will create the proxies for
us. However, this is one area of WCF that needs some improvement. And I�m
guessing this functionality will become incorporated into Visual Studio in future
releases. At least, I would hope so. To create a proxy, you need to use the command
line utility, svcutil, which has a number of switches that are not all or well
documented. But hey, I�m not complaining, it�s a small inconvenience for a whole
lot of major improvements. And it�s still only Beta.

So, you run svcutil against your service DLL and bam! You got your proxy class.
There are other options, like if the service has a MEX endpoint, you can direct it to
the service, and it will extract the service information dynamically from the service.
This is essentially the same functionality provided through Studio when creating a
Web Service, and we use the �Add Web Reference� dialog. What I really want is for
Visual Studio to automatically generate the proxies since it has all the information in
the source files to begin with! But as I said, I�m not complaining. ;)

Currently then, creating the proxy is a two step process. First, you run svcutil
against your service DLL, which will create the schema (XSD) and WSDL files. Then,
you invoke svcutil again, but this time, you run it against the output it just created
(*.xsd, *.wsdl).

The svcutil will generate �output.cs� as the default file name, unless you specify
otherwise, I normally just rename it. There are also options to just generate
DataContracts or just ServiceContracts, and also an option to generate a
client config file. Here�s the proxy file for the LocalTimeService, with some
portions edited for readability. There�s not much there, since all the magic occurs in
ClientBase.

Collapse Copy Code


[ServiceContract]
public interface ILocalTime
{
[OperationContract]
string GetLocalTime();
}

public interface ILocalTimeChannel : ILocalTime,


System.ServiceModel.IClientChannel
{
}

public partial class LocalTimeProxy :


System.ServiceModel.ClientBase<ILocalTime>, ILocalTime
{

public LocalTimeProxy()
{
}
public string GetLocalTime()
{
return base.InnerProxy.GetLocalTime();
}
}

Consuming a WCF Service

So now, the next logical step is to build a client that knows how to consume the
service that is being provided. The client code only needs two things: the proxy that
allows it to communicate with the service, and the endpoint to the service. Here�s
one version of a client that consumes the LocalTimeService:

Collapse Copy Code


class Client
{
public bool keepClocking = true;
LocalTimeProxy proxy = null;
public Client()
{
proxy = new LocalTimeProxy();
}
public void ClockingThread()
{
while (keepClocking)
{
Console.WriteLine(proxy.GetLocalTime());
Thread.Sleep(1000);
}
proxy.Close();
}
static void Main(string[] args)
{
Client client = new Client();

//Create a separate thread to request the time once a second


Thread thread = new Thread(new ThreadStart(client.ClockingThread));
thread.Start();

Console.WriteLine("Service is running....press" +
" any key to terminate.");
Console.ReadKey();

client.keepClocking = false;
//wait 2 seconds
Thread.Sleep(2000);
}
}

Not much to this client. All that it's doing is making a call to the service method
GetLocalTime(), once a second. As you can see, the client code has no indication
as to what or where the other end of the method call is. Nor what mechanism is
actually being used to make the connection. It is just a simple class method call! As
we look at other examples, you'll keep seeing the simplicity of coding that is
provided under WCF. And here is the config file that specifies the endpoint to the
service which is required by the client.

Collapse Copy Code


<configuration>
<system.serviceModel>
<client>
<endpoint name ="LocalTimeService"
address="net.pipe://localhost/LocalTimeService"
binding="netNamedPipeBinding"
contract="ILocalTime" />
</client>
</system.serviceModel>
</configuration>

Compile and run the client. Start several instances. Just make sure that the service
is started before you start the clients, otherwise nobody will be listening.

That�s it for the basics in getting services listening and consuming services. In Part
2, we'll build some examples that will demonstrate WCF's support for the various
communication patterns. The download includes all of the source code for the sample
applications described in the articles.

A closer look at Windows Communication Foundation

Abstract

In this article I am going to take you a little bit in depth of WCF(Windows


Communication Foundation), the latest technology and framework introduced by
Microsoft to make developer life easy in distributed applications.

Introduction

To make developer's life easy, Microsoft continuously brings new technologies in the
market. Sometimes those are similar to their predecessors and sometimes they bring
large enhancements in the current technologies. As a result we can see the
processing architecture of web page is totally changed in .NET 2.0. Now .NET 2.0
does not bring significant enhancements in Winform application development. So
how can we go with a Windows application that can be distributed across diverse
operating systems and that will gain the performance benefit while used on the same
OS? The answer is WCF, i.e. Windows Communication Foundation (WCF) code name
INDIGO.

In this article we will learn the basic components of WCF and also dive into some of
the details of these components. We will try to address the issues faced in previous
versions and find out why to use WCF.

What is WCF

As mentioned earlier, WCF is the Windows Communication Foundation built on .NET


2.0 framework. It is a type of service execution framework especially made for
establishing communication between diverse systems and to gain performance
benefits on similar systems. It consolidates the best features of web service,
remoting, MSMQ, System.Messaging and Microsoft enterprise services. One of the
biggest advantages of WCF is that it supports most of the open industry standards
hence it can produce the best results across heterogeneous operations systems.
Other benefits are that it is developed using managed code and uses the power and
features of .NET 2.0. As it supports WS-* standards, it supports transaction,
security, reliability. WCF uses SOAP as its native protocol for communication.

Prerequisite

You need the following to develop a WCF service:

1. OS: Windows VISTA, Windows XP SP2, Windows 2003 Server SP1


2. VS 2005 professional edition with SP1
3. Microsoft Windows Software Development KIT
4. .NET 3.0 runtime
5. WCF extensions (while working on VS 2005 editor)

Key Components of WCF

WCF is based upon the following key components that are used to build a WCF
service. We will go in the details of each component in the sections below:

1. Contract definitions
o Data contracts and data member
o Service contracts
o Fault contracts
o Message contracts
2. End points
3. Bindings
o BasicHttpBinding
o WSHttpBinding
o WSDualHttpBinding
o WSFederationHttpBinding
o MsmqIntegrationBinding
o NetMsmqBinding
o NetNamedPipeBinding
o NetPeerTcpBinding
o NetTcpBinding
4. Hosting environments
o Windows application
o Console application
o Windows service
o IIS
o WAS (Windows activation service) comes with IIS 7.0
o Windows Presentation Foundation

Problems addressed by WCF

Till now we have seen what WCF is and what WCF components are. But unless and
until we come to know the issues addressed by WCF, we will never know the power
of WCF.

Imagine you are developing an enterprise application for a bank. Now when you start
designing the system, the requirements are very complex and critical. Say for
example, the application is used by bank staff, outside customers, some of payment
gateway systems. You are not sure that what operating system and what type of
clients will be used by outside customers. You want performance with security,
reliability when used on intranet and security, reliability when used from outside.
Previously you could have gone for web services exposing web methods for outside
clients and a remoting or COM+ application for Windows OS. Both these applications
are using the same business logic and the same database. Suppose you want to add
some new business logic like introducing a new loan system, imagine how much it
will take to change all the systems. This is perhaps the simplest example. What if
you are going to modify business logic or add 3-4 additional schemes in a span of 6
months? The current design will not scale. You will start thinking, what if I would
have a single application exposing multiple endpoints for diverse and similar clients
and will give me all benefits of industry-wide open standards. That's it. WCF is the
answer to your question. WCF, with managed code, using power and features of
.NET 2.0, giving all the benefits of performance, security, transaction, reliability by
supporting all open industry standards makes life easy for the developer and the
organization by unifying the programming model with the best features from all
available technologies.

WCF is interoperable with:

1. Web services
2. .NET - .NET communication
3. Distributed transactions
4. Support for WS-* specifications
5. Queued messaging

Key subsystems of WCF


1. Service model
2. Connector framework
3. Hosting environment
4. System services
5. Messaging services
Key components in WCF

1. Contracts
2. Bindings
3. End point definitions
4. Hosting environment

We will go in details of each component in the coming sections.

Contracts

Contracts are one of the most important components of WCF. Contracts make
developing interoperable services possible. It is a common understanding between
the client and server of available methods, data structures, and message structures.
They remain loosely coupled and platform independent. WCF contains the following
contracts. As SOAP is the native protocol of WCF for communication, interfaces,
classes are translated to SOAP types by CLR.

Service contract
 Translated to WSDL. Service contract defines the operations that a service
can perform. This is what a WCF service must contain at least one. It can
have more than one service contract also. It is defined using
[ServiceContract]attribute. The implementer of the service contract is
managed code. Hence, service contract also maps the interface and methods
to platform independent description. Using the attribute feature of .NET, we
can extend the behavior of the service like is it one way or two way, the
exception handling behavior etc.
 Each service contract contains method that are exposed outside and
annotated with [OperationContract]attribute.
 Service contract can also specify the requirements that should be satisfied by
the endpoint.
E.g. session required should satisfied by endpoints.
 Example:

Collapse Copy Code

[ServiceContract
(ProtectionLevel=System.Net.Security.ProtectionLevel.None)]
public interface IWCFService
{
[OperationContract]
string GetSystemIPAddress();

[OperationContract]
List GetEmpolyeeArray();

[OperationContract]
Employee CreateNewEmployee();
}
 Usually we can use service contract over a class too. But it is not a good
practice as interfaces allows separation from the implementation logic. While
using ServiceContract and OperationContract over a method or a
class, access modifiers does not make any sense. Everything that is marked
with ServiceContract or OperationContract will be exposed to the
client outside the application domain.
 Services are of three types:
1. Typed: Used for simple communication. It can accept or return simple
or complex data objects.
E.g. CreateNewEmployee() method in the above class
2. UnTyped: It allows developers to work at message level.
E.g. Message ParseRequest(Message myRequestMessage)
3. Typed message: Falls between typed and untyped services.
Uses custom message classes defined with Message contracts.
MyMessage ProcessedRequest(MyRequestMessage msg)

Data contract
 Translated to XML schema (XSD). Basically describes data structure. When we
want to pass or return more values, then we go for data contract. It is a
serializable object that can be passed or returned to or from a service. It
supports versioning provided you do not change the name of the existing
members, name of the namespace to maintain compatibility.
 Data contract can be defined annotating [DataContract] attribute on a
class, structure or enum. The data members that are to be exposed outside
are annotated with [DataMember] attribute for class and structure and
[EnumMember] attribute for enum.
 [DataContract] tells WCF how to serialize the object. Depending upon the
client WCF serializes the members. If the communication is between WCF and
WCF then it uses binary serialization over SOAP to optimize the performance.
While in case of WCF to Non-Windows client, it uses SOAP serialization.
 Here also access modifiers do not play any role.
 There are some cases when you do not have proxy generated for the given
service. This may be the case when the WCF service using only TCP endpoints
to allow interaction. In that case WSDL will not be available unless and until it
is explicitly defined in service behavior with HTTP end point. Even if the client
does not have WSDL with us, we can create the same WCF dummy class or
proxy class at client side. WCF service will remain as it is, the implementer
will derive from ClientBase and implement the WCF service (IWCFService).
In such a case, the operation contract method will call
base.Channel.GetSystemIPAddress() and it will be routed to the server
by foundation. In this case we can have data contract members defined in the
same way. The only thing and most important thing is that namespace must
have same names as that of server. Also method names and data member
names should remain the same.

Fault contract
 Translated to SOAP faults. Allows developer to document the errors that a
service can produce. We can define service contract only on
[OperationContract] by annotating with
[FaultContract(typeof(System.Exception))] attribute. Here the
exception type can be exception to want to document. Custom exception
should be marked as serializable.

Message contract

 Translated to SOAP messages. It describes the structure of the message like


what goes where. WCF allows the developer to control what goes where in a
message for interoperability issues. Message contracts allow you to match the
expectations of other systems concerning the SOAP message. Message
contracts can be defined using the [MessageContract] attribute. Members
participating in the SOAP message can be defined and placed at the
appropriate place using [MessageHeader] and [MessageBodyMember]
attribute.
 Example:

Collapse Copy Code

[MessageContract]
public class MyMessage
{
[MessageHeader]
public string myHeader;
[MessageBodyMember]
public Employee myMessageBody;
}

Bindings

Bindings are communication channels between a WCF service and client. They decide
how the WCF service will communicate with the client. Depending upon the different
protocols like HTTP, TCP, MSMQ, there are different types of binding. Binding
supports encoding of messages using text encoding, binary encoding and Message
Transmission Optimization mechanism (MTOM, interoperable message format used
for effective transmission of large attachments greater than 64K) As WCF supports
all industry open standards, it supports security using SSL and WS-Security (schema
defined security) standards.If we want
session enabled service then binding determines whether the service is session
enabled or not. Not all binding supports sessions. As WCF is extendible, we can
define our own custom bindings. But this is very rare case because WCF has nine in-
built bindings that are sufficient for most of the applications. The exceptions can be:
RSS feed of a site or SMTP protocol.

Basic web service communication with no security


1 BasicHttpBinding :
by default
Web services with WS-* standards, supports
2 WSHttpBinding :
transactions
Web services with duplex contract and transaction
3 WSDualHttpBinding :
support
Web services with federated security with
4 WSFederationHttpBinding :
transaction support
Direct communication with MSMQ, supports
5 MsmqIntegrationBinding :
transaction
Communication between WCF applications using
6 NetMsmqBinding :
queuing with transaction support
Communication between WCF applications on the
7 NetNamedPipeBinding : same computer with duplex contracts support and
transaction support
Communication between computers across peer-
8 NetPeerTcpBinding :
to-peer services with duplex contracts support
Communication between WCF applications across
9 NetTcpBinding : computers supports duplex contracts and
transactions

Here is the mapping of base address schemes to the transport protocols:

http : HTTP
net.tcp : TCP
net.pipes : Names pipes
net.msmq : MSMQ
End points

End points are nothing but a URI which are exposed to the outside world and from
where the client can connect to the WCF service.
Each end point consists of:

 Base address: Where to send message (A)


 Type of binding: How to send message (B)
 Contract: What to send in a message (C)

We can define as many end points as the application requires. For example, if the
application is to be used by a JAVA client and WPF client then we can expose an
endpoint with TCP binding where the WPF client will communicate and an end point
with basic HTTP binding where JAVA client will communicate. We can control and
configure the behavior of an end point programmatically and using application
configuration file.

Hosting environments

The architecture of an WCF application is usually like this:


Database layer => Business logic layer => WCF service => Hosting environment

As the diagram shows, we need a host to run a WCF service. Fortunately there are
many options that can be used for hosting a WCF service. This actually depends
upon the application requirement. Following is the list of hosts:

1. Windows application: Simple winform application


2. Console application: Simple console application
3. Windows service: WCF service can be controlled by the Service control
manager
4. IIS: Can be hosted in IIS provided the service exposes at least one HTTP end
point
5. WAS (Windows Activation Service) comes with IIS 7.0: Removes
dependability upon HTTP
6. Windows Presentation Foundation

Security in WCF

When you go for a distributed application, the most important aspect is security. As
mentioned earlier, WCF supports security using binding. Binding supports security
using SSL, WS-Security standards. You can also use Windows authentication. One of
the primary goals behind WCF development was to make it easy for the development
of secured applications. WCF service can be secured using four ways:

1. Authentication
2. Message integrity
3. Message confidentiality
4. Authorization

There are some guidelines about using security mechanisms. Depending upon the
application need and requirement, we can easily select the suitable one and
implement with few efforts. Here are the guidelines:

 Use a standard binding that directly supports security. For example,


applications that
require end-to-end security for messages that go through multiple SOAP
intermediaries can use a binding that supports WS-Security, such as
WsHttpBinding.
 Use a standard binding that optionally supports security, and then configure it
as needed. For example, applications that need only transport-based security
can choose BasicHttpBinding, configuring it to use HTTPS rather than
HTTP. It's also possible to customize other more-advanced security behaviors.
For example, the authentication mechanism used by a binding such as
WsHttpBinding can be changed if desired.
 Create a custom binding that provides exactly the security behavior a
developer needs. Doing this is not for the faint of heart, but it can be the right
solution for some advanced scenarios.
 Use a standard binding that provides no support for security, such as
BasicHttpBinding. While using no security is a risky thing to do, it can be
the only option in some situations.

Other important features

There are many other features which are present in WCF and can be used to achieve
reliable communication. Those are as follows:

 Transactions: WCF uses System.Transactions to control the transaction in


a distributed application.
Service behavior can also control a transaction using the parameters in the
[ServiceBehavior] attribute. An operation contract can force a transaction
using [OperationBehavior] attribute if the operation is very critical. If the
client also supports WS-AutomicTransaction then a JAVA client and WCF
service can share the same transaction. Some binding like WsHttpBinding
and NetTcpBiinding also allows configuring the transaction flow. E.g.
Queuing: Using NetMsmqBinding or MsmqIntegrationBinding, WCF
supports queuing of messages.

Collapse Copy Code

[OperationContract]
[OperationBehavior(TransactionScopeRequired=true,
TransactionAutoComplete=true)]
public void TransferMoney(Account creditor, Account debitor)
{
//
}
 Queuing: Using NetMsmqBinding or MsmqIntegrationBinding, WCF
supports queuing of messages.
 Extensibility: WCF allows creating custom channels, bindings as per the
application requirements. For example you can create a channel for
communicating with SMTP protocol or RSS protocol.

Application outline

The attached application solution contains six projects:

1. Console client: It calls the WCF service without creating a proxy. Contract and
data members are created manually at client side. It uses simple TCP binding.
2. MsmqClient: As the name says, it uses MSMQ binding. The MSMQ must be
installed and the private queue with the given name should be created before
running this application.
3. SystemInfo: Simple data access class. It does nothing special. WCF service
calls methods of this class.
4. WCFClient: Simple Windows application to demonstrate working of WSDL
created using svcutil. Uses Basichttp binding.
5. WCFHost: A simple console application acting as a host for WCF service.
6. WCFservice: Actual WCF service with service contract and data contract.
Also contains .SVC file so that it can be hosted in IIS directly. It also contains
other details required for MSMQ binding. There is one implementer class
which implements service contracts. Most of the code is self explanatory. Your
suggestions are always welcome.

Conclusion

We can conclude that WCF simplifies the creation of distributed applications on


Windows. Because it implements SOAP and the most important WS-* specifications,
WCF provides full-featured interoperability with other Web services platforms. And
because it offers explicit support for a service-oriented approach, WCF gives
developers a natural environment for building modern software.

License
This article has no explicit license attached to it but may contain usage terms in the
article text or the download files themselves. If in doubt please contact the author
via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Communication options with WCF - Part 1

Dynamic LINQ To Entities Queries Using WCF/WPF


demo code

Contents

 Introduction
 PreRequisites
 Things To Do To Get It Running For You
 Show It
 LINQ to Entities
 WCF Service
 Windows Service Hosting And Installation
 WPF Client

Introduction

It has been a while since I have undertaken a large article, so I thought it was about
time I corrected that, and wrote a fairly meaty article. This article represents this
meat.

So I suppose I should start by stating what it is this article will cover. Well it's going
to cover quite a lot actually. The basic idea is that there is a SQL Server database
somewhere that has the Northwind database installed, and that we will be using an
ORM to obtain data from this database using a WCF service. The WCF itself will be
hosted inside a Windows service which will be installed via a customer installer.

In order to interact with this Windows hosted WCF service we will be using a WPF
client application. The WPF client application will allow the user to obtain particular
entities (Customers only as I would have been writing this article for ever to allow for
everything) to be queried using a custom query builder that will then be used to
send to the Windows hosted WCF service, which in turn will then query the ORM for
the queried entities, and return the results to the WPF client app.

In essence that is it, it may not be that exciting, but there is enough here for me to
show you how to create a service/client and an hosting windows service. Also along
the way I will be taking slight detours to talk about certain practices and cool code
that may make your life easier.

I should point out that the UI was meant to be a throw away, ok I tried to make it an
ok looking one, but that's just because I like WPF. I mean there is still some nice
ideas in there, like the way the queries are constructed, that could be ported to a
richer query generator, but that is left for an excercise to the reader.

PreRequisites

You will need VS2008 (for the Entity Framework) and VS2008 SP1, and .NET 3.5 SP1
installed.

Things To Do To Get It Running For You

In order to get the attached code (WCF service hosted in a windows service/WPF
client) you will need to make sure the following has been done

1. That the windows service has been installed and provided with login details as
part of the installation
2. That the LINQ to Entities connectionStrings section of the associated .Config
file are updated to point to your local SQL server installation
3. That the windows service is running when you attempt ot use the WPFClient
4. That the App.Config within the WPFClient project is configured to use the
correct security login, this is in the identity/userPrincipalName element.

Just to get you a little bit more familiar with it all here is the project structure
Show It

So what does it look like when running, well I decided to show you some screen
shots and also have a link to a small video for this one.
Initial view loaded
Changing the type of view for the selected Customer Orders

Starting to build up a dynamic query.

LINQ to Entities

For the ORM I had originally thought about using LINQ to SQL, but you know I think
Microsoft are slowly sweeping (personal opinion) that one under the carpet, in favour
of LINQ to Entities. So I thought why not use LINQ to Entities. So that's what this
article uses for the ORM.

I had in the past installed the LINQ to Entities whilst it was still in BETA and it was
horrible, the designer used to churn out 3 sections of XML:

CSDL : Conceptual schema definition language (CSDL)

MSDL : Mapping specification language (MSL)

SSDL : Store schema definition language (SSDL)

As I saw the designer used to create these, but not all that well in the old days and
you always had to get your hands dirty in the XML, and there was loads of it, a
couple of 1000nd lines for a small database. Eeek.
If you want to know how bad this was just use any of the 3 links above.

Mantaining these 3 sections of XML using the old beta of LINQ to Entities was a
frigging nightmare. Thankfully the new designer does away with the user having to
worry about the XML directly. Which I think is a good thing. What happens now is
that the cod behind for the designer is now a C#|VB class that has a App.Config file
associated with it, with a very strange ConnectionStrings section. Let us have a
look at one of these:

Collapse Copy Code


<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<!-- HOME -->
<add name="NorthwindEntities"
connectionString="metadata=res://LINQ2Entities/Northwind.csdl|
res://LINQ2Entities/Northwind.ssdl|
res://LINQ2Entities/Northwind.msl;provider=System.Data.SqlClient;
provider connection string="Data Source=VISTA01\SQLEXPRESS;
Initial Catalog=Northwind;Integrated Security=True;
MultipleActiveResultSets=True""
providerName="System.Data.EntityClient" />

</connectionStrings>
</configuration>

To run the attached code you will need to change the associated config within the
folder where you decide to install the service using the installer, this is covered later
within the article in section Windows Service Hosting And Installation.

We can see that there are still links to the CSDL/MSL/SSDL, but there are now
treated as metadata resources. Much nicer.

So if we now focus our attention to the LINQ to Entities designer, we can see that we
have something like the LINQ to SQL designer, but it is a little different. This is to
allow an Entity to be constructed from multiple views|tables.
For this example I will however be using a 1 to 1 mapping between Entity and
Northwind database table.

LINQ To Entities SQL Language

LINQ to Entities actually goes one step further than LINQ to SQL did in that it now
supports a full blown SQL query language, which as far as I can tell is actually the
same as SQL syntax. Here is a small example.
Collapse Copy Code
using (AdventureWorksEntities advWorksContext =
new AdventureWorksEntities())
{
string esqlQuery = @"SELECT contactID, AVG(order.TotalDue)
FROM AdventureWorksEntities.SalesOrderHeader
AS order GROUP BY order.Contact.ContactID as
contactID";

try
{
foreach (DbDataRecord rec in
new ObjectQuery<DbDataRecord>(esqlQuery, advWorksContext))
{
Console.WriteLine("ContactID = {0} Average TotalDue = {1} ",
rec[0], rec[1]);
}
}
catch (EntityException ex)
{
Console.WriteLine(ex.ToString());
}
catch (InvalidOperationException ex)
{
Console.WriteLine(ex.ToString());
}
}

Now the fact that we can store a String with a query is kind of nice, as it means we
can pass a query accross a service boundary, which AFAIK was something that LINQ
to SQL just couldn't do out of the box. I mean you couldn't serialize a
Expression<Func<Customers,Bool>> nor could you return a var , as var has
method level scope. You are also unable to create LINQ queries at a Client and
serialize them (though this would be very cool) and send them to a service to run.
So LINQ to SQL was definately limited. So this new String query ability appears to
be a good thing at first glance.

But let's just think about that for a minute, we used to able to do this sort of thing
with inline/across the wire SQL using ADO.NET and look what a mess that was, not
to mention SQL Injection Attacks. So one would have to ask whether this was a good
thing after all. I mean what is to stop a malicous user from creating there own query
string, the fact that it now uses the Entity Framework rather than the actual
database doesn't really matter to the malicous user, they would probably get the
same results.
I think a far better option to is to just limit the search results by using a dynamically
generated Where clause, or if you have time to create a SQL Query builder that
never actually contains the full string, until the last second when it needs to create
the actual query string, and pass it to the DB|ORM. The later approach is what we
actually do at work, this article will actually discuss the dynamically generated Where
clause solution.

Dynamic Where Clauses

LINQ to Entities actually offers a ObjectQuery<T>.Where method that accepts a


string and an array of ObjectParameters
According to the ObjectParameters documentation the following should actually
work. Unfortunately it doesn't seem to like the ObjectParameters names.

How annoying. Oh well, luckily help is at hand. Recall what I said about LINQ to SQL
not being able to run dynamic queries out of the box, well that was/is true. There is
however an extra Microsoft constructed class that has IQueryable<T> extension
methods that allow both LINQ to Entities and LINQ to SQL to create dynamic where
clauses.

So if we change the original query to to use the DynamicQuery API we can


successfully run this query. We must however use numbered parameters which is a
bit of a pain, but it is still better than the LINQ 2 Entities horror show shown above. I
can only imagine the reason for the problem shown above is that the LINQ to Entities
implementation has some strange parsing in there to try and make the actual SQL,
whilst the DynamicQuery API will try and create a
Expression<Func<Customers,Bool>>
How These 2 APIs Differ

As just mentioned when using the native LINQ to Entites ObjectQuery<T>.Where


method, the System.Data.Entity classes actually try and generate actual SQL
which can be used against the database.
Let's now see how the DynamicQuery API works. What it does it provide an
extension method against a IQueryable<T> type, and it creates an Expression
tree, based on the input values.

Here is a small section of the DynamicQuery API :

Collapse Copy Code


public static IQueryable<T> Where<T>(this IQueryable<T> source,
string predicate, params object[] values)
{
return (IQueryable<T>)Where((IQueryable)source, predicate, values);
}

public static IQueryable Where(this IQueryable source,


string predicate, params object[] values)
{
if (source == null) throw new ArgumentNullException("source");
if (predicate == null) throw new ArgumentNullException("predicate");
LambdaExpression lambda =
DynamicExpression.ParseLambda(source.ElementType,
typeof(bool), predicate, values);
return source.Provider.CreateQuery(
Expression.Call(
typeof(Queryable), "Where",
new Type[] { source.ElementType },
source.Expression, Expression.Quote(lambda)));
}

Some of you may recall that I recently wrote an article about Expression Trees and
went to show you how they worked. This DynamicQuery API is the entire reason that
I wrote that article.
So I hope you can now see why we might want to create an Expression Tree at
runtime. It allows us to create a dynamic query based on an Expression Tree.

WCF Service

Overall Structure

The WCF service is actually pretty simple, the entire ServiceContract is shown
below.

Collapse Copy Code


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace Service.Portal
{
[ServiceContract(
Namespace = "http://www.sachabarber.net/2008/cp",
SessionMode = SessionMode.Allowed)]
public interface IPortal
{
//Allows FaultContract(s) to callback
[OperationContract(IsOneWay = false)]
//Allows TransactionScope at client
[TransactionFlow(TransactionFlowOption.Allowed)]
//Allows SOAP faults to client
[FaultContract(typeof(ApplicationException))]
[FaultContract(typeof(ArgumentException))]
[FaultContract(typeof(Exception))]
Response ExecuteRequest(Request request);
}
}

It can be seen from the code above that there is a single ExecuteRequest
OperationContract that accepts a Request and returns a Response. Sounds
easy enough, but aren't there going to be many many Request objects. Well yes
actually, but is just a bit of standard OO polymorphism in play. Where we can store
any sub class of Request in its base class. Ill cover this in a minute for now let's
carry on examining the service, it can be seen that the single ExecuteRequest
OperationContract it marked as OneWay=false, this means that there is a
callback to the client from the service. You may notice that I am not specifying a
CallBack interface anywhere, so what is the OneWay=false all about. Quite simply it
allows faults to be sent back to the client. More on this later. The other thing to note
is that the service allows transactions to be used should the client wish to use them.

Let's now have a look at the Request object shall we.

Collapse Copy Code


using System;
using System.Runtime.Serialization;

namespace Service.Portal
{
/// <summary>
/// A Base request
/// </summary>
[DataContract]
[KnownType(typeof(CustomerRequest))]
[KnownType(typeof(CustomerSearchRequest))]
public abstract class Request : IExtensibleDataObject
{
#region Data
private ExtensionDataObject extensionDataObject=null;
#endregion

#region Abstract Methods


public abstract Response CreateResponse(Object requestResults);
public abstract Object Execute();
#endregion

....
....

That's essentially it. By using this approach you do not have to worry about a
changing service, as the ServiceContract is always the same, the only thing that
changes is the number of Requests.

And here is a specific Response DataContract class.

Collapse Copy Code


namespace Service.Portal
{
[DataContract]
public class CustomerResponse : Response
{
[DataMember(IsRequired = true, Name = "Customers")]
public List<Customers> Customers { get; set; }

}
}

KnownTypes

One of the really cool things about WCF is that you can expose a type such as
Request which has many sub classes, and you can mark the base class (Request in
this case) up with a KnowTypeAttribute and the DataContractSerializer will
know how to treat these.

Within the attached demo application there are only 2 sub classes of Request, but
they should serve well enough to demonstrate the idea of working with KnowTypes.

IExtensibleDataObject

"The IExtensibleDataObject interface provides a single property that sets or


returns a structure used to store data that is external to a data contract. The extra
data is stored in an instance of the ExtensionDataObject class and accessed through
the ExtensionData property. In a roundtrip operation where data is received,
processed, and sent back, the extra data is sent back to the original sender intact.
This is useful to store data received from future versions of the contract. If you do
not implement the interface, any extra data is ignored and discarded during a
roundtrip operation."

MSDN link : http://msdn.microsoft.com/en-


us/library/system.runtime.serialization.iextensibledataobject.aspx

In practical terms what this means is that by making your DataContract class
implement IExtensibleDataObject you are creating a versionable object.

In the attached demo code Request/Response implement


IExtensibleDataObject as follows:

Collapse Copy Code


using System;
using System.Runtime.Serialization;

namespace Service.Portal
{
[DataContract]
[KnownType(typeof(CustomerRequest))]
[KnownType(typeof(CustomerSearchRequest))]
public abstract class Request : IExtensibleDataObject
{
private ExtensionDataObject extensionDataObject=null;

public ExtensionDataObject ExtensionData


{
get { return extensionDataObject; }
set { extensionDataObject = value; }
}
}
}

ExtensionDataObject has a internal linked list of object references and type


information and it knows where unknown data members are stored. When an object
implements IExtensibleDataObject, and when a request is made that includes
unknown data members they are stored in the list of unknown members within the
internal list. If a request for an unknown data member is made that includes
unknown types, the unknown data members can be found and deserialized by using
the ExtensionDataObjects internal list of unknown data members.

Basically this is a good idea and one that I recommend that you all do.

Fault Contracts

If we now visit the WCF service and have a look at the class that implements the
ServiceContract

The WCF service is actually pretty simple, the entire ServiceContract is shown
below.

Collapse Copy Code


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace Service.Portal
{
[ServiceContract(
Namespace = "http://www.sachabarber.net/2008/cp",
SessionMode = SessionMode.Allowed)]
public interface IPortal
{

//Allows SOAP faults to client


[FaultContract(typeof(ApplicationException))]
[FaultContract(typeof(ArgumentException))]
[FaultContract(typeof(Exception))]
Response ExecuteRequest(Request request);
}
}

We can see that we are catching Exceptions and throwing some strange looking
FaultException<T>. Where the FaultException<T> are used in a client
application to catch contractually-specified SOAP faults. It can be seen that the
service implementation is set for per call, which means we will get a new service per
call, and we are not concerned with dealing with a threading synchronization context.
The other thing to mention is that we have a small helper that lets use
IncludeExceptionDetailInFaults if we are in debug mode, and not in release
mode. The single operation is also marked to not allow impersonation. There is no
need to allow impersonation in the attached service code, as it is the only service
within the call chain so there is no need to flow the current credentials to another
service. I have also insisted the service participate in trasactional calls, where the
client code will need to use a TransactionScope class to manage the transaction.
The TransactionAutoComplete property indicates that if no unhandled exceptions
occur, the transaction scope is completed automatically.

Collapse Copy Code


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Reflection;

namespace Service.Portal
{
[ServiceBehavior(
InstanceContextMode= InstanceContextMode.PerCall,
UseSynchronizationContext = false,
IncludeExceptionDetailInFaults =
DebugHelper.IncludeExceptionsInFaults)]
public class Portal : IPortal
{

#region IPortal Members


[OperationBehavior(Impersonation = ImpersonationOption.NotAllowed,
TransactionScopeRequired = true, TransactionAutoComplete = true)]
public Response ExecuteRequest(Request request)
{
Response r = null;

if (request == null)
throw new ArgumentNullException("request");

try
{
Object results = request.Execute();
r = request.CreateResponse(results);
}
...
...
...
catch (Exception ex)
{
Console.WriteLine(String.Format("Server Exception {0}",
ex.Message));

throw new FaultException<Exception>(


new Exception(ex.Message));
}

return r;
}

#endregion

//simply debug class to IncludeExceptionsInFaults in debug mode


public static class DebugHelper
{
public const bool IncludeExceptionsInFaults =
#if DEBUG
true;
#else
false;
#endif

Windows Service Hosting And Installation

As I said right at the start of this article the WCF service is actually hosted inside a
Windows service. Inside the attached demo you will find a seperate project that
allows you to debug the WCF service by the use of the following code if you are in
debug mode (where you would right click the PortalHost project and choose
"debug"), or run the service normally if you are in release mode.

Collapse Copy Code


using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Reflection;

namespace PortalHost
{
class Program
{
static void Main(string[] args)
{
#if (!DEBUG)
try
{

ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new Service() };
ServiceBase.Run(ServicesToRun);
}
catch (Exception e)
{
Console.WriteLine("Error occurred " + e.Message);
}
#else
try
{
Console.WriteLine("Starting Service");
Service.StartService();
Console.WriteLine("Service Started");

System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);

}
catch (Exception e)
{
Console.WriteLine("Error occurred " + e.Message);
}

#endif
}
}
}

Where the actual Window Service class looks like this :

Collapse Copy Code


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.ServiceModel;
using System.Reflection;
using Service.Portal;
using System.ServiceModel.Description;

namespace PortalHost
{
public partial class Service : ServiceBase
{
private static ServiceHost portalHost;

public Service()
{

}
protected override void OnStart(string[] args)
{
Service.StartService();
}

public static void StartService()


{
try
{
//WCF service hosting
portalHost = new ServiceHost(typeof(Portal));
StartServiceHost(portalHost);
}
catch (TargetInvocationException tiEx)
{
Console.WriteLine("Error occurred " + tiEx.Message);
}
catch (Exception ex)
{
Console.WriteLine("Error occurred " + ex.Message);
}
}

....
....

private static void StartServiceHost(ServiceHost serviceHost)


{
try
{
// We will recreate the service host here to be sure we don't
have a
//service in a faulted state
serviceHost = new
ServiceHost(serviceHost.Description.ServiceType);
Console.WriteLine("Attempting to open Service.Portal service.");
serviceHost.Open();
serviceHost.Faulted += new EventHandler(ServiceHost_Faulted);
}
....
....
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}

....
....

}
}

Also part of the PortalHost project is a custom installer that looks like the following:

Collapse Copy Code


using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Linq;
using System.ServiceProcess.Design;
using System.ServiceProcess;
using System.Windows.Forms;

namespace PortalHost
{
[RunInstaller(true)]
public partial class ProjectInstaller : Installer
{
public ProjectInstaller()
{
InitializeComponent();
}

// Prompt the user for service installation account values.


public static bool GetServiceAccount(ref ServiceProcessInstaller
svcInst)
{
bool accountSet = false;
ServiceInstallerDialog svcDialog = new ServiceInstallerDialog();
//Use the ServiceInstallerDialog to customise the
username and password for
//the installation process
....
....

return accountSet;
}

}
}

Where we are using the following support classes


ServiceProcessInstaller/ServiceInstaller and a
ServiceInstallerDialog (to capture the username and password during the
installation).

Handling A Faulted WCF Channel Within The Windows Service

When dealing with WCF the last thing one wants to hear about is a faulted channel,
this is incredibly bad news. Basically a faulted channel is beyond useless. So what
can we do about this situation within a hosting Windows service? Well quite simply,
what we do is catch the ServiceHost.Faulted exception, which WCF allows us to
do (thank god) and stop/restart the WCF service. This is demonstrated below:

Collapse Copy Code


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.ServiceModel;
using System.Reflection;
using Service.Portal;
using System.ServiceModel.Description;

namespace PortalHost
{
public partial class Service : ServiceBase
{
private static ServiceHost portalHost;

public Service()
{
}

protected override void OnStart(string[] args)


{
Service.StartService();
}

public static void StartService()


{
....
....

private static void StartServiceHost(ServiceHost serviceHost)


{
....
....

private static void StopServiceHost(ServiceHost serviceHost)


{
....
....
}

private static void RestartServiceHost(ServiceHost serviceHost)


{
StopServiceHost(serviceHost);
StartServiceHost(serviceHost);
}

private static void ServiceHost_Faulted(Object sender, EventArgs e)


{
ServiceHost serviceHost = sender as ServiceHost;
Console.Write(String.Format("{0} Faulted. Attempting Restart.",
serviceHost.Description.Name));
RestartServiceHost(serviceHost);
}

}
}

Installation

As previously stated the attached demo WCF service is actually hosted inside a
Windows service, and as most of us should know a Windows service runs under a
particular user account. But how does one install a Windows service?

The attached demo code has an installer that deals with installing the windows
service that hosts the WCF service. As part of this installation process you will be
prompted for login credentials for the service.

Using InstallUtil.exe

A Windows service can be installed using the InstallUtil.exe command line util. So in
order to install the attached Portal service you will need something like

installutil.exe
C:\Users\sacha\Desktop\Linq2WCF_NEW\Linq2WCF\Linq2WCF\PortalHost\bin\Releas
e\PortalHost.exe

Which when run will have a Dialog like the following where you can put in the
account details for the Windows service to use.

Using An MSI

The attached demo solution actually has an installer entitled "PortalMSIInstaller",


which is a typical installer/setup project that simply uses the output of the Windows
Service project "PortalHost". The only thing to not using this project is that the
service is installed and must then be configured to use the correct login credentials
as these are not provided as part of the installation process. The MSI also uses the
ServiceInstallerDialog, but this window is sometimes pushed to the back so
you may have to use task manager to find it as part of the installation process.

The ServiceInstallerDialog code that is used within the custom installer for the
service, that is used to show the service login screen below, is as follows:

Collapse Copy Code


// Prompt the user for service installation account values.
public static bool GetServiceAccount(ref ServiceProcessInstaller
svcInst)
{

bool accountSet = false;


ServiceInstallerDialog svcDialog = new ServiceInstallerDialog();

// Query the user for the service account type.


do
{
svcDialog.TopMost = true;
svcDialog.StartPosition = FormStartPosition.CenterScreen;
svcDialog.ShowDialog();

if (svcDialog.Result == ServiceInstallerDialogResult.OK)
{
// Do a very simple validation on the user
// input. Check to see whether the user name
// or password is blank.

if ((svcDialog.Username.Length > 0) &&


(svcDialog.Password.Length > 0))
{
// Use the account and password.
accountSet = true;

svcInst.Account = ServiceAccount.User;
svcInst.Username = svcDialog.Username;
svcInst.Password = svcDialog.Password;
}
}
else if (svcDialog.Result ==
ServiceInstallerDialogResult.UseSystem)
{
svcInst.Account = ServiceAccount.LocalSystem;
svcInst.Username = null;
svcInst.Password = null;
accountSet = true;
}

if (!accountSet)
{
// Display a message box. Tell the user to
// enter a valid user and password, or cancel
// out to leave the service account alone.
DialogResult result;
result = MessageBox.Show(
"Invalid user name or password for service
installation." +
" Press Cancel to leave the service account
unchanged.",
"Change Service Account",
MessageBoxButtons.OKCancel,
MessageBoxIcon.Hand);

if (result == DialogResult.Cancel)
{
// Break out of loop.
break;
}
}
} while (!accountSet);

return accountSet;
}

Which the installer is run it will allow you to enter the service login credentials to run
under, using the following dialog box.

Once the installer has been run you will need to change the Config file to point to
your own SQL server installation. The default config file is the name of the output
project used by the installer project, where the config file will be something like
"PortalHost.exe.config", and you should make sure to change the
<connectionStrings> section.
I'll leave it as an excercise to the reader to have a look at the "PortalMSIInstaller"
project, its all fairly standard stuff.

Starting The Windows Service (That hosts the WCF service)

Once the service is installed you will need to start it. This is easily done using the
services manager.

WPF Client

The attached "WPFClient" project carries out the following functions

 Provides a WCF setup diagnostics screen, which we have found quite


invaluable at work, as we can get non techie users to print a screen of there
setup, without the need to have to locate and open a App.Config file.
 Provides a 3D carosel view over a list of LINQ to Entities retrieved Customer
objects
 Provides a list of LINQ to Entities retrieved Order objects for the current
Customer
 Provides a search builder screen that allows the user to build up dyanamic
queries, in order to query the LINQ to Entities layer via a WCF Request.

I shall tackle each of these areas in turn in the rest of the sections below

Basic WPFClient Project Setup

Before we start to get into the code, I would like to talk about the rough structure of
the application.

Windows

There are 2 windows, 1 diagnostics window and 1 main window. The main window
hosts a 3D carosel and a both a CurrentCustomerControl and a
CurrentCustomerOrdersControl control.
UserControls

CurrentCustomerControl : Is a pretty simple user control that shows a reflected


image and the currently selected Northwind.Customers name

CurrentCustomerOrdersControl : Shows a list of the currently selected


Northwind.Customers.Orders in a ItemsControl. There are 3 different views, for
showing more or less information about the bound data to the user.

SearchControl : Holds n-many SearchClauseControls

SearchClauseControl : Allows a search clause to be built up for a single property


of the bound object

ViewModels

The attached code is using the MVVM pattern, for the main window
(CustomerOrdersViewModel) and the SearchClauseControl
(SearchClauseViewModel)

Rest Of The Codebase

As for the rest of the code I think it's all pretty standard WPF stuff, like Attached
Properties / Styles / Commands etc etc

Making Sure You Have The Correct User, For The WCF Service Calls

In order to correctly use the WCF service being hosted in the Windows service
(assuming it is installed and running), you will need to supply login credentials, this
is done via the identity\userPrincipalName section of the App.Config file for the
"WPFClient" project in the attached code.

Collapse Copy Code


<identity>
<userPrincipalName value="YOUR PC\YOUR USER" />
</identity>
WCF Setup Diagnostics

I think any help that you can give end users, to aid in problems that they may
encounter is a good thing.

It should also be remembered that some users may not actually be technically
minded, so would not relish the thought of trawling around for an App.Config file and
having to look at XML, some I vouch would not even know what XML is. So
protecting users from that is pretty nessecary in my opinion.

To this end I have created a small diagnostics screen that allows a user to view
diagnostic information about the WCF configuration associated with the given Client
App.Config file. The following code applies equally to a WPF/WinForms or a console
app that consumes a WCF service.

The code basically using some of the Configuration based classes found in the
System.ServiceModel.Configuration namespace, along with a little reflection
to search the App.Config file for all relevant WCF elements and to use this to display
in a diagnostic window.

The main code is shown below.

Collapse Copy Code


/// <summary>
/// Gets client EndPoint information out of the attached App.Config
/// </summary>
public List<String> EndPoints
{
get
{
// Automatically find all client endpoints and related
//bindings defined in app.config
List<String> endpointNames = new List<String>();

try
{
BindingsSection bindingsSection =
ConfigurationManager.GetSection(
"system.serviceModel/bindings") as BindingsSection;

if (bindingsSection == null)
{
Console.WriteLine(
"The configuration file doesn't contain " +
"a system.serviceModel/bindings configuration section");
}
else
{
endpointNames.Add("BINDINGS");
foreach (BindingCollectionElement bce in
bindingsSection.BindingCollections)
{
AnalyseBinding(endpointNames, bce);
}
}

ClientSection clientSection =
ConfigurationManager.GetSection(
"system.serviceModel/client") as ClientSection;

if (clientSection == null)
{
Console.WriteLine("The configuration file doesn't " +
"contain a system.serviceModel/client configuration
section");
}
else
{
ChannelEndpointElementCollection endpointCollection =
clientSection.ElementInformation.
Properties[String.Empty].Value as
ChannelEndpointElementCollection;

endpointNames.Add(Environment.NewLine);
endpointNames.Add("ENDPOINTS");
foreach (ChannelEndpointElement
endpointElement in endpointCollection)
{
GetPropetiesFromType(endpointNames,
endpointElement.GetType(), endpointElement);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);

}
return endpointNames;
}
}

And here is are 2 small helper methods that are used to obtain property values

Collapse Copy Code


private void AnalyseBinding(List<string> endpointNames,
BindingCollectionElement bce)
{
foreach (IBindingConfigurationElement be in bce.ConfiguredBindings)
{
GetPropetiesFromType(endpointNames, be.GetType(), be);
}
}

private void GetPropetiesFromType(List<string> endpointNames,


Type type, Object source)
{
PropertyInfo[] pis = type.GetProperties();
if (pis.Length > 0)
{
foreach (PropertyInfo pi in pis)
{
bool foundSysName = false;
String currentValue = pi.GetValue(source, null).ToString();
if (currentValue.Contains("System.Configuration"))
return;

if (currentValue.StartsWith("System.ServiceModel"))
{
Object o = pi.GetValue(source, null);
foundSysName = true;
GetPropetiesFromType(endpointNames, o.GetType(), o);

}
if (!foundSysName)
endpointNames.Add(String.Format("{0} - {1}",
pi.Name, currentValue));
else
endpointNames.Add(String.Format("{0} - {1}",
pi.Name, "<SEE ABOVE>"));
}
endpointNames.Add(Environment.NewLine);
}
}

3D Carosel

For the 3D carosel, I am using the truly excellent ElementFlow that is part of the
FluidKit codeplex contribution by Pavan Podila. This is an excellent WPF control that I
have toyed with creating myself in the past. When I found Pavans code, I basically
gave up as its so cool. It acts just like a regular panel, which means you can use it
inside ListBoxes, ItemsControls instead of the normal panels these controls use.
Pavan has done a bang up job, and this ElementFlow comes with the following
features

 SelectedItem
 Reflection On|Off
 Many many different views that are part of the standard control, that you can
see in action using the F12 key. I am only using the following views, but there
are others.
o CoverFlow
o Carousel
o RollerCoaster
o Rolodex

The 3D carosel is initially loaded with a list of 15 Northwind.Customers where the


Custom must have more than 2 Orders. This is done by using the WCF
CustomerRequest, which is done on the initial application startup.
Customers.Orders lists

From the 3D Carosel that is used to hold a list of Northwind.Customers with Orders,
the selected Customer is used to bind against a DP within the
CurrentCustomerOrdersControl control. And from inside the
CurrentCustomerOrdersControl control, a CustomerOrders DP is set with the
current Northwind.Customers.Orders. This is shown below

Collapse Copy Code


/// <summary>
/// CustomerOrders Dependency Property
/// </summary>
public static readonly DependencyProperty CustomerOrdersProperty =
DependencyProperty.Register("CustomerOrders", typeof(List<Orders>),
typeof(CurrentCustomerOrdersControl),
new FrameworkPropertyMetadata(null,
new PropertyChangedCallback(OnCustomerOrdersChanged)));

/// <summary>
/// Gets or sets the CustomerOrders property.
/// </summary>
public List<Orders> CustomerOrders
{
get { return (List<Orders>)GetValue(CustomerOrdersProperty); }
set { SetValue(CustomerOrdersProperty, value); }
}

/// <summary>
/// Handles changes to the CustomerOrders property.
/// </summary>
private static void OnCustomerOrdersChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
List<Orders> orders = e.NewValue as List<Orders>;

if (orders != null)
((CurrentCustomerOrdersControl)d).lstOrders.ItemsSource = orders;
}

/// <summary>
/// BoundCustomer Dependency Property
/// </summary>
public static readonly DependencyProperty BoundCustomerProperty =
DependencyProperty.Register("BoundCustomer", typeof(Customers),
typeof(CurrentCustomerOrdersControl),
new FrameworkPropertyMetadata(null,
new PropertyChangedCallback(OnBoundCustomerChanged)));

/// <summary>
/// Gets or sets the BoundCustomer property.
/// </summary>
public Customers BoundCustomer
{
get { return (Customers)GetValue(BoundCustomerProperty); }
set { SetValue(BoundCustomerProperty, value); }
}

/// <summary>
/// Handles changes to the BoundCustomer property.
/// </summary>
private static void OnBoundCustomerChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
Customers customer = e.NewValue as Customers;

if (customer !=null)
((CurrentCustomerOrdersControl) d).CustomerOrders = customer.Orders;
}
Once the Northwind.Customers.Orders are obtained they are used as a source of the
embedded ItemsControl, within the CurrentCustomerOrdersControl.

There are also 3 buttons on the CurrentCustomerOrdersControl that can be


used to change the current DataTemplate that is applied to the ItemsControl.

Search Builder

Right at the beginning of this article I stated that the attached code used the LINQ to
Entities framework, and that we would be writing dynamic queries in the UI that
were then sent to the WCF service and would be used to query the LINQ to Entities
framework.

This is done in the UI using 2 user controls.

SearchClauseControl

This is a simple control that takes a Type and then uses Reflection to build up
various properties / allowable values that the user can pick based on the currently
selected Types property type. Most of the logic associated with this control is done
via the SearchClauseViewModel. The SearchClauseControl is also called by
the parent SearchControl in order for the current search clause query to be added
to any other search clause query.

The property that provides the actual query string for a SearchClauseControl
single is as follows:

Collapse Copy Code


public String ClauseResult
{
get
{

StringBuilder sb = new StringBuilder(1000);

if (!IsFirst)
sb.Append(String.Format("{0} ", currentOperator));

if (IsCollectionProperty)
sb.Append(String.Format("{0}.Count ", currentProperty.Name));
else
{
if (IsString)
sb.Append(String.Format("{0}.", currentProperty.Name));
else
sb.Append(String.Format("{0} ", currentProperty.Name));
}

if (IsOperatorComparable)
{
sb.Append(String.Format("{0} ", currentCondition));
sb.Append(String.Format("@{0} ", ParameterNumber));
}

if (IsString)
{
sb.Append(String.Format("{0}(@{1})",
currentCondition,
ParameterNumber));
}

return sb.ToString();
}
}

SearchControl

Is basically a container that hosts a a number of SearchClauseControl controls.


The only thing that the SearchControl does is to build up a dynamic query string
based on the current configuration of all its contained SearchClauseControl
controls. When a dyanimic query string is created it is sent (via the
SearchRequestedEvent routed event) to the main window who in turn creates a
CustomerSearchRequest query and runs the query.
What actually happens when the SearchControl.SearchRequested routed event
is seen in the main window (CustomOrdersWindow) is that the
SearchControl.SearchRequested event is subscribed to and then the main
windows view model (CustomerOrdersViewModel)
SearchCustomerWithOrders() method is called.

This method is shown below.

Collapse Copy Code


public void SearchCustomerWithOrders(String whereClause, List<Object>
searchParameters)
{
try
{
Service<IPortal>.Use((client) =>
{
using (TransactionScope scope = new TransactionScope())
{
CustomerSearchRequest request = new CustomerSearchRequest();
request.WhereClause = whereClause;
request.SearchParameters = searchParameters;

CustomerResponse response =
(CustomerResponse)client.ExecuteRequest(request);
if (response.Customers != null)
CurrentCustomers =
new ObservableCollection<Customers>(response.Customers);

if (CurrentCustomers.Count > 0)
SelectedCustomer = CurrentCustomers[0];

//complete the Transaction


scope.Complete();
}
});
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}

What is actually happening here is that we are using the static method of the
Service<T> class, which is very cool class indeed. Lets see it.

Collapse Copy Code


using System.ServiceModel;
using System;

namespace WpfClient.ServiceProxy
{
/// Service client delegate
public delegate void UseServiceDelegate<T>(T proxy);

/// <summary>
/// A helper class to run code using a WCF client proxy
///
/// This weird class came from
/// http://www.iserviceoriented.com/blog/post/Indisposable+-
+WCF+Gotcha+1.aspx
/// </summary>
public static class Service<T>
{

public static ChannelFactory<T> _channelFactory =


new ChannelFactory<T>("PortalServiceTcp");

/// <summary>
/// Creates the WCF service proxy and runs the codeBlock delegate
/// using the WCF service proxy that is created
/// </summary>
/// <param name="codeBlock">The code to run using the WCF Proxy</param>
public static void Use(UseServiceDelegate<T> codeBlock)
{
IClientChannel proxy =
(IClientChannel)_channelFactory.CreateChannel();
bool success = false;
try
{
codeBlock((T)proxy);
proxy.Close();
success = true;
}
catch (FaultException<ApplicationException> dex)
{
Console.WriteLine("Client
FaultException<ApplicationException>");
}
catch (FaultException<ArgumentException> aex)
{
Console.WriteLine("Client FaultException<ArgumentException>");
}
catch (FaultException<Exception> ex)
{
Console.WriteLine("Client FaultException<Exception>");
}
catch (FaultException fEx)
{
Console.WriteLine("Client FaultException");
}
finally
{
if (!success)
{
proxy.Abort();
}
}
}
}
}

It can be seen that the method has the following signature


Service<T>.Use(UseServiceDelegate<T> codeBlock), so what essentaily
happens is that a new WCF proxy is created, and then the delegate that was passed
into the Service<T>.Use method is called where the newly created WCF proxy
class is passed as a parameter to the orginal delegate (lambda from the (client)
=> { ...} within the
CustomerOrdersViewModel.SearchCustomerWithOrders code previously
shown.

Pretty tidy, huh. This is how all the calls to the WCF service are done inside the
attached WPFClient code.

So now that we have an actual WCF proxy the lamda within the
CustomerOrdersViewModel.SearchCustomerWithOrders() is run, which
creates a new CustomerSearchRequest, which is then sent to the WCF service.
Lets examine the CustomerSearchRequest and see how that works.

Collapse Copy Code


using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Linq.Expressions;
using System.Linq;

//Linq2Entities
using LINQ2Entities;
using System.Data.Objects;
using System.Linq.Dynamic;

namespace Service.Portal
{
[DataContract]
public class CustomerSearchRequest : Request
{
[DataMember]
public List<Object> SearchParameters { get; set; }
[DataMember]
public String WhereClause { get; set; }

public override Response CreateResponse(Object requestResults)


{
CustomerResponse response = new CustomerResponse();
response.Customers = requestResults as List<Customers>;
return response;
}

public override Object Execute()


{
NorthwindEntities context = new NorthwindEntities();

List<Customers> custs =
context.Customers.Include("Orders")
.Where(this.WhereClause,
this.SearchParameters.ToArray()).ToList();

return custs;
}
#endregion
}
}

Thanks to the lovely extension methods provided by the DynamicQuery API


discussed in the LINQ to Entities section, it becomes almost trivial to conduct a
dynamic query, we simple include a Where clause and use the query string that was
created in the WPF client along with the associated parameter values also passed
into the WCF call from the WPF client.

That's It

That is about all I wanted to say, but if you liked this article please leave a vote and
a comment, thanks.

WCF / WPF Chat Application

Contents
 Introduction
 A Note About the Demo Application
 Prerequisites
 A Brief Overview of the Demo Application and What We are Trying to Achieve
 Some Key Concepts Explained
o WCF: the New Service-orientated Attributes
o WCF: the Use of Interfaces
o WCF: the Use of Callbacks
o WCF: Asynchronous Delegates
o WCF: Creating the Proxy
o WCF: Configuration
o WPF: Styles/Templates
o WPF: Animations
o WPF: Databinding
o WPF: Multithreading a WPF Application
 How This All Works in the DEMO Application
 That's It
 Conclusion
 History
 Other Stuff

Introduction

For those that have read some of my other CodeProject.com articles, you will
probably know that I am not shy about trying out new technologies. One good thing
about that is that I generally share what I learn right here and this article is one of
the hardest ones I've done, IMHO. This article is about how to create a peer-to-peer
chat application using Windows Communication Foundation (WCF) and also how to
make it look nice using Windows Presentation Foundation (WPF).

When I first started reading about WCF, the first place I looked was the MSDN WCF
Samples (which I read a lot), but they weren't that great. I also found lots of chat
apps based on the MSDN versions, which were no good, as they could not return the
list of users within the chat application. I wanted to create a nice WPF styled app
with the list of connected chatters.

So I hunted around a bit more and eventually came across a damn fine/brilliant
article by Nikola Paljetak, which I have tailored for this article. I have OK'd this with
Nikola and the original article content is here. To be honest, the original article was
pure brilliance (it should be mentioned that Nikola is a Professor), but it took a while
for me to get what was going on, as the code wasn't commented. I have now
commented all code, so I think it will still make a very nice discussion/article for
those who are new to WCF/WPF. I was totally new to WCF before this article, so if I
can do it, so can all of you.
So that's what this article is all about. At the end of the article, I would hope you
understand at least some of the key WCF areas and possibly be inspired enough to
look at the WPF side of this article, also.

A Note About the Demo App

Before I start bombarding people with the inner mechanisms of the attached
WPF/WCF application, shall we have a quick look at the finished product? There are 3
main areas within the attached demo application:

A login screen

A main window, from which the user can choose who to chat with:
And a window where chatters may openly chat:
The application is based on using Visual Studio 2005 with The Visual Studio Designer
for WPF installed, or using Expression BLEND and Visual Studio 2005 combination, or
Wordpad if you prefer to write stuff in that. Obviously, as it's a WPF/WCF application,
you will also need the .NET 3.0 Framework. This application will cover the following
concepts:

 WCF
o The new service orientated attributes
o The use of interfaces
o The use of callbacks
o Asynchronous delegates
o Creating the proxy
 WPF
o Styles
o Templates
o Animations
o Databinding
o Multithreading a WPF application

However, this application is not really that orientated to WPF, as that is covered in
numerous other WPF articles at The Code Project. The WPF stuff is really just a
wrapper around the WCF article, which is the real guts of this article. Although there
is some nice WPF stuff going on, just to make the chat application look nicer than an
ordinary console application. I will, however, discuss interesting bits of the WPF
implementation.

Prerequisites

1. To run the code supplied with this article, you will need to install the May
2006 LINQ CTP, which is available here. There is a new March 2007 CTP
available, but it's about 4GB for the full install (as its not just LINQ but the
entire next generation of Visual Studio codenamed "Orcas") and quite fiddly,
and probably going to change anyway. So, the May 2006 LINQ CTP will be OK
for the purpose of what this article is trying to demonstrate.
2. The .NET 3.0 Framework, which is available for download here.

A Brief Overview of the Demo App and What We are Trying


to Achieve

In the attached demo application, we are trying to carry our the following
functionality:

1. Allow chatters to pick a name for themselves and pick an image (Avatar) that
they would like to be presented by
2. Allow the chatters to join a peer-to-peer chat
3. Allow chatters to see who else is available to chat to
4. Allow chatters to send private message
5. Allow chatters to send global messages
6. Allow chatters to leave the chat environment
7. Make it all look pretty using WPF (not strictly a requirement for a chat app,
but I like WPF, so humour me)

In order to achieve all of this I have developed 3 separate assemblies, which by the
end I hope you will understand.

 ChatService.Dll: the WCF chat server, that allows chat clients to connect and
is the main message router
 Common.Dll: is a simple serializable class which is used by both the
ChatService.Dll and the WPFChatter.Dll files
 WPFChatter.Dll: the pretty WPF wrapper around the client WCF functions

Some Key Concepts Explained

There are a number of key concepts that were mentioned earlier that need to be
explained in order for the full application (which covers a lot of ground) to be
understood. So I'll just explain each of these a little bit at a time, so the the final
application should be a little easier to explain (well that's the idea anyway).

WCF: the New Service Orientated Attributes

There are a number of new attributes that may be used with WCF to adorn our NET
classes/interfaces, shown below are the ones that are used as part of the attached
demo application.

ServiceContractAttribute

Indicates that an interface or a class defines a service contract in a Windows


Communication Foundation (WCF) application. It has the following members:

Name Description
Gets or sets the type of callback contract
CallbackContract
when the contract is a duplex contract.
Gets or sets the name used to locate the
ConfigurationName
service in an application configuration file.
Gets a value that indicates whether the
HasProtectionLevel
member has a protection level assigned.
Gets or sets the name for the <portType>
Name element in Web Services Description
Language (WSDL).
Gets or sets the namespace of the
Namespace <portType> element in Web Services
Description Language (WSDL).
Specifies whether the binding for the
ProtectionLevel contract must support the value of the
ProtectionLevel property.
Gets or sets whether sessions are allowed,
SessionMode
not allowed or required.
TypeId (Inherited from Attribute)

See the MSDN article for more details.

OperationContractAttribute

Indicates that a method defines an operation that is part of a service contract in a


Windows Communication Foundation (WCF) application. It has the following
members:
Name Description
Gets or sets the WS-Addressing action of
Action
the request message.
Indicates that an operation is implemented
asynchronously using a
AsyncPattern Begin<methodName> and
End<methodName> method pair in a
service contract.
Gets a value that indicates whether the
HasProtectionLevel messages for this operation must be
encrypted, signed, or both.
Gets or sets a value that indicates whether
the method implements an operation that
IsInitiating
can initiate a session on the server (if such
a session exists).
Gets or sets a value that indicates whether
IsOneWay
an operation returns a reply message.
Gets or sets a value that indicates whether
the service operation causes the server to
IsTerminating
close the session after the reply message,
if any, is sent.
Name Gets or sets the name of the operation.
Gets or sets a value that specifies whether
ProtectionLevel the messages of an operation must be
encrypted, signed, or both.
Gets or sets the value of the SOAP action
ReplyAction
for the reply message of the operation.
TypeId (Inherited from Attribute)

See the MSDN article for more details

ServiceBehaviorAttribute

Specifies the internal execution behavior of a service contract implementation. It has


the following members:

Name Description
AddressFilterMode Gets or sets the AddressFilterMode that is
used by the dispatcher to route incoming
Name Description
messages to the correct endpoint.
Specifies whether to automatically close a
AutomaticSessionShutdown session when a client closes an output
session.
Gets or sets whether a service supports one
ConcurrencyMode
thread, multiple threads, or reentrant calls.
Gets or sets the value used to locate the
ConfigurationName service element in an application
configuration file.
Gets or sets a value that specifies whether to
IgnoreExtensionDataObject send unknown serialization data onto the
wire.
Gets or sets a value that specifies that
general unhandled execution exceptions are
to be converted into a
System.ServiceModel.FaultException
IncludeExceptionDetailInFaults of type
System.ServiceModel.ExceptionDetail
and sent as a fault message. Set this to true
only during development to troubleshoot a
service.
Gets or sets the value that indicates when
InstanceContextMode
new service objects are created.
Gets or sets the maximum number of items
MaxItemsInObjectGraph
allowed in a serialized object.
Gets or sets the value of the name attribute
Name in the service element in Web Services
Description Language (WSDL).
Gets or sets the value of the target
Namespace namespace for the service in Web Services
Description Language (WSDL).
Gets or sets a value that specifies whether
ReleaseServiceInstanceOnTransactionComplete the service object is released when the
current transaction completes.
Gets or sets a value that specifies whether
TransactionAutoCompleteOnSessionClose pending transactions are completed when the
current session closes without error.
TransactionIsolationLevel Specifies the transaction isolation level for
Name Description
new transactions created inside the service,
and incoming transactions flowed from a
client.
Gets or sets the period within which a
TransactionTimeout
transaction must complete.
TypeId (Inherited from Attribute)
UseSynchronizationContext Gets or sets a value that specifies whether to
use the current synchronization context to
choose the thread of execution.
ValidateMustUnderstand Gets or sets a value that specifies whether
the system or the application enforces SOAP
MustUnderstand header processing.

See the MSDN article or more details. Here is an example of how these new WCF
attributes are used within the demo application, Service project -> ChatService.cs.

Collapse Copy Code


[ServiceContract(SessionMode = SessionMode.Required,
CallbackContract = typeof(IChatCallback))]
interface IChat
{
[OperationContract(IsOneWay = true, IsInitiating = false,
IsTerminating = false)]
void Say(string msg);

[OperationContract(IsOneWay = true, IsInitiating = false,


IsTerminating = false)]
void Whisper(string to, string msg);

[OperationContract(IsOneWay = false, IsInitiating = true,


IsTerminating = false)]
Person[] Join(Person name);

[OperationContract(IsOneWay = true, IsInitiating = false,


IsTerminating = true)]
void Leave();
}
WCF: the Use of Interfaces

"The notion of a contract is the key to building a WCF service. Those of you
that have a background in classic DCOM or COM technologies might be
surprised to know that WCF contracts are expressed using interface-based
programming techniques (everything old is new again!). While not
mandatory, the vast amount your WCF applications will begin by defining a
set of .NET interface types that are used to represent the set of members a
given WCF type will support. Specifically speaking, interfaces that represent
a WCF contract are termed service contracts. The classes (or structures)
that implement them are termed service types."

Pro C# with .NET3.0, Apress. Andrew Troelsen

So there you are -- that's what a nice new book says -- but what does this look like
to us in code? Well the actual ChatService.cs class implements the IChat interface
just mentioned, and so looks like this:

Collapse Copy Code


[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession,
ConcurrencyMode = ConcurrencyMode.Multiple)]
public class ChatService : IChat
{

WCF: the Use of Callbacks

Recall earlier, when I mentioned the ServiceContractAttribute I also


mentioned that one of its properties was a CallBackContract that was defined as,
which allows the WCF service to call the client back. This new WCF method is very
nice. I remember trying to do something like this with remoting and events back to
the client, and it was not fun at all. I much prefer this method. Let's have a look.
Recall that the original service contract interface was declared like this:

Collapse Copy Code


[ServiceContract(SessionMode = SessionMode.Required,
CallbackContract = typeof(IChatCallback))]
interface IChat
{
....
}

Well we still need to define an interface to allow the callback to work, so an example
of this may be (as done in the demo app):
Collapse Copy Code
interface IChatCallback
{
[OperationContract(IsOneWay = true)]
void Receive(Person sender, string message);

[OperationContract(IsOneWay = true)]
void ReceiveWhisper(Person sender, string message);

[OperationContract(IsOneWay = true)]
void UserEnter(Person person);

[OperationContract(IsOneWay = true)]
void UserLeave(Person person);
}

WCF: Asynchronous Delegates

"The .NET Framework allows you to call any method asynchronously. To do


this you define a delegate with the same signature as the method you want
to call; the common language runtime automatically defines BeginInvoke
and EndInvoke methods for this delegate, with the appropriate signatures.

The BeginInvoke method initiates the asynchronous call. It has the same
parameters as the method you want to execute asynchronously, plus two
additional optional parameters. The first parameter is an AsyncCallback
delegate that references a method to be called when the asynchronous call
completes. The second parameter is a user-defined object that passes
information into the callback method. BeginInvoke returns immediately and
does not wait for the asynchronous call to complete. BeginInvoke returns an
IAsyncResult, which can be used to monitor the progress of the
asynchronous call.

The EndInvoke method retrieves the results of the asynchronous call. It can
be called any time after BeginInvoke; if the asynchronous call has not
completed, EndInvoke blocks the calling thread until it completes. "

Calling Synchronous Methods Asynchronously

WCF: Creating the Proxy

In order to for the client to communicate with a WCF service, we need a proxy
object. This can be quite a daunting task (and a little complicated to be honest).
Luckily like a lot of things in .NET 3.0/3.5 there are tools provided to make our lives
easier (you still have to know about them though), and WCF is no different. It has a
little tool called "svcutil" which comes to the rescue.

So how do we create a proxy for our little WCF service (ChatService.exe for the
demo app) using svcutil. Well I have read one thing that said you should be able to
just start the WCF service, point svcutil at the running WCF service, and be able to
create the client proxy that way. But I have to say, I could NOT get that to work at
all. It seems to a common gripe, if you search the internet. So the way I got it to
work was as follows:

1. Open a visual studio command prompt, and change to the directory that
contains the WCF service
2. Run the following command line: svcutil <YOUR_SERVICE.exe>
3. This will list a few files, namely *.wsdl, and *.xsd, and a
schemas.microsoft.com.2003.10.Serialization.xsd file
4. Next you need to run the following command line: svcutil *.wsdl
*.xsd /language:C# /out:MyProxy.cs /config:app.config
5. You now have 2 new client files, MyProxy.cs and app.config, so you can copy
these to your client application

To give you an idea of what svcutil.exe produces in terms of client files, let's have a
look. Here is the MyProxy.cs C# file that was auto-generated by svcutil.exe.

Collapse Copy Code


//---------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.312
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//---------------------------------------------------------------------------
namespace Common
{
using System.Runtime.Serialization;

[System.CodeDom.Compiler.GeneratedCodeAttribute(
"System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute()]
public partial class Person : object,
System.Runtime.Serialization.IExtensibleDataObject
{
private System.Runtime.Serialization.ExtensionDataObject
extensionDataField;

private string ImageURLField;

private string NameField;

public System.Runtime.Serialization.ExtensionDataObject ExtensionData


{
get
{
return this.extensionDataField;
}
set
{
this.extensionDataField = value;
}
}

[System.Runtime.Serialization.DataMemberAttribute()]
public string ImageURL
{
get
{
return this.ImageURLField;
}
set
{
this.ImageURLField = value;
}
}

[System.Runtime.Serialization.DataMemberAttribute()]
public string Name
{
get
{
return this.NameField;
}
set
{
this.NameField = value;
}
}
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel",
"3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="IChat",
CallbackContract=typeof(IChatCallback),
SessionMode=System.ServiceModel.SessionMode.Required)]
public interface IChat
{

[System.ServiceModel.OperationContractAttribute(IsOneWay=true,
IsInitiating=false, Action="http://tempuri.org/IChat/Say")]
void Say(string msg);

[System.ServiceModel.OperationContractAttribute(IsOneWay=true,
IsInitiating=false, Action="http://tempuri.org/IChat/Whisper")]
void Whisper(string to, string msg);

[System.ServiceModel.OperationContractAttribute(
Action=http://tempuri.org/IChat/Join,
ReplyAction="http://tempuri.org/IChat/JoinResponse")]
Common.Person[] Join(Common.Person name);

[System.ServiceModel.OperationContractAttribute(IsOneWay=true,
IsTerminating=true, IsInitiating=false,
Action="http://tempuri.org/IChat/Leave")]
void Leave();
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel",
"3.0.0.0")]
public interface IChatCallback
{

[System.ServiceModel.OperationContractAttribute(IsOneWay=true,
Action="http://tempuri.org/IChat/Receive")]
void Receive(Common.Person sender, string message);

[System.ServiceModel.OperationContractAttribute(IsOneWay=true,
Action="http://tempuri.org/IChat/ReceiveWhisper")]
void ReceiveWhisper(Common.Person sender, string message);

[System.ServiceModel.OperationContractAttribute(IsOneWay=true,
Action="http://tempuri.org/IChat/UserEnter")]
void UserEnter(Common.Person person);
[System.ServiceModel.OperationContractAttribute(IsOneWay=true,
Action="http://tempuri.org/IChat/UserLeave")]
void UserLeave(Common.Person person);
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel",
"3.0.0.0")]
public interface IChatChannel : IChat, System.ServiceModel.IClientChannel
{
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel",
"3.0.0.0")]
public partial class ChatClient :
System.ServiceModel.DuplexClientBase<IChat>,
IChat
{

public ChatClient(System.ServiceModel.InstanceContext callbackInstance) :


base(callbackInstance)
{
}

public ChatClient(System.ServiceModel.InstanceContext callbackInstance,


string endpointConfigurationName) :
base(callbackInstance, endpointConfigurationName)
{
}

public ChatClient(System.ServiceModel.InstanceContext callbackInstance,


string endpointConfigurationName, string remoteAddress) :
base(callbackInstance, endpointConfigurationName, remoteAddress)
{
}

public ChatClient(System.ServiceModel.InstanceContext callbackInstance,


string endpointConfigurationName,
System.ServiceModel.EndpointAddress remoteAddress) :
base(callbackInstance, endpointConfigurationName, remoteAddress)
{
}

public ChatClient(System.ServiceModel.InstanceContext callbackInstance,


System.ServiceModel.Channels.Binding binding,
System.ServiceModel.EndpointAddress remoteAddress) :
base(callbackInstance, binding, remoteAddress)
{
}

public void Say(string msg)


{
base.Channel.Say(msg);
}

public void Whisper(string to, string msg)


{
base.Channel.Whisper(to, msg);
}

public Common.Person[] Join(Common.Person name)


{
return base.Channel.Join(name);
}

public void Leave()


{
base.Channel.Leave();
}
}

And here is the client App.Config that was auto-generated by svcutil.exe.

Collapse Copy Code


<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="DefaultBinding_IChat" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00"
sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false"
hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288"
maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8"
transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32"
maxStringContentLength="8192"
maxArrayLength="16384"
maxBytesPerRead="4096"
maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None"
proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName"
algorithmSuite="Default" />
</security>
</binding>

</basicHttpBinding>
</bindings>
<client>
<endpoint binding="basicHttpBinding"
bindingConfiguration="DefaultBinding_IChat"
contract="IChat" name="DefaultBinding_IChat_IChat" />
</client>
</system.serviceModel>

</configuration>

So as you can see, these files can simply be used straightaway within your own
client application to communicate with the WCF service. But wait, we are still not
finished with svcutil.exe. Recall that I mentioned asynchronous delegates -- so why
did I do that? Well the svcutil.exe also allows us to create asynchronous proxy code,
using one of the command line switches. To do this, we use the following command
line (notice the /a option):

svcutil *.wsdl *.xsd /a /language:C# /out:MyProxy.cs


/config:app.config

...instead of:

svcutil *.wsdl *.xsd /language:C# /out:MyProxy.cs


/config:app.config

...which we used previously. This will then change the format of the C# (or VB .NET)
file we get out. What we get now for each WCF service method is an asynchronous
one. So, we would get the following:

Collapse Copy Code


[System.ServiceModel.OperationContractAttribute(IsOneWay=true,
IsInitiating=false, Action="http://tempuri.org/IChat/Say")]
void Say(string msg);

[System.ServiceModel.OperationContractAttribute(IsOneWay=true,
IsInitiating=false, AsyncPattern=true,
Action="http://tempuri.org/IChat/Say")]
System.IAsyncResult BeginSay(string msg, System.AsyncCallback callback,
object asyncState);

void EndSay(System.IAsyncResult result);

...instead of:

Collapse Copy Code


[System.ServiceModel.OperationContractAttribute(IsOneWay=true,
IsInitiating=false, Action="http://tempuri.org/IChat/Say")]
void Say(string msg);

Hopefully you can see where this ties in with the WCF: Asynchronous Delegates
section mentioned earlier. But just to be sure, here's a more detailed description of
what's going on. Using the /a switch of svcutil.exe, you can generate a proxy that
contains asynchronous methods in addition to the synchronous ones. For each
operation in the original contract, the asynchronous proxy and contract will contain
two additional methods of this form:

The OperationContractAttribute offers the AsyncPattern Boolean property.


AsyncPattern only has meaning on the client-side copy of the contract. You can
only set AsyncPattern to true on a method with a Begin<Operation>( )-
compatible signature. The defining contract must also have a matching method with
an End<Operation>( )-compatible signature. These requirements are verified at
proxy load time. What AsyncPattern does is bind the underlying synchronous
method with the Begin/End pair, and correlates the synchronous execution with the
asynchronous one.

When the client invokes a method of the form Begin<Operation>( ) with


AsyncPattern set to true, it tells WCF not to try to directly invoke a method by
that name on the service. Instead, it will use a thread from the thread pool to
synchronously call the underlying method (identified by the Action name). The
synchronous call will block the thread from the thread pool, not the calling client. The
client will only be blocked for the slightest moment it takes to dispatch the call
request to the thread pool. The reply method of the synchronous invocation is
correlated with the End<Operation>( ) method.

As the attached demo application makes use of asynchronous methods for the Join
operation, asynchronous delegates are using within the code to achieve this.
WCF: Configuration

As with all .NET applications, WCF applications allow the application to be configured
via a configuration file. This will be discussed later on, for now you just need to know
that the following items may be configured in an App.Config file for a WCF
application:

 Service addresses
 Service type
 Behavior configuration
 Endpoints
 Binding types
 Service security

WPF: Styles / Templates

WPF styles and templates allow us to change how standard components look. This is
quite a well documented feature, but what I will say is that by using a little bit of
styling one is able to convert a rather plain ListView into a ListView that looks
like the figure shown below. Quite nice, I think. So how is this done? Well, it's all
down to styling. The figure below shows a standard ListView item which is styled
and has some custom data templates assigned. Each item in the ListView is
actually a Common.Person object, which will be discussed later.

All that has been done is that I have applied a style to a standard .NET ListView
control. Here is the XAML that does this. However, I say I am not going to dwell on
these WPF features, as they are well documented and not really part of the main
thrust of this article. I just wanted those people reading this that hadn't come across
WPF before, to know what can be done with it.

Collapse Copy Code


<Style x:Key="ListViewContainer" TargetType="{x:Type ListViewItem}">
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="Foreground" Value="#FF000000"/>

<Setter Property="FontFamily" Value="Agency FB"/>


<Setter Property="FontSize" Value="15"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Foreground" Value="Black" />
<Setter Property="Background">

<Setter.Value>

<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">


<LinearGradientBrush.GradientStops>
<GradientStop Color="#D88" Offset="0"/>
<GradientStop Color="#D31" Offset="1"/>
</LinearGradientBrush.GradientStops>

</LinearGradientBrush>

</Setter.Value>
</Setter>
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
<MultiTrigger>

<MultiTrigger.Conditions>

<Condition Property="IsSelected" Value="true" />


<Condition Property="Selector.IsSelectionActive" Value="true" />
</MultiTrigger.Conditions>
<Setter Property="Background">
<Setter.Value>

<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">

<LinearGradientBrush.GradientStops>
<GradientStop Color="#0E4791" Offset="0"/>
<GradientStop Color="#468DE2" Offset="1"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>

</Setter.Value>

</Setter>
<Setter Property="Foreground" Value="Black" />
</MultiTrigger>
</Style.Triggers>
</Style>

<!-- Gridview Templates -->

<DataTemplate x:Key="noTextHeaderTemplate"/>

<DataTemplate x:Key="textCellTemplate">
<TextBlock Margin="10,0,0,0" Text="{Binding}"
VerticalAlignment="Center"/>
</DataTemplate>

<DataTemplate x:Key="imageCellTemplate">

<Border CornerRadius="2,2,2,2" Width="40" Height="40"


Background="#FFFFC934" BorderBrush="#FF000000" Margin="3,3,3,3">
<Image HorizontalAlignment="Center" VerticalAlignment="Center"
Width="Auto" Height="Auto"
Source="{Binding Path=ImageURL}" Stretch="Fill"
Margin="2,2,2,2"/>
</Border>
</DataTemplate>

.....
.....

<ListView DockPanel.Dock="Bottom" Margin="0,-10,0,0"


VerticalAlignment="Bottom"
x:Name="lstChatters" SelectionMode="Single"
ItemContainerStyle="{StaticResource ListViewContainer}"
Background="{x:Null}" BorderBrush="#FFFFFBFB" Foreground="#FFB5B5B5"
Opacity="1" BorderThickness="2,2,2,2"
HorizontalAlignment="Stretch" Width="Auto" Height="Auto">

<ListView.View>
<GridView>
<GridView.ColumnHeaderContainerStyle>
<Style TargetType="GridViewColumnHeader">
<Setter Property="Visibility" Value="Hidden" />
<Setter Property="Height" Value="0" />

</Style>
</GridView.ColumnHeaderContainerStyle>
<GridViewColumn Header="Image"
HeaderTemplate="{StaticResource noTextHeaderTemplate}"
Width="100" CellTemplate="{StaticResource imageCellTemplate}"/>
<GridViewColumn DisplayMemberBinding="{Binding Path=Name}"
Header="First Name"
HeaderTemplate="{StaticResource textCellTemplate}" Width="100"/>
</GridView>
</ListView.View>

</ListView>

WPF: Animations

Animations are another element of WPF (again well documented, so I'll not go into it
too much). I have not gone too overboard with animations in the demo application,
but I do use animation twice (because one simply has to if they are developing WPF
stuff).

Once to load the ChatControl and once to hide the ChatControl. The only thing
that is special is the way that I am using animation. They are part of the
Window1.xaml but the triggers are performed in code behind logic. As this may be
useful to some people I'll give a small example.

In Window1.xaml I have declared an animation as follows, the one shown below


loads the ChatControl by growing it from 0 X/Y scale to 100% X/Y scale over a
period of 1 second, and is triggered when a user clicks a ListView item.

Collapse Copy Code


<!-- Show Chat Window Animation -->
<Storyboard x:Key="showChatWindow">

<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="ChatControl"
Storyboard.TargetProperty="(UIElement.RenderTransform).(
TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:001" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="ChatControl"
Storyboard.TargetProperty="(UIElement.RenderTransform).(
TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>

<SplineDoubleKeyFrame KeyTime="00:00:001" Value="1"/>


</DoubleAnimationUsingKeyFrames>
</Storyboard>
I trigger this animation directly from code-behind. So how do I do that? Well, let's
have a look at the code, shall we? It's fairly easy; the code to do that is as follows:

Collapse Copy Code


//get Storyboard animation from window resources
((Storyboard)this.Resources["showChatWindow"]).Begin(this);

WPF: Databinding

The styled ListView that I am using within Window1.xaml utilizes data binding in
order to bind a List of Person objects. This is done by using Templates as already
shown in the WPF : Styles/Templates section. But just in case you're not so sure
about all this WPF stuff, what actually happens is that I use a DataTemplate which
specifies just how the ListView will display its data. To do that, I define the
following DataTemplates and these DataTemplates include the Binding values.
This allows a collection of Person objects to be bound to the ListView.

Collapse Copy Code


<DataTemplate x:Key="textCellTemplate">

<TextBlock Margin="10,0,0,0" Text="{Binding}" VerticalAlignment="Center"/>


</DataTemplate>

<DataTemplate x:Key="imageCellTemplate">
<Border CornerRadius="2,2,2,2" Width="40" Height="40"
Background="#FFFFC934" BorderBrush="#FF000000" Margin="3,3,3,3">

<Image HorizontalAlignment="Center" VerticalAlignment="Center"


Width="Auto"
Height="Auto" Source="{Binding Path=ImageURL}" Stretch="Fill"
Margin="2,2,2,2"/>

</Border>
</DataTemplate>

WPF: Multithreading a WPF Application

Threading in WPF is quite similar to .NET 2.0/Win forms, you still have the issue of
threads that are not on the same owner thread as a UI component needing to be
marshaled to the correct thread. The only difference is the keywords. For example, in
.NET 2.0, one would probably have done:

Collapse Copy Code


if (this.InvokeRequired)
{
this.Invoke(new EventHandler(delegate
{
progressBar1.Value = e.ProgressValue;
}));
}
else
{
progressBar1.Value = e.ProgressValue;
}

...while in WPF we would (and I do) use the following syntax. Note :
CheckAccess() is marked as <BROWSABLE(false)> so don't be expecting to see it
using Intellisense. However, it does work.

Collapse Copy Code


/// <summary>

/// A delegate to allow a cross UI thread call to be marshaled


/// to correct UI thread
/// </summary>
private delegate void ProxySingleton_ProxyEvent_Delegate(
object sender, ProxyEventArgs e);

/// <summary>
/// This method checks to see if the current thread needs to be
/// marshalled to the correct (UI owner) thread. If it does a new
/// delegate is created
/// which recalls this method on the correct thread
/// </summary>
/// <param name="sender"><see
/// cref="Proxy_Singleton">ProxySingleton</see></param>

/// <param name="e">The event args</param>


private void ProxySingleton_ProxyEvent(object sender,
ProxyEventArgs e)
{
if (!this.Dispatcher.CheckAccess())
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
new ProxySingleton_ProxyEvent_Delegate(
ProxySingleton_ProxyEvent),
sender, new object[] { e });
return;
}
//now marshalled to correct thread so proceed
foreach (Person person in e.list)
{
lstChatters.Items.Add(person);
}
this.ChatControl.AppendText("Connected at " +
DateTime.Now.ToString() + " with user name " +
currPerson.Name + Environment.NewLine);
}

Well, you know what, if you've got to this point without falling asleep, I think you're
ready to deal with the inner workings of the attached demo application(s). It should
be child's play now, as we've covered all the key elements. There's nothing new to
say, apart from how the demo app uses all this stuff (though, some of it we've
already discussed). So it should be just a question of explaining it all now.

How This All Works in the DEMO Application

Well how about we start with a sequence diagram (I know UML isn't that great for
distributed apps, so I've annotated it with comments, but I hope you get the general
idea).
I apologize that the text on this diagram is so small, but that's down to the
restrictions on image sizes here at The Code Project. I'll even give you some class
diagrams, for those that prefer them. Remember that there are 3 separate
assemblies (ChatService / Common / WPFChatter), which I talked about earlier:

ChatService

In order for this service to work correctly, there is a special configuration file. It
could also have been done in code, but App.Config is just more flexible. So, let's
have a look at the ChatService.exe App.Config, shall we? Well, it looks like this:

Collapse Copy Code


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>

<add key="addr" value="net.tcp://localhost:22222/chatservice" />


</appSettings>
<system.serviceModel>

<services>
<service name="Chatters.ChatService" behaviorConfiguration="MyBehavior">
<endpoint address=""
binding="netTcpBinding"
bindingConfiguration="DuplexBinding"
contract="Chatters.IChat" />

</service>
</services>

<behaviors>

<serviceBehaviors>
<behavior name="MyBehavior">

<serviceThrottling maxConcurrentSessions="10000" />


</behavior>
</serviceBehaviors>
</behaviors>

<bindings>
<netTcpBinding>

<binding name="DuplexBinding" sendTimeout="00:00:01">


<reliableSession enabled="true" />
<security mode="None" />
</binding>

</netTcpBinding>
</bindings>

</system.serviceModel>
</configuration>

As you can see, this App.Config file contains all the information required to enable
the service to operate. WCF supports a lot of different binding options, such as:

Binding type Description


BasicHttpBinding A binding that is suitable for
communicating with WS-Basic Profile
conformant Web Services, for
example, ASMX-based services. This
Binding type Description
binding uses HTTP as the transport
and Text/XML as the default
message encoding.
A secure and interoperable binding
WSHttpBinding that is suitable for non-duplex
service contracts.
A secure and interoperable binding
that is suitable for duplex service
WSDualHttpBinding
contracts or communication through
SOAP intermediaries.
A secure and interoperable binding
that supports the WS-Federation
WSFederationHttpBinding protocol, enabling organizations that
are in a federation to efficiently
authenticate and authorize users.
A secure and optimized binding
suitable for cross-machine
NetTcpBinding
communication between WCF
applications.

A secure, reliable, optimized binding


NetNamedPipeBinding that is suitable for on-machine
communication between WCF
applications.
A queued binding that is suitable for
NetMsmqBinding cross-machine communication
between WCF applications.

NetPeerTcpBinding A binding that enables secure, multi-


machine communication.
A binding that is suitable for cross-
machine communication between a
MsmqIntegrationBinding
WCF application and existing MSMQ
applications.

For the demo application, I am using NetTcpBinding. For more information on


bindings in WCF applications, you can see this link.
Common

This is a very simple class that is used by the ChatService and WPFChatter
assemblies. This class represents a single chatter and may be sent over the WCF
channel due the special WCF annotations that have been applied to this class. The
entire class is listed below, as it's not so big:

Collapse Copy Code


using System
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;
using System.ComponentModel;

namespace Common
{
#region Person class
/// <summary>
/// This class represnts a single chat user that can participate in
/// this chat application
/// This class implements INotifyPropertyChanged to support one-way
/// and two-way WPF bindings (such that the UI element updates when
/// the source has been changed dynamically)
/// [DataContract] specifies that the type defines or implements a
/// data contract and is serializable by a serializer, such as
/// the DataContractSerializer
/// </summary>
[DataContract]
public class Person : INotifyPropertyChanged
{
#region Instance Fields
private string imageURL;
private string name;
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region Ctors
/// <summary>
/// Blank constructor
/// </summary>

public Person()
{
}

/// <summary>

/// Assign constructor


/// </summary>
/// <param name="imageURL">Image url to allow a picture to be
/// created for this chatter</param>
/// <param name="name">The name to use for this chatter</param>

public Person(string imageURL, string name)


{
this.imageURL = imageURL;
this.name = name;
}
#endregion
#region Public Properties
/// <summary>

/// The chatters image url


/// </summary>
[DataMember]
public string ImageURL
{
get { return imageURL; }
set
{
imageURL = value;
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged("ImageURL");
}
}
/// <summary>
/// The chatters Name
/// </summary>

[DataMember]
public string Name
{
get { return name; }
set
{
name = value;
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged("Name");
}
}
#endregion
#region OnPropertyChanged (for correct well behaved databinding)
/// <summary>
/// Notifies the parent bindings (if any) that a property
/// value changed and that the binding needs updating
/// </summary>

/// <param name="propValue">The property which changed</param>


protected void OnPropertyChanged(string propValue)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propValue));
}
}
#endregion
}
#endregion
}

As you can see, this class has some special attributes which still haven't been talked
about. It also inherits from a strange interface. So what's that all about, then? Well,
[DataContract] specifies that the type defines or implements a data contract and
is serializable by a serializer such as DataContractSerializer. The
INotifyPropertyChanged interface is a special WPF interface that allows the class
to notify and binding container of a change in a value. Thus, when a property is
changed, the binding container will be informed. This applies to the Window1.xaml
ListView in my case, as described in the WPF: Databinding section.
WPFChatter
The app.config file and WCF proxy were created using the WCF scvutil.exe tool, as
mentioned in the WCF: Creating the Proxy section. The finished WPF application is as
shown below:
What I'm going to do now is explain a bit about how all the WCF/WPF stuff works in
conjunction with each other, using the attached demo app. I think the best place to
start would be to describe the actual ChatService (the server end) and why it's
adorned the way it is. I will not go into all the inner workings of the ChatService.cs
file just yet, as this will be visited later.

ChatService.cs
Collapse Copy Code
[ServiceContract(SessionMode = SessionMode.Required,
CallbackContract = typeof(IChatCallback))]
interface IChat
{
[OperationContract(IsOneWay = true, IsInitiating = false,
IsTerminating = false)]
void Say(string msg);

[OperationContract(IsOneWay = true, IsInitiating = false,


IsTerminating = false)]
void Whisper(string to, string msg);

[OperationContract(IsOneWay = false, IsInitiating = true,


IsTerminating = false)]
Person[] Join(Person name);

[OperationContract(IsOneWay = true, IsInitiating = false,


IsTerminating = true)]
void Leave();
}

interface IChatCallback
{
[OperationContract(IsOneWay = true)]
void Receive(Person sender, string message);

[OperationContract(IsOneWay = true)]
void ReceiveWhisper(Person sender, string message);

[OperationContract(IsOneWay = true)]
void UserEnter(Person person);

[OperationContract(IsOneWay = true)]
void UserLeave(Person person);
}
public class ChatEventArgs : EventArgs
{
public MessageType msgType;
public Person person;
public string message;
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession,
ConcurrencyMode = ConcurrencyMode.Multiple)]
public class ChatService : IChat
{
...
}

There are several things to note here:

1. There is an IChat interface which is implemented by the ChatService


(server end) class. This is in order that the ChatService implements a
common Chat interface that is known at compile time. Each of the interface
methods are adorned with new WCF [OperationContract] attributes. I
discussed all the possible values for this attribute earlier in this article. The
general rule of thumb here is that if the method needs to return a value of
IsOneWay = true. Otherwise, it will be IsOneWay = false. All these
methods are also marked with the IsInitiating and IsTerminating
properties. As the Join method is initialising the service, this is marked with
IsInitiating = true and as the Leave method is quitting the service,
this is marked with IsTerminating = true.
2. There is also another IChatCallBack interface included within the
ChatService class. This is to allow the ChatService to make callbacks to
the clients using a well-known interface that is also known at compile time. It
can be seen that the server-implemented IChat interface actually includes
extra annotation to state whether there is a callback required. Let's have a
look at [ServiceContract(SessionMode = SessionMode.Required,
CallbackContract = typeof(IChatCallback))]. Notice how the
CallbackContract is specified as being of type IChatCallback. That's
how the WCF service knows how to communicate back to the client.
Obviously, just having the CallbackContract property and not the actual
IChatCallback interface is not enough. You need both.
3. Lastly, we need to note that the actual ChatService is also adorned with
extra attributes that allow the service itself to be managed correctly. I am
using InstanceContextMode = InstanceContextMode.PerSession.
PerSession instructs the service application to create a new service object
when a new communication session is established between a client and the
service application. Subsequent calls in the same session are handled by the
same object. I am also using ConcurrencyMode =
ConcurrencyMode.Multiple. A value of Multiple means that service
objects can be executed by multiple threads at any one time. In this case,
you must ensure thread safety.

So that's the ChatService's WCF attributes explained, but what about the client-
side code? Remember that we used svcutil.exe to create a proxy object the way I
previously described. So I am not going to go into that in too much detail. However,
the full proxy code (ChatService.cs, in the WPFChatter project in the demo code) is
shown below. With the descriptions just given, and the previously mentioned
attribute tables, you should be able to see what's going on I hope.

Collapse Copy Code


using Common;

/// <summary>
/// This class was auto generated by the svcutil.exe utility.
/// The www.codeprject.com article will explain how this class
/// was generated, for those readers that just need to know.
/// Basically, anyone like me.
/// </summary>
#region IChat interface
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel",
"3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(CallbackContract = typeof(
IChatCallback), SessionMode = System.ServiceModel.SessionMode.Required)]
public interface IChat
{
[System.ServiceModel.OperationContractAttribute(AsyncPattern = true,
Action = "http://tempuri.org/IChat/Join">http://tempuri.org/IChat/Join,
ReplyAction = "http://tempuri.org/IChat/JoinResponse")]
System.IAsyncResult BeginJoin(Person name, System.AsyncCallback callback,
object asyncState);

Person[] EndJoin(System.IAsyncResult result);

[System.ServiceModel.OperationContractAttribute(IsOneWay = true,
IsInitiating = false, Action = "http://tempuri.org/IChat/Leave")]
void Leave();

[System.ServiceModel.OperationContractAttribute(IsOneWay = true,
IsInitiating = false, Action = "http://tempuri.org/IChat/Say")]
void Say(string msg);

[System.ServiceModel.OperationContractAttribute(IsOneWay = true,
IsInitiating = false, Action = "http://tempuri.org/IChat/Whisper")]
void Whisper(string to, string msg);
}
#endregion
#region IChatCallback interface
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel",
"3.0.0.0")]
public interface IChatCallback
{
[System.ServiceModel.OperationContractAttribute(IsOneWay = true,
Action = "http://tempuri.org/IChat/Receive")]
void Receive(Person sender, string message);

[System.ServiceModel.OperationContractAttribute(IsOneWay = true,
Action = "http://tempuri.org/IChat/ReceiveWhisper")]
void ReceiveWhisper(Person sender, string message);

[System.ServiceModel.OperationContractAttribute(IsOneWay = true,
Action = "http://tempuri.org/IChat/UserEnter")]
void UserEnter(Person person);

[System.ServiceModel.OperationContractAttribute(IsOneWay = true,
Action = "http://tempuri.org/IChat/UserLeave")]
void UserLeave(Person person);
}
#endregion
#region IChatChannel interface
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel",
"3.0.0.0")]
public interface IChatChannel : IChat, System.ServiceModel.IClientChannel
{
}
#endregion
#region ChatProxy class
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel",
"3.0.0.0")]
public partial class ChatProxy : System.ServiceModel.DuplexClientBase<IChat>,
IChat
{
public ChatProxy(System.ServiceModel.InstanceContext callbackInstance)
:
base(callbackInstance)
{
}

public ChatProxy(System.ServiceModel.InstanceContext callbackInstance,


string endpointConfigurationName)
:
base(callbackInstance, endpointConfigurationName)
{
}

public ChatProxy(System.ServiceModel.InstanceContext callbackInstance,


string endpointConfigurationName, string remoteAddress)
:
base(callbackInstance, endpointConfigurationName, remoteAddress)
{
}

public ChatProxy(System.ServiceModel.InstanceContext callbackInstance,


string endpointConfigurationName,
System.ServiceModel.EndpointAddress remoteAddress)
:
base(callbackInstance, endpointConfigurationName, remoteAddress)
{
}

public ChatProxy(System.ServiceModel.InstanceContext callbackInstance,


System.ServiceModel.Channels.Binding binding,
System.ServiceModel.EndpointAddress remoteAddress)
:
base(callbackInstance, binding, remoteAddress)
{
}

public System.IAsyncResult BeginJoin(Person name,


System.AsyncCallback callback, object asyncState)
{
return base.Channel.BeginJoin(name, callback, asyncState);
}

public Person[] EndJoin(System.IAsyncResult result)


{
return base.Channel.EndJoin(result);
}

public void Leave()


{
base.Channel.Leave();
}
public void Say(string msg)
{
base.Channel.Say(msg);
}

public void Whisper(string to, string msg)


{
base.Channel.Whisper(to, msg);
}
}
#endregion

OK, so now that I've described the skeleton, boiler plate code that both the
Server/Client use to carry out their communications, let's dive in to see how the
actual code utilizes the ChatService (server end) and the client side proxy object
also called ChatService. I think the best way to do this is to list out one of the
operations (such as Join) and follow it from start to finish, from client to server.

One thing to note though, before I start going into this stuff fully, is that I needed to
be able to call the client side proxy object methods from several different
windows/controls within the attached WPF project. To this end, there is a class called
Proxy_Singleton.cs that is really just a singleton wrapper object around all the
different operations that need to be carried out for the ChatService to work
correctly. It simply enables the client code to obtain the current singleton object and
call its methods without having to worry about instantiating a new proxy object, or
keeping track of the correct proxy object.

Join

For the Join operation, the following sequence is observed

1. The user enters a name and assigns an image on the SignInControl.xaml


control, where a new Person object is created which is accessible via a public
property. This control then raises the AddButtonClickEvent where the
container Window1.xaml is listening to this event. The container,
Window1.xaml, then hides the SignInControl.xaml control. It grabs the new
Person object that was created by the SignInControl.xaml and calls the
Connect method of the Proxy_Singleton.cs, passing it the new Person
object.
2. Both Window1.xaml and ChatControl.xaml are then wired up to subscribe to
the Proxy_Singleton.cs ProxyEvent event and ProxyCallBackEvent
event, such that when the Proxy_Singleton.cs receives a callback message
from the server (another chatter), it will fire these events and all listening
parties will know what to do with the received data.
3. The Proxy_Singleton.cs Connect method uses an asynchronous
connection to call the Join method on the ChatService (local proxy).
Recall that I told you about asynchronous delegates and how the
asynchronous connections were handled by the svcutil.exe tool.
4. The Proxy_Singleton.cs Connect method eventually calls (through WCF
magic, tcpBninding actually) the Join method of the ChatService
(server). This will return the new List of chatters to all connected chatters.
The server does this by maintaining a multicast delegate that holds a list of
delegates of the type public delegate void
ChatEventHandler(object sender, ChatEventArgs e);. There is 1
each per connected chatter. Basically what happens is that whenever one of
the IChat methods on the server is called, the delegate for the client may
also called (dependant on message type). Obviously, some messages (such
as Whisper) are private. As such, only the particular delegate for the receiver
of the message is invoked. Nevertheless, the mechanism is the same. When a
message is received by the server, the message type is examined. If it's
private, only the particular delegate for the receiver (client) of the message is
invoked. Otherwise, all attached client delegates are invoked. When the
delegate is invoked by the server, it will use the IChatCallback interface to
make the call back to the client. As the Proxy_Singleton.cs Connect
class implements IChatCallback, it is capable of receiving and dealing with
the callback messages. It will generally make the callback messages available
to other objects via internally generated events which, as mentioned earlier,
Window1.xaml and ChatControl.xaml have subscribed to.

This probably needs some code snippets to help explain, so let's start with the
Proxy_Singleton.cs Connect code:

Collapse Copy Code


///<summary>
/// Begins an asynchronous join operation on the
/// underlying <see cref="ChatProxy">ChatProxy</see>

/// which will call the OnEndJoin() method on completion


/// </summary>
/// <param name="p">The <see cref="Common.Person">chatter</see>
/// to try and join with</param>
public void Connect(Person p)
{
InstanceContext site = new InstanceContext(this);
proxy = new ChatProxy(site);
IAsyncResult iar = proxy.BeginJoin(p,
new AsyncCallback(OnEndJoin), null);
}
/// <summary>

/// Is called as a callback from the asynchronous call,


/// so simply get the list of
/// <see cref="Common.Person">Chatters</see> that will
/// be yielded as part of the Asynch Join call
/// </summary>
/// <param name="iar">The asnch result</param>
private void OnEndJoin(IAsyncResult iar)
{
try
{
Person[] list = proxy.EndJoin(iar);
HandleEndJoin(list);
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error",
MessageBoxButton.OK, MessageBoxImage.Error);
}
}
/// <summary>

/// If the input list is not empty, then call the


/// OnProxyEvent() event, to raise the event for subscribers
/// </summary>
/// <param name="list">The list of
/// <see cref="Common.Person">Chatters</see> </param>
private void HandleEndJoin(Person[] list)
{

if (list == null)
{
MessageBox.Show("Error: List is empty", "Error",
MessageBoxButton.OK, MessageBoxImage.Error);
ExitChatSession();
}
else
{
ProxyEventArgs e = new ProxyEventArgs();
e.list = list;
OnProxyEvent(e);
}
}
/// <summary>

/// Raises the event for connected subscribers


/// </summary>
/// <param name="e"><see cref=
/// "ProxyCallBackEventArgs">ProxyCallBackEventArgs</see>
/// event args</param>
protected void OnProxyCallBackEvent(ProxyCallBackEventArgs e)
{
if (ProxyCallBackEvent != null)
{
// Invokes the delegates.
ProxyCallBackEvent(this, e);
}
}
/// <summary>

/// Raises the event for connected subscribers


/// </summary>
/// <param name="e"><see cref=
/// "ProxyEventArgs">ProxyEventArgs</see>
/// event args</param>
protected void OnProxyEvent(ProxyEventArgs e)
{
if (ProxyEvent != null)
{
// Invokes the delegates.
ProxyEvent(this, e);
}
}
.....
/// <summary>

/// New chatter entered chat room, so call the


/// internal UserEnterLeave() method passing it the input parameters
/// and the <see cref="CallBackType">CallBackType.UserEnter</see>
/// type
/// </summary>
/// <param name="sender">The <see cref=
/// "Common.Person">current chatter</see></param>

/// <param name="message">The message</param>


public void UserEnter(Person person)
{
....
}

So this ends up calling the Join method in the ChatService (server), which then
uses IChatCallback to call the client back using the appropriate IChatCallback
method. For example:

 A Join method in the ChatService will result in an IChatCallback


UserEnter method being called.
 A Leave method in the ChatService will result in an IChatCallback
UserLeave method being called.
 A Say method in the ChatService will result in an IChatCallback
Receive method being called.
 A Whisper method in the ChatService will result in an IChatCallback
ReceiveWhisper method being called.

So let's have a look at the Join/UserEnter operation at the server end:

Collapse Copy Code


/// <summary>
/// Takes a <see cref="Common.Person">Person</see> and allows them
/// to join the chat room, if there is not already a chatter with
/// the same name
/// </summary>

/// <param name="person"><see cref=


/// "Common.Person">Person</see> joining</param>
/// <returns>An array of <see cref="Common.Person">Person</see>
/// objects</returns>

public Person[] Join(Person person)


{
bool userAdded = false;
//create a new ChatEventHandler delegate, pointing to the
//MyEventHandler() method
myEventHandler = new ChatEventHandler(MyEventHandler);

//carry out a critical section that checks to see if the new


//chatter name is already in use, if its not allow the new
//chatter to be added to the list of chatters, using the
//person as the key, and the
//ChatEventHandler delegate as the value, for later invocation
lock (syncObj)
{
if (!checkIfPersonExists(person.Name) && person != null)
{
this.person = person;
chatters.Add(person, MyEventHandler);
userAdded = true;
}
}

//if the new chatter could be successfully added, get a


//callback instance create a new message, and broadcast it to
//all other chatters, and then return the list of al chatters
//such that connected clients may show a list of all the chatters
if (userAdded)
{
callback =
OperationContext.Current.GetCallbackChannel<IChatCallback>();
ChatEventArgs e = new ChatEventArgs();
e.msgType = MessageType.UserEnter;
e.person = this.person;
BroadcastMessage(e);
//add this newly joined chatters ChatEventHandler delegate,
//to the global multicast delegate for invocation
ChatEvent += myEventHandler;
Person[] list = new Person[chatters.Count];
//carry out a critical section that copy all chatters to
//a new list
lock (syncObj)
{
chatters.Keys.CopyTo(list, 0);
}
return list;
}
else
{
return null;
}
}
....

/// <summary>
/// This method is called when ever one of the chatters
/// ChatEventHandler delegates is invoked. When this method
/// is called it will examine the events ChatEventArgs to see
/// what type of message is being broadcast, and will then
/// call the correspoding method on the clients callback interface
/// </summary>
/// <param name="sender">the sender, which is not used</param>
/// <param name="e">The ChatEventArgs</param>
private void MyEventHandler(object sender, ChatEventArgs e)
{
try
{
switch (e.msgType)
{
case MessageType.Receive:
callback.Receive(e.person, e.message);
break;
case MessageType.ReceiveWhisper:
callback.ReceiveWhisper(e.person, e.message);
break;
case MessageType.UserEnter:
callback.UserEnter(e.person);
break;
case MessageType.UserLeave:
callback.UserLeave(e.person);
break;
}
}
catch
{
Leave();
}
}
.....

/// <summary>
///loop through all connected chatters and invoke their
///ChatEventHandler delegate asynchronously, which will firstly call
///the MyEventHandler() method and will allow a asynch callback to
///call
///the EndAsync() method on completion of the initial call
/// </summary>
/// <param name="e">The ChatEventArgs to use to send to all
/// connected chatters</param>

private void BroadcastMessage(ChatEventArgs e)


{

ChatEventHandler temp = ChatEvent;

//loop through all connected chatters and invoke their


//ChatEventHandler delegate asynchronously, which will firstly
//call the MyEventHandler() method and will allow a asynch
//callback to call the EndAsync() method on completion of the
//initial call
if (temp != null)
{
foreach (ChatEventHandler handler in temp.GetInvocationList())
{
handler.BeginInvoke(this, e, new AsyncCallback(EndAsync),
null);
}
}
}

Say

The methodology for the Say operation is similar to the Join operation described
above, with the following key differences:

1. The Say operation is NOT called asynchronously


2. A Say method in the ChatService will result in an IChatCallback
Receive method being called
3. The Say operation is NOT private, so ALL client delegates (at the server) will
be invoked

Whisper

The methodology for the Whisper operation is similar to the Join operation, with
the following key differences:

1. The Whisper operation is NOT called asynchronously


2. A Whisper method in the ChatService will result in an IChatCallback
ReceiveWhisper method being called
3. The Whisper operation is private, so only the particular recipients client
delegate (at the server) will be invoked

Leave

The methodology for the Leave operation is similar to the Join operation, with the
following key differences:

1. The Leave operation is NOT called Asynchronously


2. A Leave method in the ChatService will result in an IChatCallback
UserLeave method being called
3. The Leave operation is NOT private, so ALL client delegates (at the server)
will be invoked

That's It

I hope this article shows that all these new Microsoft technologies can actually work
together quite well. I have to say, I think this application looks cool. I have been
messing around with WPF for a while, nothing serious, but with this one, I tried to
have a go. So I hope some of you like it.

So What Do You Think?

I would just like to ask, if you liked the article, please vote for it. Also, leave some
comments, as it lets me know if the article was at the right level or not, and whether
it contained what people need to know.

Conclusion

I have enjoyed writing this WPF/WCF article and I have now become hopelessly
addicted to .NET 3.0/3.5. So if you want to keep a work/life balance, I would suggest
you stay far away from .NET 3.0/3.5 if at all possible, because once it's got you in its
little tentacles, there really is no escape. "Resistance Is Futile. You Will Be
Assimilated."

That said, once you get your head around the vast learning curve that is .NET 3.0,
it's really much better IMHO than previous .NET 2.0 offerings.

Introduction

This article includes WCF Introduction, Sample WCF Service Library, Hosting of WCF
Service at Windows Service and consuming the WCF Service at Web Application.

Background

Basic knowledge of C#, and HTML is required.

WCF Introduction

WCF(Windows Communication Foundation), originally tagged with the code name


"Indigo" is a programming framework used to build applications that inter-
communicate. It is Microsoft’s unified programming model for building service-
oriented applications. It enables developers to build secure, reliable, transacted
solutions that integrate across platforms and interoperate with existing investments.
WCF is the part of the .Net Framework dedicated to communications.

This definition is from wikipedia and Microsoft, For more detail you can refer

http://en.wikipedia.org/wiki/Windows_Communication_Foundation

Creating WCF Service Application with Visual Studio 2008

One of the good article is available at code project site. you can refer this article
WCFOverview.aspx

Creating WCF Service Library with Visual Studio 2008

These are the steps needed to be followed to create a WCF Service Library with
Visual Studio 2008

 Open Visual Studio 2008.


 Click on New Project in the File menu.
 Expand the Visual C# node in the Project types tree, and select the WCF
node.
 Select WCF Service Library.
 Choose the Name and Location where the application is to be saved and click
the OK button.
 The project will be created with the default files, which are IService1.cs,
Service1.cs, and App.config.
We can see the ServiceContract attribute with IService1, and the methods exposed
are defined with the OperationContract attribute. Service1 is the concrete class for
the implementation of IService1. Endpoints and other behavioral properties are
defined in the system.serviceModel section of the App.Config file.

We need to make the necessary changes in the above section of App.Config if we are
renaming the services; otherwise, external systems cannot identify the services.

WCF Service Code

IService1.cs
Collapse Copy Code
//<createdby> Murali Manohar Pareek </createdby>
//<date> Oct 23, 2008 </date>
//<description> WCF Service</description>
//<version> 1.0.0.0 </version>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace WCFServiceSample
{
// NOTE: If you change the interface name "IService1" here,
// you must also update the reference to "IService1" in App.config.
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);

[OperationContract]
CompositeType GetDataUsingDataContract(CompositeType composite);

// TODO: Add your service operations here


}

// Use a data contract as illustrated in the sample below to


//add composite types to service operations
[DataContract]
public class CompositeType
{
bool boolValue = true;
string stringValue = "Hello ";

[DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}

[DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
}

Service1.cs
Collapse Copy Code

//<createdby> Murali Manohar Pareek </createdby>


//<date> Oct 23, 2008 </date>
//<description> WCF Service</description>
//<version> 1.0.0.0 </version>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace WCFServiceSample
{
// NOTE: If you change the class name "Service1" here,
you must also update the reference to "Service1" in App.config.
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}

public CompositeType GetDataUsingDataContract(CompositeType composite)


{
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
}
}

App.Config
Collapse Copy Code
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<!-- When deploying the service library project, the content of the config
file
must be added to the host's
app.config file. System.Configuration does not support config files for
libraries. -->
<system.serviceModel>
<services>
<service name="WCFServiceSample.Service1" behaviorConfiguration=
"WCFServiceSample.Service1Behavior">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:8731/Design_Time_Addresses
/WCFServiceSample/Service1/" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address
supplied
above -->
<endpoint address ="" binding="wsHttpBinding" contract=
"WCFServiceSample.IService1">
<!--
Upon deployment, the following identity element should be removed
or replaced to reflect the identity under which the deployed service runs.
If removed, WCF will infer an appropriate identity
automatically.
-->
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<!-- Metadata Endpoints -->
<!-- The Metadata Exchange endpoint is used by the service to describe
itself to clients. -->
<!-- This endpoint does not use a secure binding and should be secured
or removed before deployment -->
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFServiceSample.Service1Behavior">
<!-- To avoid disclosing metadata information,
set the value below to false and remove the metadata endpoint above
before deployment -->
<serviceMetadata httpGetEnabled="True"/>
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>

Run WCF Service Library

When we run this application as like simple windows or web application, it will host
the application automatically and run the Test Client. We can use Test Client as
follows:

Hosting the WCF Service

 IIS 6 (ASPNET_WP.EXE / W3wp.exe)


o Activation on demand upon client request
o Only supports HTTP/S transport
 Self Hosting
o Can be any managed application, i.e. Console or WinForms application
o Low-level but flexible
 Windows Activation Service (WAS)
o Supports all transports
o Will ship with IIS 7 on Vista and Longhorn Server
 Managed Windows Services (NT Services)

Here we will host the WCF Service on Managed Windows Service. We will Add New
Project as follows:
Step 1: Add New Project

Step 2: Select Windows Service Project


Step 3: Add Reference
Step 4: Select Project Tab and Add “WCFServiceSample” Library as a
Reference into Windows Service

Step 5: Now we will open the WCF Service Host. To open the service
Host, we need System.ServiceModel Library as a reference into
the windows service.
Step 6: Windows service itself does not have any configuration file
related to WCF Service Configuration like endpoint, behavior
etc. so we have to include App.Config file into the windows
service. We simply add Application Configuration File and make
the same copy as App.Config file in WCFServcieSample
application.

Step 7: Now we add the code in Windows service to open the Host.
Step 8: Add Windows Service Code
Collapse Copy Code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.ServiceModel;
using System.IO;

namespace WCFServiceSampleWindowsServiceHost
{
public partial class Service1 : ServiceBase
{
ServiceHost host;
FileStream fs;
StreamWriter m_streamWriter;

public Service1()
{
InitializeComponent();
}

protected override void OnStart(string[] args)


{
fs = new FileStream(@"c:\temp\WCFLog.txt", FileMode.OpenOrCreate,
FileAccess.Write);
m_streamWriter = new StreamWriter(fs);

try
{
if (host != null)
{
host.Close();
}

host = new ServiceHost(typeof(WCFServiceSample.Service1));


host.Open();

m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
m_streamWriter.WriteLine(DateTime.Now + " WCF: Host
open successfully \n");

m_streamWriter.WriteLine(DateTime.Now + " WCF: Service


Started successfully \n");
}
catch (Exception ex)
{
m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
m_streamWriter.WriteLine(DateTime.Now + " WCF: Error in
opening Host : " + ex.Message + "\n");

if (host != null)
{
host = null;
}
}
finally
{
m_streamWriter.Flush();
m_streamWriter.Close();
m_streamWriter = null;
fs.Close();
fs = null;
}
}

protected override void OnStop()


{
fs = new FileStream(@"c:\temp\WCFLog.txt", FileMode.OpenOrCreate,
FileAccess.Write);
m_streamWriter = new StreamWriter(fs);

try
{
if (host != null)
{
host.Close();
host = null;

m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
m_streamWriter.WriteLine(DateTime.Now + " WCF: Host close
successfully \n");
m_streamWriter.WriteLine(DateTime.Now + " WCF: Stopped
successfully \n");
}
}
catch (Exception ex)
{
m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
m_streamWriter.WriteLine(DateTime.Now + " WCF: Error in
closing Host : " + ex.Message + "\n");
}
finally
{
m_streamWriter.Flush();
m_streamWriter.Close();
m_streamWriter = null;
fs.Close();
fs = null;
}
}
}
}
Step 9: Add Installer. It will add Service Process Installer and Service
Installer. Service Process Installer takes care for Service Account
related information and Service Installer takes care of service
related information like ServiceName, DisplayName, StarupType
etc.
Step 10: Set the ServiceProcessInstaller Property as required.
Step 11: Set the ServiceInstaller Property as required and build the
application.

Run Windows Service

To run the windows service we have to install the windows service. There is two
option to install the windows service.

1. Using InstallUtil Command of .NET Framework.

Open the command prompt and run below command

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe
D:\murali\projects\WCF
Demo\SampleWCFService\WCFServiceHost\bin\Debug\
WCFServiceSampleWindowsServiceHost.exe

Using Setup Project


Install Windows Service using Setup Project

Step 1: Add Setup Project

Step 2: Add Project Output


Step 3: Select “WCFServiceSampleWindowsServiceHost” as primary
output.

Step 4: View Custom Actions


Step 5: Add Custom Actions

Step 6: Select Primary output from Application Folder of Setup Project


Step 7: Primary output will automatically add with all sub folder of
Custom Actions. Now Build the Setup Application

Step 8: Install the Setup Application


Step 9: It will show the Setup Wizard, using this wizard we will install
the Windows Service

Step 10: Now open Services using Control Panel -> Administrative Tools
-> Services. It will show the list of available service. Select our
“WCFServiceSample” Service and Start it.
Step 11: Starting Service.

Consuming the WCF Service

We add Web Application Project as a client.

Step 1: Add ASP.NET Web Application Project


Step 2: Add Service Reference using Right click on References of the
Web application, and select Add Service Reference. Add Service
Address, this address is same as defined in App.Config file. Type
the Namespace of the Service that we desire and press Ok
button
Step 3: The proxy is created and added to the service reference, and is
ready to consume the service in the application with the
WCFServiceSample reference

Using WCF Service Client

Create the instance of the WCF client to communicate to the WCF service as follows:

Collapse Copy Code


protected void btnGetData_Click(object sender, EventArgs e)
{
WCFServiceSample.Service1Client proxy =
new WebApplicationSample.WCFServiceSample.Service1Client();
lblOutput.Text =proxy.GetData(Convert.ToInt32(txtInput.Text));
}

protected void btnGetCompData_Click(object sender, EventArgs e)


{
WCFServiceSample.Service1Client proxy =
new WebApplicationSample.WCFServiceSample.Service1Client();
WCFServiceSample.CompositeType compType =
new WebApplicationSample.WCFServiceSample.CompositeType();
compType.BoolValue = true;
compType.StringValue = txtInput.Text;
compType = proxy.GetDataUsingDataContract(compType);
lblOutput.Text = compType.StringValue;
}

Run Web Application

Enter the input into the given text box and get the output by pressing the button.

Conclusion

This article includes WCF Introduction, Sample WCF Service Library, Hosting of WCF
Service at Windows Service and consuming the WCF Service at Web Application. I
will include details about configuring a service and a client for different types of
communication in my next article very soon.

History

WCF : A few tips

Introduction

I am by no means a WCF expert, but I have been using it a bit at work of late, and I
have come across a few issues that I thought may be worth mentioning in an a top-
tips style article.
So that is what this article will be.

This article assumes you know a little bit about WCF, and that you know enough to
edit config files.

Please make sure to read the "Running the code" section before you try to run it.

Tip1 : Debugging WCF

One of the first things that you will most likely want to do is call a WCF service and
debug it. Now when I first started creating WCF services at my company I created
IIS web hosted services. While this may be a great end solution, it doesn't really
offer the opportunity to be debugged that easily. So my advice would be to create a
Console based implementation of your WCF service and use this for debugging
purposes, and then when you are happy you can push the tested code back into an
IIS web based service.

The attached demo app uses a Console hosted (self hosted) WCF service, which is
hosted as follows:

Collapse Copy Code


using System;
using System.ServiceModel;

namespace WcfServiceLibrary1
{
class Program
{
static void Main(string[] args)
{

Console.WriteLine("-------------------------------------------------------------
--------");
Console.WriteLine("This is the WCF Service hosting within a console
application");
Console.WriteLine("The service can also be hosted with a web
browser");
Console.WriteLine("");
Console.WriteLine("Initializing WCF Service...");

// The service configuration is loaded from app.config


using (ServiceHost host = new ServiceHost(typeof(Service)))
{
host.Open();
Console.WriteLine("WCF Service is ready for requests." +
"Press any key to close the service.");
Console.WriteLine();
Console.Read();

Console.WriteLine("Closing service...");
}
}
}
}

So this is enough to host the WCF service.

Tip2 : Adding a Service Reference

If we consider how the attached demo app WCF service is configured at the server
end.

Collapse Copy Code


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="InitialTransactionValue" value="12" />
</appSettings>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MetadataBehavior">
<serviceMetadata httpGetEnabled="true"
httpGetUrl="http://localhost:8001/ServiceHost/mex" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MetadataBehavior"
name="WcfServiceLibrary1.Service">
<endpoint
address="service"
binding="netTcpBinding"
contract="WcfServiceLibrary1.IService"
name="TcpBinding" />
<endpoint
address="service"
binding="wsDualHttpBinding"
contract="WcfServiceLibrary1.IService"
name="HttpBinding" />
<endpoint
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"
name="MexBinding"/>
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8000/ServiceHost/" />
<add baseAddress="http://localhost:8001/ServiceHost/" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>

It can be seen that there are 3 possible end points

 netTcpBinding
 HttpBinding
 MexBinding

and 2 possible host addresses

 net.tcp://localhost:8000/ServiceHost/
 http://localhost:8001/ServiceHost/

My personal experience was that, I could never find the running service if I tried to
add a service reference using the "tcp" host address. I ALWAYS had to use the "http"
host address to find the running service. This is shown below.
So this failed where I tried to use "Tcp" host address. But if I used the "Http" host
address all is cool
So I would recommend always creating a http binding to allow you to gain access to
the service eevn if you don't end up using the http binding.

Amendment

One of the readers of this article, Benoît Dion, suggested that I could fix this with
altering the mexBinding end point in the service end.

So this is what I did with this small App.Config change at the service end.

Collapse Copy Code


<!--<endpoint
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"
name="MexBinding"/>-->
<endpoint
address="mex"
binding="mexTcpBinding"
contract="IMetadataExchange" />
And I am pleased to inform that this now allows you to add the service reference
using the tcp address, net.tcp://localhost:8000/ServiceHost/

So thanks Benoît.

Tip3 : Service Configuration

In the attached demo app, the WCF service definition looks like the following

Collapse Copy Code


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Net.Security;

namespace WcfServiceLibrary1
{
/// <summary>
/// The service contract
/// </summary>
[ServiceContract(
Name = "IService",
Namespace = "WcfServiceLibrary1.Service")]
public interface IService
{
[OperationContract]
[ReferencePreservingDataContractFormat]
List<Person> GetPeople();

[OperationContract]
List<Person> GetPeopleWithOutCicularReferencing();

//A simple DataContract serializable class


[DataContract]
public class Person
{

int age = 0;
string name = string.Empty;
List<Person> children = new List<Person>();
Person parent = null;

[DataMember]
public int Age
{
get { return age; }
set { age = value; }
}

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

[DataMember]
public List<Person> Children
{
get { return children; }
set { children = value; }
}

[DataMember]
public Person Parent
{
get { return parent; }
set { parent = value; }
}

}
}

It can be seen that the service contract operations (methods) return generic
List<T>, which is personal choice. But what you must make sure is that the proxy
(client) for the WCF service actually returns the same sort of objects. This is
achieved by configuring the WCF service reference when you add it.

To add a reference you must ensure that you have access to the running WCF
service host (ie the actual service), in the attached demo this is the Console app.

So providing you have access to the actual WCF service, you should ensure that you
configure the service to use the same types as the operation contracts that were
defined within the service contract interface. Which in the case shown above was
generic List<T>, so we can change this in the drop down combo boxes provided
within the Data Type section of the service reference settings dialog.

If you do not have a service reference and are in the process of adding it, this
service reference settings dialog, is accessable from the Advanced button of the add
service reference dialog.
Tip4 : Service Parameters

When the WCF service was eventually added it was found that some of the default
parameters just were not big enough. Shown below is the before and after
App.Config for the client.
So I changed some of these parameters to improve the service throughput
Tip5 : Circular References

As part of something we were doing I needed to have a circular reference, you know
when object A holds a reference to object B and object B holds a reference to object
A.

What was found was that the default DataContractSerializer couln't to set to
deal with serializing a cyclic object graph in a config file, even though it is totally
capable of doing this task. It appeared that some of the properties of the
DataContractSerializer can only be set via a constructor call, not via config
files. So I did a bit of research into this and found some interesting code that allowed
you to create a specialized DataContractSerializer that would allow cyclic
object graphs to be serialized. The code that I found allowed you to adorn your
service interface operation contracts with a custom attribute called
ReferencePreservingDataContractFormatAttribute

Collapse Copy Code


using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Runtime.Serialization;
using System.ServiceModel.Description;

namespace WcfServiceLibrary1
{

/// <summary>
/// Allows us to adorn the IService contract with this
/// attribute to indicate that a specialized DataContractSerializer
/// should be used that has preserveObjectReferences set true
/// </summary>
public class ReferencePreservingDataContractFormatAttribute
: Attribute, IOperationBehavior
{
#region IOperationBehavior Members
public void AddBindingParameters(OperationDescription description,
BindingParameterCollection parameters)
{
}
public void ApplyClientBehavior(OperationDescription description,
System.ServiceModel.Dispatcher.ClientOperation proxy)
{
IOperationBehavior innerBehavior =
new
ReferencePreservingDataContractSerializerOperationBehavior(description);
innerBehavior.ApplyClientBehavior(description, proxy);
}

public void ApplyDispatchBehavior(OperationDescription description,


System.ServiceModel.Dispatcher.DispatchOperation dispatch)
{
IOperationBehavior innerBehavior =
new
ReferencePreservingDataContractSerializerOperationBehavior(description);
innerBehavior.ApplyDispatchBehavior(description, dispatch);
}

public void Validate(OperationDescription description)


{
}

#endregion
}
}

Which in turns create a new


ReferencePreservingDataContractSerializerOperationBehavior object
that inherits from IOperationBehavior. It is this class that is resposible for
creating the actual DataContractSerializer that allows serializing a cyclic
object graph. The code for this class is as follows:

Collapse Copy Code


using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Runtime.Serialization;
using System.ServiceModel.Description;
namespace WcfServiceLibrary1
{
/// <summary>
/// A specialized DataContractSerializer that has
/// preserveObjectReferences set true, which allows for
/// circular references to be serialized
/// </summary>
public class ReferencePreservingDataContractSerializerOperationBehavior :
DataContractSerializerOperationBehavior
{
#region Ctor
public ReferencePreservingDataContractSerializerOperationBehavior(
OperationDescription operationDescription)
: base(operationDescription) { }
#endregion

#region Public Methods


public override XmlObjectSerializer CreateSerializer(Type type, string
name,
string ns, IList<Type> knownTypes)
{
return CreateDataContractSerializer(type, name, ns, knownTypes);
}

public override XmlObjectSerializer CreateSerializer(Type type,


XmlDictionaryString name, XmlDictionaryString ns, IList<Type>
knownTypes)
{
return new DataContractSerializer(type, name, ns, knownTypes,
2147483646 /*maxItemsInObjectGraph*/,
false/*ignoreExtensionDataObject*/,
true/*preserveObjectReferences*/,
null/*dataContractSurrogate*/);
}
#endregion

#region Private Methods


private static XmlObjectSerializer CreateDataContractSerializer(Type
type,
string name, string ns, IList<Type> knownTypes)
{
return CreateDataContractSerializer(type, name, ns, knownTypes);
}
#endregion
}
}

The important part is the constructor of the DataContractSerializer where we


set the preserveObjectReferences value. This is the all important part.

The importance of this class may become clearer if we see an example screen shots
from the attached demo where the following applies:

 The first WCF call uses the


ReferencePreservingDataContractFormatAttribute, so is safe to
return circular references
 The second WCF call uses the standard DataContractSerializer, so
causes a communication Exception.

If we just remind ourselves what the service contract looks like

Collapse Copy Code


/// <summary>
/// The service contract
/// </summary>
[ServiceContract(
Name = "IService",
Namespace = "WcfServiceLibrary1.Service")]
public interface IService
{
[OperationContract]
[ReferencePreservingDataContractFormat]
List<Person> GetPeople();

[OperationContract]
List<Person> GetPeopleWithOutCicularReferencing();

So we can see that the 1st call worked just fine, as we used the
ReferencePreservingDataContractFormatAttribute, so is safe to return
circular references

But the next call failed completely, and resulted in a communication Exception. This
is because the standard DataContractSerializer, doesnt have the
preserveObjectReferences parameter turned on.
I can take no resposibility for creating either the
ReferencePreservingDataContractFormatAttribute or the
ReferencePreservingDataContractSerializerOperationBehavior code.
This is down to Sowmy Srinivasan, whos blog I found it on. I totally get what its
about though, as I hope you do now. You can read more at Sowmy Srinivasan's Blog

Wrap Up

I am fully aware that these tips may not be suitable for everyones WCF services, but
they are things that I found helped my own code, as such I thought it may be worth
sharing what I found. I hope at least one of these tips is useful to you.

Running the Code

You will need to change the App.Config in the ServiceClientTestApp project to use
your own PC user.

So you will need to change the following lines

<userPrincipalName value="XXXXXX" />

To be something like

<userPrincipalName value="YOUR_PC_NAME\YOUR_USER"/>

If you dont change this, the ServiceClientTestApp project will not work.

We're Done

If you liked this article and found it useful please leave a vote/comment.

Вам также может понравиться