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

Overview on WCF Service Architecture

This article will help you to understand WCF Service Architecture. It describes major components of
WCF like Contracts and its different types, Policies and Binding, Service Runtime, Messaging,
Activation and Hosting and how they work together.
WCF service is collection of Endpoints and each endpoint describes how service is going to be
communicate with clients. Endpoint has Address which tells where the WCF service
resides, Bindings describes which protocol will be used for communication and Contract which
gives details about how data will be exchanged.

Below diagram from MSDN describes you how WCF application works.

Components of WCF

Contracts
Basically WCF contracts defines how service behaves and what opeartions it
exposes to clients. If service execution get some exception then service might
issue fault and contract decides what kind of fault to issue. Contracts also
defines What kind of MEPs required by service?
Below are WCF Contract Types

Service Contract: defines which operations service makes avilable for


communication with clients and implications for the underlying message
exchange while communication. Service Contract is collective mechanisms
by which a service's capabilities and requirement are describes to clients.
You create a WCF Service Contract by defining .NET interface. See more
details on Service Contract Attribute

Operation Contract: is a part of WCF Service Contract and can be


applied only to methods. WCF uses opt-in model to define what can be
exposed to clients means you have to explicitly apply [OperationContract]
to methods. It is like web methods in ASMX web service. See more
on Operation Contract Attribute

Data Contract: defines structure of data included in SOAP messages


while communication between service and clients. It creates a custom data
type which represents business entity like Customer, Product etc and it
becomes a formal agreement between Service and Client which describes
what kind of data to be exchanged. WCF uses Data Contract Serializer by
default to serialize and deserialize data. See how to implement
DataContract in WCF?

Message Contract: allows you to manage how messages to be


structured and control message headers. It gives you nice platform to
control WCF messages. Some time the default soap messages generated by
WCF are not capable to fulfill your requirements and you wish to
customize or modify it using MessageContracts. See implementing WCF
MessageContract

Policies and Binding

It specifies required or optional that client should follow for communication


with WCF service. Policies are defined in WS-Policy specification. For example
if WCF service defines a endpoint which supports transport security, reliable
messaging and a binary encoding and other specifications, this endpoint
details will be exposed by WSDL to client as policy assertion. Client will
understand it and follow those requirements.
For best possible result from WCF Architecture you should use proper policy
specification and choose bindings. See how to choose which WCF binding

Service Runtime
It describes different behavior that can make effect on service run time. After
you design and implement ServiceContracts you can configure service and
operation behavior. Using those behaviors you can achieve through puts,
reliability and performance of services. Below are WCF behaviors which can
be configured in configuration file or programmatically.

Throttling Behavior: ServiceThrottlingBehavior class exposes


properties like MaxConcurrentCalls, MaxConcurrentInstances,
MaxConcurrentSessions. These properties are very useful for WCF
services perfromance. Using this you can decide how many instances or
sessions can be created at application level

Error Behavior: It allows you to decide how to handle errors or


exceptions occured at WCF layer. FaultContract are widely used to handle
WCF exceptions.

Metadata Behavior: specify whether service metadata is avilable to


clients. By adding mex endpoint and configuring or adding
programmatically serviceMetadata element of behavior element in
config file you can enable or disable metadata to clients.

Instance Behavior: decides how objects are created and refers to the
life time of the service object. Whenever clients make request runtime will
create service objects to provide the response. Through instancing we can
control how long this service instance wants to be retained. By setting
InstanceContextMode property of ServiceBehavior you can control
instance behavior. You can set it as PerCall, PerSession or Single.

Transaction Behavior: enables WCF operations to be complies with


ACID (Atomic, Consistency, Isolation, Durability) properties and execute
operations as single logical unit where either all or none of the statements
get executed. Transctions work with WCF operations however it also
depend on how you configure your service and what binding you use.

Dispatch Behavior: controls how a message is processed to and from


WCF Infrastructure. You can use message compression and optimized file
type encoding.

Messaging
WCF messaging provides a unified programing model and flexibility for
presenting data and messages exchanges. Messaging layer has many channels,
those channels are called as Channel Stack. Each channel involves in some or
other way in processing of message like authentication, sending or recieving
messages to and from endpoint. Channels are included in
System.ServiceModel.Channels namespace.
There are two types of channels

Protocol Channels: are Transaction Protocol, Reliable Messaging


Protocol and Security Protocol. Implements SOAP based protocol by
processing and possibly modifying message. E.g. WS-Security and WSReliability.

Transport Channels: includes Message Encoding and Transport


Protocol. Handles sending and receiving message from network.

Activation and Hosting:


WCF service can be host in multiple ways and activate for clients. Every
method for hosting comes with advantages and disadvantages. While choosing
hosting environment for your WCF service you should consider - what
protocols are used, what kind of security you required, how service should be
activated for clients.
Below are different ways to host your WCF service.

IIS: you can host only HTTP/HTTPs based WCF services in if your
using IIS 6.0 or previous versions. Hosting in IIS gives feature like
"activation on demand" your service code is not in memory for all time
and gets instantiated whenever first request comes in.
See how to host WCF service in IIS

WAS: is the new process activation method that comes with IIS 7.0.
You can host WCF service and have HTTP and non HTTP (TCP or
netNamedPipe protocols) based message based activation

Self-Hosting: WCF service can be self hosted as console application,


Win Forms or WPF application with graphical UI. Self-hosting might look
like a lot of work - but it does give you the best flexibility: you can pick
your protocols as you like, you can set up your own addressing scheme the
way you like it, and you have total control over what gets done when. You
can introduce your own custom ServiceHost if you need to do some extra
work to host services, and so on.

Windows Service: WCF service objects lifetime will be controlled by


Service Controller Manager(SCM) of Windows. SCM is avilable for all
versions of Windows. Advantages of hosting WCF service in Windows
Service includes service remains activated and avilable for clients as there
is no runtime activation, any type of protocols can be used, more security
through Windows Identity.
See hosting WCF service in Windows service

WCF message exchange patterns and


implementation of duplex service
What are WCF message exchange patterns?

Message exchange patterns are standard design which tells how the communication between WCF
service and client should happen. It decides protocols for communication channels to exchange
messages between service and clients and help interoperability.

WCF supports three message exchange patterns which are described below.

1. One Way
One Way mep is like short term memory loss, it just fires the execution
and forget about the response. It is useful when client do not require the
response back like changing status of order, logging some noncritical
operations. If you are using MSMQ bindings then One way mep is the best
choice for communication as client just needs to call the queue and
execution of task is totally depend on queue. For marking the operation as
one way use IsOneWay = True.

[ServiceContract]
public interface IOrders
{
[OperationContract(IsOneWay=true)]
public void CompleteOrder(int orderID);
}

Note that using One-way operation contract with fault contract or


transaction contexts is not possible.

2. Request-response
In Request-response mep client sends message to WCF service and service
sends back some response with required processing. This is the most used
pattern in SOA as many real time operation requires some status or data
back as response. Using this pattern with the void return type operations
empty SOAP body will be send to client as response. For marking
operation as Request-response you do not have do anything as the default
property of IsOneWay is false.

[ServiceContract]
public interface IOrders
{
[OperationContract]
public void PlaceOrder(Order order);
}

3. Duplex
Duplex pattern is two way message channel where service and client can
communicate independently with each other and execute operations.
Client should provide the appropriate endpoint using it service should be
able to send messages. In real time application Duplex pattern is
complicated as it service required active connection and open firewalls of
client which is usually avoided because of security. Most of the Duplex
contracts requires long running sessions at cost of performance.

[ServiceContract]
public interface IOrderDuplexCallback
{
[OperationContract(IsOneWay = true)]
void ShowShipmentDetails(Delivery delivery);
}

[ServiceContract(Namespace = "http://NorthwindServices/OrderService",
SessionMode=SessionMode.PerSession,
CallbackContract=typeof(IOrderDuplexCallback))]
public interface IOrder
{
[OperationContract(IsOneWay = true)]
void PlaceOrder(Order order);
}

The difference between Request-response and Duplex pattern is, Requestresponse pattern requires the response on same communication channel
whereas Duplex will create the separate communication channel to return
response to client.

Step by step walkthrough to implement Duplex contract.


This part of article describes step by step defining and creating WCF duplex
contracts. Duplex contract enables service and clients communicates each
other without depending on each other. Duplex communication requires client
to provide channel on which service can trigger operations.

1. Create WCF Service library


Create a new WCF Service library as suggested in Create new WCF service
library and test using WCFTestClient. This article will give you a basic
service implementation.

2. Add Service Contract


Duplex contract requires ServiceContracts with One Way and
voidOperationContract.
Add new Service Contracts to the project
Primary contract which will be called by client to service. It uses
SessionMode.PerSession to maintain each session data.

[ServiceContract(Namespace = "http://NorthwindServices/OrderService",
SessionMode=SessionMode.Allowed,
CallbackContract=typeof(IOrderDuplexCallback))]
public interface IOrder
{
[OperationContract(IsOneWay = true)]
void PlaceOrder(Order order);
}

CallbackContract which will be called by service to client. As it is


mentioned as callback contract for IOrder WCF will add ServiceContract
so no need to mention it explicitly.

public interface IOrderDuplexCallback


{
[OperationContract(IsOneWay = true)]
void ShowShipmentDetails(Delivery delivery);
}

3. Duplex Service implementation


Implement IOrder interface with PlaceOrder operations.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class OrderService : IOrder
{
public void PlaceOrder(int orderID)
{
//Add code for placing orders

// In real application you can use it to update clients


// as and when the shipping status change.

// You can call this method from other internal classes


// to update shipping like shipped, in transit, delivered.
Callback.ShowShipmentDetails(string.Format
("Your order has shipped with tracking number {0} ", 22298889844));
}

/// <summar>
/// Read only public property to give access to callback contract

/// </summary>
public IOrderDuplexCallback Callback
{
get
{
return OperationContext.Current.GetCallbackChannel
<IOrderDuplexCallback>();
}
}
}

4. Add service endpoint


Open the app.config file and the endpoint for Order Service. For duplex
contract we will use wsDualHttpBinding.

<services>
<service name="NorthwindServices.OrderService">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:7741/NorthwindServices
/OrderService/" />
</baseAddresses>
</host>
<endpoint address ="" binding="wsDualHttpBinding"
contract="NorthwindServices.IOrder">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding"

contract="IMetadataExchange"/>
</service>
</services>

5. Host OrderService
Host this OrderService as suggested in Hosting WCF service in
IIS. orhosting in Windows service.

6. Client Application
Add the client application as suggested in article for Hosting service in
previous step.

7. Callback client class


Add a class with name OrderCallback to client application. This class will
implement the callback contract interface. Add reference to your service in
class by using keyword.

using Northwind.OrderServiceRef;

public class OrderCallback : IOrderCallback


{
public void ShowShipmentDetails(string TrackingID)
{
Console.WriteLine(TrackingID);
}
}

8. Call Service Operation

Open the program.cs from client console application and add below code.
It creates the InstanceContext of callback and hit the service operation.

static void Main(string[] args)


{
OrderCallback callback = new OrderCallback();
InstanceContext context = new InstanceContext(callback);
OrderServiceRef.OrderClient client = new OrderClient(context);
client.PlaceOrder(1234);
Console.Read();
}

9. Test Service Operation


Add the break points in OrderCallback.cs and main methods. Run the
console application by pressing F5. After calling service operation it calls
the ShowShipmentDetails from OrderCallback.cs and print message send
by service.

WCF Service Contract Attributes


This article will give you brief description about wcf service contract attributes like namespace,
callbackcontract, protectionlevel, configuration name, session mode. This will help you to design wcf
service contract in more efficient way. WCF service contract is included in System.Servicemodel
namespace. Service Contracts are behavioral contracts as defines behavior of service. You will have
to include the reference to System.Servicemodel and use [ServiceContract]with interface or class.
It is a good practice to create service contract with interface as interface creates contract model for
client.

Service contract has below attributes:


1. Name
This is a string property which allows you to set the name of the service
contract. The default name of your service is your class or interface name.
If you are using [ServiceContract] with the interface the prefix "I" also will
include to your service name. So It is always better to use some
meaningful name for your service. The wsdl will include your service
name as PortType.

[ServiceContract(Name="Product")]
public interface IProductService
{

2. CallbackContract
Callback contracts are used in duplex message channel where client and
server can call each other. (Read more on WCF MEP) In duplex model
client send request to server it might be time consuming operation and
then service needs to provide notification to client through callback
contracts. If you use callbackcontract you will loose the service

interoperability. Also you need to consider that not all bindings support
callback contracts like the bindings which are depend on HTTP protocols.
HTTP protocols are stateless whereas duplex channel require live
connection to complete the operation.

[ServiceContract]
interface IOrdersCallback
{
[OperationContract(IsOneWay = true)]
void OnOrderPlaced(string message, DateTime timestamp);
}

[ServiceContract(CallbackContract = typeof(IOrdersCallback))]
public interface IOrders
{
[OperationContract]
bool OrderPlace(Order order);
}

See how to implement callback contracts

3. ConfigurationName
By using ConfigurationName property you can set the service name in
service config file. It specifies the name of config element for service.

[ServiceContract(Name="Orders", ConfigurationName="OrderService")]
public interface IOrders
{
[OperationContract]
void PlaceOrder(Order order);
}

In config file

<service name="OrderService">
<endpoint
address="http://localhost:8080/OrderService" binding="basicHttpBinding"
bindingConfiguration="myBindingConfiguration" contract="IOrders">
</service>

4. HasProtectionLevel
It is a read only boolean property. If the ProtectionLevel property is set to
other than "None", HasProtectionLevel property will return true else
return false.

5. ProtectionLevel
It allows you to define protection level for all messages on wire. There are
three different options of ProtectionLevel enum available.
o

None : No protection will be applied to messages.

Sign : Messages will be signed digitally before sending.

EncryptAndSign : Encrypt message before digitally signed and


send.

[ServiceContract(ProtectionLevel = ProtectionLevel.Sign)]
public interface IOrderService
{
[OperationContract()]
bool PlaceOrder();
}

Whatever value you set for ServiceContract.ProtectionLevel same value


will be applied to all OperationContract and FaultContract. If you
explicitly set different values to operation contract an exception will be
thrown.

6. Namespace
If you are having multiple services with similar method signatures adding
a unique namespace value to service contract will help you as your
methods will become unique by using this feature. This property is very
important while serialization and deserialization as you might have
similar class names at client side and service side.

[ServiceContract(Namespace="http://northwind.com/orderservice") ]
public interface IOrderService
{
[OperationContract(Name="GetOrder")]
Order GetOrder(int orderID);
}

You must set the same value to bindingNamespace in app.config for


service.

7. SessionMode
It allows you to decide how session should work for your service. Only
bindings with WS-*, NetTcpBinding and NetNamedPipeBinding allows
sessions. There are three ways to handle sessions.
o

Allowed : Request with session is allowed but not mandatory.

Required : Service can be connected only through valid sessions.

NotAllowed : Service can be connected only through sessionless


requests.

[ServiceContract(SessionMode = SessionMode.Allowed)]

public interface IOrders


{

WCF Operation Contract Attributes


This article will give you brief description about wcf operation contract attributes. This will help you
to design wcf operation contract in more effective way. WCF operation contract is included in
System.Servicemodel namespace. You will have to include the reference to System.Servicemodel and
use[OperationContract] with methods. Methods marked as [OperationContract] will be exposed
to clients for invoking. It is similar to Web methods of asmx web services.

Operation contract has below attributes:


1. Name
It is read/write string property. You can get or set the different and
meaningful name to your operations using this property. The default value
for this property would be your method name. The value of this property
will be used in wsdl for <operation> element.

[ServiceContract()]
public interface IOrders
{
[OperationContract(Name="PlaceOrder")]
bool OrderPlace(Order order);
}

2. Action and ReplyAction


Action and ReplyAction properties are co related. The default value for
Action is concatenation of ServiceNameSpace + ServiceContractName +
OperationName and for ReplyAction ServiceNameSpace +
ServiceContractName + OperationName + Response.
Action header indicates the URI of Operation to be invoked and defines
WS-Addressing action. WS-Addressing allows you transport neutral
communication between client and service and it is very much useful in
situation where SOAP response is not enough and cannot be provided
immediately. So you will have to introduce intermediate router service
between client and target service which will receive message and route to
different services for additional activities.
You can specify the value for Action and ReplyAction as "*" (an asterisk)
to handle all unhandled URI.
Create new WCF service library and test using WCFTestClient

[ServiceContract(Namespace="http://orders.northwind.com")]
public interface IOrders
{
[OperationContract(
Action="http://orders.northwind.com/placeorders",
Name="PlaceOrders",
ReplyAction="http://orders.northwind.com/reorderqty"
)]
Message PlaceOrders(Message msg);
}

3. AsyncPattern
AsyncPattern is a Boolean property with default value of false. You can
mark it as true if your service operation should execute asynchronously on
client or server or both. You should create the asynchronous operations to
handle long running processes like I/O calls.

For creating wcf asynchronous operations use the method name


conventions as BeginMethodName and EndMethodName. The
BeginMethodName must be marked as
[OperationContract(AsyncPattern=true)].

[ServiceContract]
public interface IOrders
{
[OperationContract]
int TodaysOrderCount(DateTime dt);

[OperationContract(AsyncPattern = true)]
IAsyncResult BeginPlaceOrder(Order order, AsyncCallback cb, Object state);

bool EndPlaceOrder(IAsyncResult ar);


}

4. HasProtectionLevel
HasProtectionLevel is a read only Boolean property with default value of
false. If value of ProtectionLevel is set to "None" it will return false and if
ProtectionLevel is set to Sign or EncryptAndSign it will return true.

5. IsInitiating
IsInitiating is a Boolean property with default value of false. The service
operation marked with IsInitiating = true must be called before any other
operation from client side. This operation will create new session for
client. For use of this the ServiceContract should support sessions by
marking SessionMode=SessionMode.Required or
SessionMode=SessionMode.Allowed. This property can be used where
Service Contract needs to validate the client details before executing any
operation.

From below example client must call ValidateClient before any other
operation call. If any other operation get called before ValidateClient
service returns ActionNotSupported FaultException. Operation
PlaceOrder can be call many times after calling ValidateClient and before
CloseChannel.

[ServiceContract(SessionMode=SessionMode.Required)]
public class OrderService
{
[OperationContract(
IsOneWay=true,
IsInitiating=true,
IsTerminating=false
)]
public void ValidateClient()
{
return true;
}

[OperationContract(
IsInitiating=false,
IsTerminating=false
)]
public bool PlaceOrder(Order order)
{
// Place order code
return true;
}

[OperationContract(
IsOneWay=true,
IsInitiating=false,
IsTerminating=true

)]
public void CloseChannel()
{
//code to end session for current client
}
}

6. IsTerminating
This is a Boolean property with default value of false. IsTerminating is
used to close client's current session. In previous example once operation
CloseChannel called no other calls can be made to service except
ValidateClient.

7. IsOneWay
IsOneWay is Boolean property with default value of false. For making
operation as One way you need to set IsOneWay = true. IsOneWay
operations has short term memory loss, it just fired and forget without
bothering about response or execution of operation.
Sometime operation just need to execute without expecting the response
like marking the order status. You cannot use FaultException,
TransactionContext with OneWay operations. If you are using MSMQ
bindings One Way operations are very much useful. If the value of
IsOneWay is false and operation's return type is void then empty SOAP
body return.

[ServiceContract]
public interface IOrders
{
[OperationContract(IsOneWay=true)]
public void ChangeOrderStatus(int orderID, OrderStatus orderStatus);
}

8. Name
Name is string property with default value of Operation Name. It allows
you to give operation name with more meaningful value than the default
method name. This value will be generated in WSDL for <Operation>
element.

[ServiceContract]
public interface IOrders
{
[OperationContract(Name="GetOrderReport")]
String OrderReport(DateTime dt);
}

9. ProtectionLevel
The default value for ProtectionLevel is None or the value which is set at
ServiceContract level. It defines the Protection Level of operation and how
service messages will be protected. The value for ProtectionLevel can be
set as
o
o
o

None : No protection will be applied to messages and message


will flow on wire as plain text.
Sign : Messages will be digitally signed before sending.
EncryptAndSign : Messages will be encrypted before sign and
sending.

Not all wcf Bindings like BasicHttpBindins supports ProtectionLevel. For


using ProtectionLevel property you must use the binding which supports
protection. Bindings security mode should be set to Message, if it is set to
None or Transport the operation level setting of protection level does not
have any effect.

[ServiceContract()]

public interface IOrders


{
[OperationContract(ProtectionLevel = ProtectionLevel.Sign)]
int GetHighValueOrdersCount(DateTime dt);
}

WCF DataContract with enum example

WCF DataContracts
This article explains required steps to implement WCF DataContracts with Enum members.
DataContract represents the business entities like Product, Customer, Order. It is a agreement
between service and clients for exchanging data.
Go through an article on WCF DataContract attributes for the best use of DataContracts.

Step by step implementation of WCF DataContract and


Enum members

1. Create WCF Service Library


Create a WCF service library as suggested in Create new WCF service
library and test using WCFTestClient.

2. Add ProductWebOnly DataContract enum

Add ProductWebOnly enum to the WCF Service Library created in


previous step. Right click on NorthwindServices -> Select Add -> Class
-> name it as ProductWebOnly.cs.
Add Enum Members to it as Yes and No to indicating whether the
project is avilable only on Web.

using System.Runtime.Serialization;

namespace NorthwindServices
{
[DataContract]
public enum ProductWebOnly
{
[EnumMember]
Yes,

[EnumMember]
No
}
}

3. Product datastore
Create or replace Products.xml for service data store. Add below xml to
the file.
Note that XML is different than the one created in first step. Added
newWebOnly element for ProductWebOnly enum

<?xml version="1.0" standalone="yes"?>


<DocumentElement>

<Products>
<ProductID>1</ProductID>
<ProductName>Chai</ProductName>
<categoryID>1</categoryID>
<UnitsInStock>39</UnitsInStock>
<CategoryName>Condiments</CategoryName>
<WebOnly>Yes</WebOnly>
</Products>
<Products>
<ProductID>2</ProductID>
<ProductName>Chang</ProductName>
<categoryID>1</categoryID>
<UnitsInStock>17</UnitsInStock>
<CategoryName>Condiments</CategoryName>
<WebOnly>No</WebOnly>
</Products>
<Products>
<ProductID>3</ProductID>
<ProductName>Aniseed Syrup</ProductName>
<categoryID>2</categoryID>
<UnitsInStock>13</UnitsInStock>
<CategoryName>Condiments</CategoryName>
<WebOnly>Yes</WebOnly>
</Products>
</DocumentElement>

4. Add Product DataContract


Add Product DataContract to the WCF Service Library created in
previous step. Right click on NorthwindServices -> Select Add -> Class
-> name it as Product.cs

Product DataContract will represent Product entity from Products.xml


datastore.
See the use of WebOnly DataMember which is using ProductWebOnly
DataContract.

using System.Runtime.Serialization;

namespace NorthwindServices
{
[DataContract]
public class Product
{
[DataMember]
public int ProductID { get; set; }

[DataMember]
public string ProductName { get; set; }

[DataMember]
public int CategoryID { get; set; }

[DataMember]
public string CategoryName { get; set; }

[DataMember]
public int UnitsInStock { get; set; }

[DataMember]
public ProductWebOnly WebOnly { get; set; }
}
}

5.

New OperationContract

Open IProducts ServiceContract from NorthwindServices library and


add new OperationContract GetProducts, GetAllProducts, AddProduct.

using System.ServiceModel;

namespace NorthwindServices
{
[ServiceContract]
public interface IProducts
{
[OperationContract]
string GetProductName(int productID);

[OperationContract]
int GetProductQty(int productID);

[OperationContract]
string GetCategoryName(int productID);

[OperationContract] Product GetProduct(int productID);

[OperationContract]
List<Product> GetAllProducts();

[OperationContract]
bool AddProduct(Product product);
}
}

6. Implementation IProducts ServiceContract


Implement the IProducts ServiceContract by implementing its
OperationContracts. Open the ProductService.cs file created in first step
from NorthwindServices. Add new methods for OperationContract
GetProduct, GetAllProducts, AddProduct.
The method implementaion of GetCategoryName, GetProductQty,
GetProductName created in first step has omitted from below code as it
does not implement DataContract. You should keep it in
ProductService.cs or remove it from IProduct.cs as well.

using System.Xml.Linq;

namespace NorthwindServices
{
public class ProductService : IProducts
{
public Product GetProduct(int productID)
{
Product product = new Product();

XDocument doc = XDocument.Load("C:\\products.xml");

IEnumerable<XElement> products =
(from result in doc.Descendants("DocumentElement")
.Descendants("Products")
where result.Element("ProductID").Value==productID.ToString()
select result);

product.ProductID =
products.ElementAt(0).Element("ProductID").Value;
product.ProductName =

products.ElementAt(0).Element("ProductName").Value;
product.CategoryID =
products.ElementAt(0).Element("categoryID").Value;
product.UnitsInStock =
products.ElementAt(0).Element("UnitsInStock").Value;
product.WebOnly =
(ProductWebOnly)Enum.Parse(typeof(ProductWebOnly),
products.ElementAt(0).Element("WebOnly").Value);

return product;
}

public List<Product> GetAllProducts()


{
List<Product> lstProducts = new List<Product>();

XDocument doc = XDocument.Load("C:\\products.xml");

IEnumerable<XElement> products =
(from result in doc.Descendants("DocumentElement")
.Descendants("Products")
select result);

foreach(XElement element in products)


{
Product product = new Product();

product.ProductID = element.Element("ProductID").Value;
product.ProductName = element.Element("ProductName").Value;
product.CategoryID = element.Element("categoryID").Value;
product.UnitsInStock = element.Element("UnitsInStock").Value;
product.WebOnly=(ProductWebOnly)Enum.Parse(
typeof(ProductWebOnly), element.Element("WebOnly").Value);

lstProducts.Add(product);
}
return lstProducts;
}

public bool AddProduct(Product product)


{
List<Product> lstProducts = new List<Product>();

XDocument doc = XDocument.Load("C:\\products.xml");

doc.Element("DocumentElement").Add(
new XElement("Products",
new XElement("ProductID", product.ProductID),
new XElement("ProductName", product.ProductName),
new XElement("UnitsInStock", product.UnitsInStock),
new XElement("CategoryID", product.CategoryID),
new XElement("CategoryName", product.CategoryName),
new XElement("WebOnly", product.WebOnly)));

doc.Save("C:\\products.xml");

return true;
}
}
}

If you provide an input value to parameter ProductID of GetProduct


method which is not available in data store. It will through an exception.
So handle such exceptions using FaultContract.

7. ProductService Endpoint

You do not need to change anything from app.config file for service
endpoint as you have just added some methods to ServiceContract and
do not have change address, binding or contract.
Make sure you have below endpoint in app.config of Service library.

<service name="NorthwindServices.ProductService">
<host>
<baseAddresses>
<add baseAddress =
"http://localhost:7741/NorthwindServices/ProductService" />
</baseAddresses>
</host>
<endpoint address ="" binding="wsHttpBinding"
contract="NorthwindServices.IProducts">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange"/>
</service>

8. Host Product WCF Service


Host this Product WCF Service in IIS using WCF service in IIS or
inWindows service.

9. Client Application for Product WCF service


Open the program.cs file from Client application created in previous
step. Add implementation for Service Operations.

using NorthwindApp.ProductServiceRef;

namespace NorthwindApp
{
class Program
{
static void Main(string[] args)
{
AddProduct();
GetAllProducts();
GetProductDetails();
Console.Read();
}

private static void AddProduct()


{
using (ProductsClient client = new ProductsClient())
{
Product product = new Product();
product.CategoryID = "2";
product.CategoryName = "Condiments";
product.ProductID = "8";
product.ProductName = "Coffee";
product.UnitsInStock = "20";
product.WebOnly = ProductWebOnly.No;
client.AddProduct(product);
}
}

private static void GetAllProducts()


{
using (ProductsClient client = new ProductsClient())

{
Product[] products = client.GetAllProducts();

for (int index = 0; index < products.Count(); index++)


{
ShowProduct(products[index]);
}
}
}

private static void GetProductDetails()


{
using (ProductsClient client = new ProductsClient())
{
ProductServiceRef.Product product = client.GetProduct(2);
ShowProduct(product);
}
}

private static void ShowProduct(Product product)


{
Console.WriteLine("Product ID : " + product.ProductID);
Console.WriteLine("Product Name : " + product.ProductName);
Console.WriteLine("CategoryID : " + product.CategoryID);
Console.WriteLine("Units In Stock : " + product.UnitsInStock);
Console.WriteLine("Web Only : " + product.WebOnly);
Console.WriteLine("********************************");
Console.WriteLine();
}
}
}

Tutorial on wcf message contract by


example
This article gives you a walkthrough on WCF message contract by example, when to use WCF
message contract, comparison of DataContract and MessageContract and finally some constraint on
using WCF Message Contracts.

When to use WCF Message Contracts.


By default WCF takes care of creating SOAP messages according to
serviceDataContracts and OperationContracts. However some time you
required full control on SOAP messages structure and how serialization
happens specially when your service needs to be interoperable for consuming
by different types of clients or service needs to provide extra layer of security
on messages and message parts. Messages are exchanged in different way
of Message Exchange Patterns in WCF .

WCF DataContract vs MessageContract


Northwind system which is used for Order Entry web application with order
details is running on Windows server which might have effect on the Product
inventory back office application running on unix machine and payment
application with customer details on mainframe machine. At the same time
Product details need to send to your marketing campaign through API.
For accomplishing all those requirements you might create different
DataContracts which will give you the XML xsd for communication with
clients and other services. Such XSDs are tightly coupled which faces
versioning issues and do not give you any control. For any last minute change
on serialized object you will have to use events like OnSerializing or
OnDeserializing. For example each of these operation requires to validate the
private license key. This validation needs to be done in OnSerializing and if
validation is sucessful then serilize the object.
You can also choose to create MessageContracts which will give you more
control over the SOAP and no need for handling any extra events. SOAP
headers are the reasonable place to keep the private keys like license key
which can be use for validation.

ServiceContract never changes in case of MessageContracts in case of


modification in data structure just need to change the message contract and
no need for the regenerating proxies. In case of change in DataContracts you
need to regenerate the proxy. So MessageContract is the good choice if your
entity changes often.

Implementation of MessageContract
Below is an implementation of MessageContract where Northwind WCF
service has heterogeneous client ask for the customer info. Only clients with
specific license key will get the required response else WCF FaultExceptionwill
be thrown.

1. Create New Service library


Create a new service using Create new WCF service library and test using
WCFTestClient

2. Customer DataContract
Add new Customer DataContract to handle the Customer related info by
adding new class to Service library. Add below code to the class and
reference to System.Runtime.Serialization

namespace NorthwindServices
{
[DataContract]
public class Customer
{
[DataMember]
public string CustomerName;

[DataMember]
public string PhoneNumber;

[DataMember]
public string Email;
}
}

3. Request MessageContract
Create a new MessageContract for request by adding new class to Service
library. Name it as CustomerContactRequest. Add reference to
System.ServiceModel

namespace NorthwindServices
{
[MessageContract(IsWrapped=false)]
public class CustomerContactRequest
{
[MessageHeader]
public string LicenseKey;

[MessageBodyMember]
public int CustomerID;
}
}

4. Response MessageContract
Create a MessageContract for response.

namespace NorthwindServices
{
[MessageContract(IsWrapped = false)]
public class CustomerContactResponse

{
[MessageBodyMember]
public Customer Contact;
}
}

5. Add ServiceContract
Add a service contract to handle customer message request and response.

[ServiceContract]
public class ICustomerService
{
[OperationContract]
[FaultContract(typeof(string)]
CustomerContactResponse
GetCustomerContact(CustomerContactRequest request);
}

6. Implementation of ICustomerService
Implement ICustomerService as below. If LicenseKey is matching return
the contact information else throw FaultException.

public class CustomerService : ICustomerService


{
/// <summary>
/// App key to validate
/// In real time application this key can be reside
///

in config files or in data base.

/// </summary>

private string AppKey


{
get
{
return "northwind-xxx-1234-abc";
}
}

public CustomerContactResponse
GetCustomerContact(CustomerContactRequest request)
{
if (request.LicenseKey != AppKey)
throw new FaultException<string>("Invalid Key");

// Get a record from your data store based on request.CustomerID


//

and set it to CustomerContactResponse as below.

CustomerContactResponse response = new CustomerContactResponse();


response.Contact = new Customer();
response.Contact.CustomerName = "Abc";
response.Contact.Email = "abc@xyz.com";
response.Contact.PhoneNumber = "91 77 980 91 000";
return response;
}
}

7. Add service endpoint


Add CustomerService endpoint in app.config of NorthwindServices wcf
service library under <system.serviceModel><services>

<service name="NorthwindServices.CustomerService">

<host>
<baseAddresses>
<add baseAddress = "http://localhost:7741/NorthwindServices/
CustomerService" />
</baseAddresses>
</host>
<endpoint address ="" binding="wsHttpBinding"
contract="NorthwindServices.ICustomerService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange"/>
</service>

8. Host CustomerService
Host the CustomerService in hosting WCF service in IIS or in hosting in
Windows service.

9. CustomerService client
Add client application for WCF CustomerService as suggested by article in
previous. step.
Add ServiceReference to CustomerService to NorthwindApp client
application by right clicking on Service References -> Enter
http://localhost:7741/NorthwindServices/CustomerService in address
box and click Go.
Add a reference to NorthwindApp.CustomerServiceRef in Program.cs
Add below client code in Program.cs of client application.

static void Main(string[] args)


{
CustomerServiceClient client = new CustomerServiceClient();
try
{
CustomerContactResponse response = new CustomerContactResponse();

//response.Contact = client.GetCustomerContact("abcd", 1234);

response.Contact = client.GetCustomerContact
("northwind-xxx-1234-abc", 1234);

Console.WriteLine(response.Contact.CustomerName);
Console.WriteLine(response.Contact.Email);
Console.WriteLine(response.Contact.PhoneNumber);
}
catch (FaultException<string> ex)
{
Console.WriteLine(ex.Detail);
}
Console.Read();
}

Handling wcf service exceptions using fault


contracts and data contracts.
In this article we will see how we can use WCF fault contracts to handle exceptions. WCF gives you
enough flexibility to handle exceptions and send required detail to clients. By default WCF sends
exception details to clients using SOAP FaultContract. The default FaultContract will allow you to set
Message, Reason properties and throw it to clients.

We can easily customize the FaultContract with generic version


FaultContract<T> which helps you to provide more appropriate and
meaningful details to client with custom error messages and also the flexibility
to log or take actions on critical errors. To get more details about exceptions
you can enable WCF tracing and logging.
Why we should use the FaultContract rather than using .Net exceptions?
Exceptions has limitations and security risks.
1.

.Net exception can be used by only CLR supported languages so loosing


great WCF feature of interoperability.

2.

Throwing exceptions can provide service implementation and private


details to clients.

3.

Exceptions are tightly coupled between clients and service.

We will add our FaultContract to existing service created by article - Create


new WCF service library and test using WCFTestClient

Walkthrough for implementing FaultContracts.


1. Create WCF Service library
Create a new WCF Service library as suggested in Create new WCF service
library and test using WCFTestClient. This article will give you a basic
service implementation.

2. Add DataContract for FaultContract


Add new DataContract which will work as FaultContract to send error
messages to clients.

[DataContract]
public class ServiceException
{
/// <summary>

/// Exception Message


/// </summary>
[DataMember]
public string Message { get; set; }

/// <summary>
/// If critical, user should redirect to error page
/// and exception details should log.
/// </summary>
[DataMember]
public bool IsCritical { get; set; }
}

See details about DataMember and EnumMember.

3. Exception Manager
Add new sealed class to project and name it as ExceptionManager. This
class will work as single point to handle all WCF service exceptions and
errors.

public sealed class ExceptionManager


{
/// <summary>
/// Private Constructor to ensure that the class cannot be instantiated
/// </summary>
private ExceptionManager()
{

public static ServiceException HandleException(string message)


{

return HandleException(message, false);


}

public static ServiceException HandleException(string message,


bool isCritical)
{
ServiceException exception = new ServiceException();
exception.Message = message;
exception.IsCritical = isCritical;

// Log exception details if it is critical

return exception;
}

public static ServiceException HandleException(System.Exception ex)


{
ServiceException exception = new ServiceException();
exception.Message = ex.Message;
exception.IsCritical = IsCritical(ex);

// Log exception details if it is critical

return exception;
}

/// <summary>
/// If error is not user defined then IsCritical should be true.
/// </summary>
/// <param name="ex">Exception</param>
/// <returns>bool value</returns>
private static bool IsCritical(System.Exception ex)
{

bool returnValue = true;


if (ex is SqlException)
{
SqlException sqlEx = (SqlException)ex;
returnValue = sqlEx.Number > 50000 ? false : true;
}
return returnValue;
}

public static bool HandleException(System.Exception ex, string policyName)


{
throw new NotImplementedException();
}
}

4. Add FaultContracts
Add FaultContracts to OperationContract.

[ServiceContract]
public interface IProducts
{
[OperationContract]
[FaultContract(typeof(ServiceException))]
string GetProductName(int productID);

[OperationContract]
[FaultContract(typeof(ServiceException))]
int GetProductQty(int productID);

[OperationContract]
[FaultContract(typeof(ServiceException))]

string GetCategoryName(int productID);


}

5. FaultContract Implementation
Add implementation for FaultContract. If any error occurs, error will be
handled by ExceptionManager class and custom message will be return to
clients.

public class ProductService : IProducts


{
public string GetProductName(int productID)
{
string productName = string.Empty;

try
{
XDocument doc = XDocument.Load("products.xml");

productName =
(from result in doc.Descendants("DocumentElement")
.Descendants("Products")
where result.Element("productID").Value == productID.ToString()
select result.Element("productname").Value)
.FirstOrDefault<string>();

if (string.IsNullOrEmpty(productName))
throw new FaultException<ServiceException>(ExceptionManager.
HandleException("Product ID does not exist in system."));
}catch (Exception ex)
{

throw new FaultException<ServiceException>


(ExceptionManager.HandleException(ex));
}

return productName;
}

public int GetProductQty(int productID)


{
int ProductQty = 0;

try
{
XDocument doc = XDocument.Load("products.xml");
string strProductQty =
(from result in doc.Descendants("DocumentElement")
.Descendants("Products")
where result.Element("productID").Value == productID.ToString()
select result.Element("UnitsInStock").Value)
.FirstOrDefault<string>();

if (string.IsNullOrEmpty(strProductQty))
throw new FaultException<ServiceException>(ExceptionManager.
HandleException("Product ID does not exist in system."));

int.TryParse(strProductQty, out ProductQty);


}catch (Exception ex)
{
throw new FaultException<ServiceException>
(ExceptionManager.HandleException(ex));
}
return ProductQty;
}

public string GetCategoryName(int productID)


{
string categoryName = string.Empty;
try
{
XDocument doc = XDocument.Load("products.xml");

categoryName =
(from result in doc.Descendants("DocumentElement")
.Descendants("Products")
where result.Element("productID").Value == productID.ToString()
select result.Element("CategoryName").Value)
.FirstOrDefault<string>();

if (string.IsNullOrEmpty(categoryName))
throw new FaultException<ServiceException>(ExceptionManager.
HandleException("Product ID does not exist in system."));
}catch (Exception ex)
{
throw new FaultException<ServiceException>
(ExceptionManager.HandleException(ex));
}

return categoryName;
}
}

6. Hosting Service
Host this WCF service in IIS or in Windows service.

7. Add Client Application

Now add console application to solution. Name it as NorthwindApp.

8. Add Service Reference


Add service reference to NorthwindApp by right click on NorthwindApp
project and click on Add Service Reference. Below window should appear.
Enter the address of service endpoint which you have added in service
app.config.

Enter ProductServiceRef for Namespace and click on OK. Service


reference is added to your client application.

Check Client application's App.config, it should have service endpoint and


client details.

9. Client Implementation
Service reference is now available for Northwind. We can call service
operations and implement error handling using FaultContracts. Add the
below code to NorthwindApp -> Program.cs file.

class Program
{
static void Main(string[] args)
{
ShowOperations();
}

private static void ShowOperations()


{
ConsoleKeyInfo cki;

do
{
Console.WriteLine();
Console.WriteLine("Enter Product ID or press Esc to quit : ");
cki = Console.ReadKey();
if (!char.IsNumber(cki.KeyChar))
{
Console.WriteLine(" Invalid number");
}
else
{
Int32 number;
if (Int32.TryParse(cki.KeyChar.ToString(), out number))
{
Console.WriteLine();
GetProductName(number);
GetProductQty(number);
GetCategoryName(number);
}
else
{
Console.WriteLine("Unable to parse input");
}
}
} while (cki.Key != ConsoleKey.Escape);

Console.Read();
}

private static void GetProductName(int ProductID)


{
try
{

ProductsClient client = new ProductsClient();


string ProductName = client.GetProductName(ProductID);
Console.WriteLine(string.Format("Product name {0} for ProductID {1}",
ProductName, ProductID));
}
catch(FaultException<ServiceException> ex)
{
Console.WriteLine(string.Format("Errors
occured in service : {0} ", ex.Detail.Message));
}
}

private static void GetProductQty(int ProductID)


{
try
{
ProductsClient client = new ProductsClient();
int ProductQty = client.GetProductQty(ProductID);
Console.WriteLine(string.Format("Product qty {0} for Product ID {1}",
ProductQty, ProductID));
}
catch(FaultException<ServiceException> ex)
{
Console.WriteLine(string.Format("Errors
occured in service : {0} ", ex.Detail.Message));
}
}

private static void GetCategoryName(int ProductID)


{
try
{
ProductsClient client = new ProductsClient();

string CategoryName = client.GetCategoryName(ProductID);

When to use which bindings in WCF


WCF comes with number of built-in bindings and this article describes pros and cons of each of these
bindings. It will help you to choose appropriate bindings depending on your requirements and create
endpoints for communicating to clients.

What is WCF Bindings?


WCF bindings decides how Windows Communication Foundation service endpoint should
communicate with clients. Each WCF service endpoint requires binding to be specified, if not set
explicitly it uses default basicHttpBinding. It gives communication details and define below
things.
1.

Protocols: specifies what type of security can be used like reliable messaging or transaction
context.

2.

Encoding: specifies type of message encoding like binary or text.

3.

Transport: specifies communication transport to be used like HTTP or TCP.

WCF Predefined Bindings


1. basicHttpBinding
basicHttpBinding is best when you have traditional ASMX(Active Server
Methods) web services and needs to be replace with WCF. It supports text
as well as MTOM encodings and it does not support WS-* standards like
WS-Addressing, WS-Security and WS-ReliableMessaging.
basicHttpBinding uses HTTP or HTTPS protocols. You can
configureSSL for Transport Layer security with basicHttpBinding.

2. WsHttpBinding

This is secure and interoperable bindings uses SOAP over HTTP. With
WsHttpBinding messages are encrypted by default and achieve message
level security. It supports reliability, transactions and security over
internet. It supports HTTP or HTTPS protocols and text as well as MTOM
encoding.
The difference between basicHttpBinding and WsHttpBindingis
WsHttpBinding does support WS-* standards like WS-Addressing, WSSecurity and WS-ReliableMessaging

3. wsDualHttpBinding
wsDualHttpBinding is best when you required bidirectional
communication with client. In some scenario when client makes call to
WCF service, after processing of long running request service has to call
client application for example updating shipment details to client
application.
It supports reliability, transactions and security over internet. It supports
HTTP or HTTPS protocols and text as well as MTOM encoding. You can
implement Duplex message exchange pattern with wsDualHttpBinding.

4. webHttpBinding
webHttpBinding is best when you wish to implement RESTful WCF
service. This is secure and interoperable binding which sends information
directly over HTTP or HTTPS without creating SOAP messages. It allows
HTTP request to use plain old XML (POX) style messaging which reduces
the message size on wire compare to SOAP messages.

5. NetTcpBinding
netTcpBinding is best when WCF service and its clients are in intranet
infrastructure. As it supports only TCP protocol and not HTTP so service
cannot be accessed over internet.
This is secure binding is used to send binary encoded SOAP messages with
in intranet computers. It supports reliability, transaction and security. If
your using netTcpBinding and host WCF service in IIS, you need to make
some settings on system and IIS this article will help you for required
settings.

6. netNamedPipeBinding

When your WCF service and its clients reside on same computer
netNamedPipeBinding is the best choice and gives best performance over
other bindings. This is secure bindings. Binary encoded SOAP messages
are sent over named pipes.
See how to implement netNamedPipeBinding in WCF services.

7. netPeerTcpBinding
netPeerTcpBinding is best when you require more security for peer to peer
communication as netTcpBinding does not provide it. It is secure binding
and supports TCP protocols.

8. WsFederationHttpBinding
It is secure and interoperable binding supports federated security. It
supports HTTP and HTTPS transport protocols as well as text and MTOM
encodings.

9. NetMsmqBinding
netMsmqBinding is best when you have to execute service operations in
queued manner. Service requests are placed in queue and executed one by
one. With netMsmqBinding service operations will always be one way and
does not return any response to client.
This is interoperable bindings and can be used on existing MSMQ
applications that use COM or Application Programing Interface(API)
In real time applications you have to use multiple bindings for one service
endpoints. For example internet applications should be able to access service
through HTTP request at same time the back office application should be able
to access service by netTcpBinding or netNamedPipeBinding to get
performance benefits.

CategoryName,ProductID));
}
catch(FaultException<ServiceException> ex)
{
Console.WriteLine(string.Format("Errors
occured in service : {0} ", ex.Detail.Message));

}
}
}

See the implementation of ServiceException in bold.


While working with code from this article do not forget to mention appropriate
path of data store which can be Products.xml download here.

Configure IIS for WCF service with SSL and


transport security
This article will help you to configure IIS for WCF service with SSL and achieve WCF Transport
security. It uses a WCF service, create a SSL certificate usingIIS Server Certificates with WCF
service hosted in IIS.
In Windows Communication Foundation Transport security is depend on the binding and transport
being used. It requires SSL certificate to be registered with IIS. For production environment you
must obtain the certificate from third party certificate issuer like Verisign. In Transport Security
server and clients are configured with X.509 certificates to allow verification of other party. For
development purpose you can create Self Signed Certificate

Advantages of Transport Security

Improved interoperability as it does not required for both parties to


understand XML level security.

Improvement in overall performance as compare to Message level


security.

Streaming is possible where as in Message level security it is not


possible.

We can implement SSL for WCF service in two ways

If you are hosting WCF service in IIS you can use IIS infrastructure to
set up SSL.

If your WCF service is self-hosted you can create SSL certificate


usingHttpCfg.exe and use it for service binding.

Step by step configuration of IIS for WCF Service with SSL


Create Self Signed SSL certificate
In this step we will create self-signed certificate using IIS manager.
Open IIS manager using inetmgr command. Select <server name > from
connection pane which is at left side of IIS manager.
Double click on Server Certificates from middle pane of IIS manager.
From actions (right side) pane of IIS manager click on Self Signed
Certificate.
You will get a new window where you have to enter certificate name. Give
name as NorthwindCertificates.

Create and Host your WCF Service


Create a WCF service.

Endpoint configuration for Transport security


Open the WCF service library application created in previous step. Open
app.config file from NorthwindServices application to make changes for
WCF endpoint to allow transport security with ssl.
Add bindingConfiguration which sets attributes for basicHttpBinding and
set its security mode. There are three type of security modes avilable in

WCFMessage for message level security, Transport for transport level


security and TransportWithMessageCredential for providing security
over transport with encrypted messages or you can set it as None to disable
security of WCF service.
Set clientCredentialType as None to specify anonymous authentication
which does not perform client authetication. The possible values for
clientCredentialType are None, Basic, Digest, Ntlm, Windows.
Change serviceBehaviors for allowing https request by setting
httpsGetEnabled="true".
Your Service endpoint will be

<system.serviceModel>
<services>
<service name="NorthwindServices.ProductService">

<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="secureHttpBinding"
contract="NorthwindServices.IProducts"/>

<endpoint address="mex"
binding="mexHttpsBinding"
contract="IMetadataExchange" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="secureHttpBinding">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</basicHttpBinding>

</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

Configure SSL Certificate for WCF Service


Host your WCF service in IIS. In IIS manager right click on the site which you
created for hosting and click on Edit Bindings.... From the new window you
should be able to see http binding configured.
Now click on Add button and select https from type dropdown of Add Site
Binding window.
From SSL Certificate drop down select NorthwindCertificate which you
created in first step. Click Ok and close Site Bindings window.

Publish your WCF service once again to https://localhost/ address.

Client application for SSL secured WCF service


Create a client application for this SSL secured WCF service and Add Service
Reference to https://localhost/ProductServiceHost.svc.
Add below code to client application which calls WCF service and get Product
details for ProductID 1.

namespace NorthwindClient
{
class Program
{
static void Main(string[] args)
{
ProductServiceRef.ProductsClient client
= new ProductServiceRef.ProductsClient();
string category = client.GetCategoryName(1);
string name = client.GetProductName(1);
int qty = client.GetProductQty(1);
Console.WriteLine("Product Name : " + name);
Console.WriteLine("Product Qty : " + qty.ToString());
Console.WriteLine("Product Category : " + category);
Console.Read();
}
}
}

Execute the client application you might


getSecurityNegotiationException with Could not establish trust
relationship for the SSL/TLS secure channel with authority
'localhost'. To resolve this issue open app.config file of client application
and replace localhost from endpoint address with your computer name.

https://localhost/ProductServiceHost.svc

Change it to
https://<your computer name>/ProductServiceHost.svc

Download source code.


WCF Message Level Security by Example
This article will describe how to implement WCF message level security. It will show you the
required steps to create WCF library, host it in IIS, secure with Message Level Security, client
application and finally see encrypted messages using WCFTraceViewer.

WCF Security
WCF provides three modes for security. Transport, Message and
TransportWithMessageCredential. Transport security can be achieved with SSL over http(https).
This article elaborates Message Level security. TransportWithMessageCredential is a
combination of other two.

What is WCF Message Security


Message level security encrypts request / response messages using WSSecurity specifications. It encloses security credentials and claims with every
message. Each message either signed or encrypted. Message Security provides

end-to-end channel security and is independent of transport protocol. In short


mutual authentication and message security are delivered at the message
level.

Advantages of Message Level security in WCF


Message Security provides multiple levels of security meaning that
different parts (header, body etc) of message can be secured by different
encryption methods.
Message Security is not dependent on WCF protocols. It provides the
security regardless of binding used.
Message Security provides end-to-end security, in Transport Security
where once the message received at server it is not encrypted whereas in
Message Level security it is still encrypted.
Message security is the only option to provide security when you have
intermediate routers to route request / response.

Implementation of Message Level Security in WCF

Creation of WCF Service Library


Go through Create a WCF Service and Test using WCFTestClient. It creates
basic WCF Service which has OperationContracts to return Product details
from Products.xml.

Host ProductService in IIS


For this article we will use http protocols and host service in IIS. Unlike
Transport Security you do not need to make any changes in IIS for Message
Level Security.

Configure WCF Message Level Security


Open NorthwindServices service library which you created in first step and
open its App.config file.
Here we will configure bindingConfiguration element of endpoint.
Add<bindings> section under <system.serviceModel>
Set security mode as Message and clientCredentialType as Windows.
Your <system.serviceModel> configuration should look like

<system.serviceModel>
<services>
<service name="NorthwindServices.ProductService"
behaviorConfiguration="ServiceBehavior">
<host>
<baseAddresses>
<add baseAddress =
"http://localhost:7741/NorthwindServices
/ProductService/" />
</baseAddresses>
</host>
<endpoint address ="" binding="wsHttpBinding"
contract="NorthwindServices.IProducts"
bindingConfiguration ="wsMessage">

<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior" >
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name ="wsMessage">
<security mode ="Message">
<message clientCredentialType ="Windows"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>

clientCredentialType
clientCredentialType can have any value from below available options for
Message Level Security.
1. None: Messages are secured with encryption however it does not
perform any authentication.
2. Windows: Messages are secured with encryption and clients are
authenticated using built in Windows Authentication which can be
through Active Directory or NTLM.
3. UserName: Messages are secured and encrypted and clients are
authenticated by provided UserName and Password.
4. Certificate: Messages are encrypted and both service and clients are
authenticated with certificates.
5. IssuedToken: Messages are encrypted and authentication happens
through issued tokens by authority like Cardspace.

Client Application
Create a new console application as client for this WCF service. Add service
reference of ProductService to client application.

Add below client code to console application.

using NorthwindApp.ProductServiceRef;

namespace NorthwindApp
{

class Program
{
static void Main(string[] args)
{
ProductsClient client = new ProductsClient();
string cateName = client.GetCategoryName(1);
Console.WriteLine(cateName);
Console.Read();
}
}
}

Enable WCF Tracing and Message Logging for client application to see how
communication has encrypted. Execute application and open SvcTraceViewer.
SvcTraceViewer is located at C:\Program Files (x86)\Microsoft
SDKs\Windows\v7.0A\Bin. If you do not have SvcTraceViewer
installed click here to download.
Trace and Messages must have generated after execution of client application.
Open it and notice how messages are encrypted.

Download source code.

WCF message exchange patterns and


implementation of duplex service
What are WCF message exchange patterns?
Message exchange patterns are standard design which tells how the communication between WCF
service and client should happen. It decides protocols for communication channels to exchange
messages between service and clients and help interoperability.

WCF supports three message exchange patterns which are described below.

1. One Way
One Way mep is like short term memory loss, it just fires the execution
and forget about the response. It is useful when client do not require the
response back like changing status of order, logging some noncritical
operations. If you are using MSMQ bindings then One way mep is the best
choice for communication as client just needs to call the queue and
execution of task is totally depend on queue. For marking the operation as
one way use IsOneWay = True.

[ServiceContract]
public interface IOrders
{
[OperationContract(IsOneWay=true)]
public void CompleteOrder(int orderID);
}

Note that using One-way operation contract with fault contract or


transaction contexts is not possible.

2. Request-response
In Request-response mep client sends message to WCF service and service
sends back some response with required processing. This is the most used
pattern in SOA as many real time operation requires some status or data
back as response. Using this pattern with the void return type operations
empty SOAP body will be send to client as response. For marking
operation as Request-response you do not have do anything as the default
property of IsOneWay is false.

[ServiceContract]
public interface IOrders
{

[OperationContract]
public void PlaceOrder(Order order);
}

3. Duplex
Duplex pattern is two way message channel where service and client can
communicate independently with each other and execute operations.
Client should provide the appropriate endpoint using it service should be
able to send messages. In real time application Duplex pattern is
complicated as it service required active connection and open firewalls of
client which is usually avoided because of security. Most of the Duplex
contracts requires long running sessions at cost of performance.

[ServiceContract]
public interface IOrderDuplexCallback
{
[OperationContract(IsOneWay = true)]
void ShowShipmentDetails(Delivery delivery);
}

[ServiceContract(Namespace = "http://NorthwindServices/OrderService",
SessionMode=SessionMode.PerSession,
CallbackContract=typeof(IOrderDuplexCallback))]
public interface IOrder
{
[OperationContract(IsOneWay = true)]
void PlaceOrder(Order order);
}

The difference between Request-response and Duplex pattern is, Requestresponse pattern requires the response on same communication channel
whereas Duplex will create the separate communication channel to return
response to client.

Step by step walkthrough to implement Duplex contract.


This part of article describes step by step defining and creating WCF duplex
contracts. Duplex contract enables service and clients communicates each
other without depending on each other. Duplex communication requires client
to provide channel on which service can trigger operations.

1. Create WCF Service library


Create a new WCF Service library as suggested in Create new WCF service
library and test using WCFTestClient. This article will give you a basic
service implementation.

2. Add Service Contract


Duplex contract requires ServiceContracts with One Way and
voidOperationContract.
Add new Service Contracts to the project
Primary contract which will be called by client to service. It uses
SessionMode.PerSession to maintain each session data.

[ServiceContract(Namespace = "http://NorthwindServices/OrderService",
SessionMode=SessionMode.Allowed,
CallbackContract=typeof(IOrderDuplexCallback))]
public interface IOrder
{
[OperationContract(IsOneWay = true)]
void PlaceOrder(Order order);
}

CallbackContract which will be called by service to client. As it is


mentioned as callback contract for IOrder WCF will add ServiceContract
so no need to mention it explicitly.

public interface IOrderDuplexCallback


{
[OperationContract(IsOneWay = true)]
void ShowShipmentDetails(Delivery delivery);
}

3. Duplex Service implementation


Implement IOrder interface with PlaceOrder operations.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class OrderService : IOrder
{
public void PlaceOrder(int orderID)
{
//Add code for placing orders

// In real application you can use it to update clients


// as and when the shipping status change.

// You can call this method from other internal classes


// to update shipping like shipped, in transit, delivered.
Callback.ShowShipmentDetails(string.Format
("Your order has shipped with tracking number {0} ", 22298889844));
}

/// <summar>
/// Read only public property to give access to callback contract
/// </summary>
public IOrderDuplexCallback Callback
{

get
{
return OperationContext.Current.GetCallbackChannel
<IOrderDuplexCallback>();
}
}
}

4. Add service endpoint


Open the app.config file and the endpoint for Order Service. For duplex
contract we will use wsDualHttpBinding.

<services>
<service name="NorthwindServices.OrderService">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:7741/NorthwindServices
/OrderService/" />
</baseAddresses>
</host>
<endpoint address ="" binding="wsDualHttpBinding"
contract="NorthwindServices.IOrder">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange"/>
</service>
</services>

5. Host OrderService
Host this OrderService as suggested in Hosting WCF service in
IIS. orhosting in Windows service.

6. Client Application
Add the client application as suggested in article for Hosting service in
previous step.

7. Callback client class


Add a class with name OrderCallback to client application. This class will
implement the callback contract interface. Add reference to your service in
class by using keyword.

using Northwind.OrderServiceRef;

public class OrderCallback : IOrderCallback


{
public void ShowShipmentDetails(string TrackingID)
{
Console.WriteLine(TrackingID);
}
}

8. Call Service Operation


Open the program.cs from client console application and add below code.
It creates the InstanceContext of callback and hit the service operation.

static void Main(string[] args)


{
OrderCallback callback = new OrderCallback();
InstanceContext context = new InstanceContext(callback);
OrderServiceRef.OrderClient client = new OrderClient(context);
client.PlaceOrder(1234);
Console.Read();
}

9. Test Service Operation


Add the break points in OrderCallback.cs and main methods. Run the
console application by pressing F5. After calling service operation it calls
the ShowShipmentDetails from OrderCallback.cs and print message send
by service.

WCF by example on netNamedPipeBinding


netNamedPipeBinding is the best mechanism for interprocess communication which crosses process
boundaries on same machine. With netNamedPipeBinding the security can be achieved only through
transport level security as it does not support message level security. However messages are secured
as only the same machine can call the service operations.

The reason netNamedPipeBinding is the best mechanism because it gives you


the default security and best possible performance boost. To test the
performance of netNamedPipeBinding we called below service code in a loop
for 10 seconds from client console application using different bindings.
SeeWhen to use which WCF binding

public string WelcomeGuest(string guestName)


{

return "Welcome " + guestName;


}

Client Code
int i = 0;
DateTime n = DateTime.Now;

while((DateTime.Now.Second - n.Second) <= 10)


{
i++;
Console.WriteLine(Service.WelcomeGuest("ABC"));
}

Console.WriteLine(i.ToString());

And below is amazing statistics.


WSDualHttpBinding best for duplex contracts, executed for 1823 times.
WSHttpBinding best when addressing WS-* specifications, executed for 2797
times.
BasicHttpBinding best when you just want to convert your ASMX web services
to WCF, executed for 18974 times.
NetTcpBinding best when clients are only from intranet, executed for 41457
times.
NetNamedPipeBinding processed for 49789 times.

Step by step implementation of WCF service using


netNamedPipeBinding

1. Create WCF Service library


We will start with Create new WCF service library and test using
WCFTestClient. This article will give you a basic service implementation.

2. Add Customer ServiceContract


Add new ServiceContract by right click on NorthwindServices service
library project -> Select New Item -> Select Interface -> Name it as
ICustomer.

namespace NorthwindServices
{
[ServiceContract]
public interface ICustomer
{

}
}

3. Add OperationContracts
Add a reference to System.ServiceModel. Add OperationContract for
Customer Service. The operation contract GetCustomerName and
GetCustomerCount can be called by service clients.

namespace NorthwindServices
{
[ServiceContract]
public interface ICustomer
{
[OperationContract]
string GetCustomerName(int CustomerID);

[OperationContract]
int GetCustomerCount();
}
}

4. Customer DataAccess
We will use an XML file as Customer data store. Create a new XML and
add below elements to it.

<?xml version="1.0" standalone="yes"?>


<DocumentElement>
<Customer>
<CustomerID>1</CustomerID>
<CompanyName>Let's Stop N Shop</CompanyName>
<City>Mumbai</City>
</Customer>
<Customer>
<CustomerID>2</CustomerID>
<CompanyName>Hungry Coyote Import Store</CompanyName>
<City>Mumbai</City>
</Customer>
<Customer>
<CustomerID>3</CustomerID>
<CompanyName>John Steel</CompanyName>
<City>Pune</City>
</Customer>
<Customer>
<CustomerID>4</CustomerID>
<CompanyName>Andy's Seasoning</CompanyName>
<City>Delhi</City>

</Customer>
<Customer>
<CustomerID>5</CustomerID>
<CompanyName>Kountry Store</CompanyName>
<City>Pune</City>
</Customer>
</DocumentElement>

5. Implement ICustomer ServiceContract


Implement the interface ICustomer and add business logic to the
operation contracts.
The OperationContract GetCustomerName will return the CompanyName
based on CustomerID from Customers.xml
The OperationContract GetCustomerCount will return the total number of
Customers from Customers.xml

namespace NorthwindServices
{
public class CustomerService : ICustomer
{
public string GetCustomerName(int CustomerID)
{
XDocument doc = XDocument.Load("C:\\Customers.xml");

string companyName =
(from result in doc.Descendants("DocumentElement")
.Descendants("Customer")
where result.Element("CustomerID").Value
== CustomerID.ToString()
select result.Element("CompanyName").Value)

.FirstOrDefault<string>();

return companyName;
}

public int GetCustomerCount()


{
XDocument doc = XDocument.Load("C:\\Customers.xml");

return doc.Descendants("Customer").Count();
}
}
}

6. Service Endpoint
Open NorthwindServices wcf service library's app.config file. Add service
endpoint for customer service under <system.serviceModel><services>
tag.
Note that the address we are using is with net.pipe://localhost/
If you are using only one endpoint with netNamedPipeBinding for service
mark the httpGetEnabled as false from respective serviceBehaviors.

<system.serviceModel>
<services>
<service
name="NorthwindServices.CustomerService"
behaviorConfiguration="ServiceBehavior">

<host>
<baseAddresses>
<add baseAddress="net.pipe://localhost/NorthwindServices/" />

</baseAddresses>
</host>

<endpoint address="CustomerService"
binding="netNamedPipeBinding"
contract="NorthwindServices.ICustomer" />

<endpoint address="CustomerService/mex"
binding="mexNamedPipeBinding"
contract="IMetadataExchange" />

</service>
</services>

<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="False" />
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>

7. Host Customer Service in Windows Service Or in IIS


Go through the article hosting WCF service in Windows service to host
your Customer Service in windows services.
The <system.serviceModel> tag of app.config file from Windows service
should be same as the tag from wcf service library application.
For hosting it in IIS check the article hosting wcf service with
nettcpbinding or netnamedpipebinding in IIS

So you will have to add host for CustomerService and its endpoint details
in Windows service application as there are for ProductService. Add the
endpoint with net.pipe://localhost/ just like you added in
NorthwindServices.

8. CustomerService reference to client application


Create a client application as suggested in previous step. Add a service
reference to customer service by right clicking on client application -> Add
Service Reference.

9. Execute CustomerService
Write below code in client application to execute Service operations.

class Program
{
static void Main(string[] args)
{
int customerID = 2;
CustomerClient client = new CustomerClient();
string companyName = client.GetCustomerName(2);
Console.WriteLine(string.Format("Company name for Customer ID {0} is {1}",
customerID, companyName));
Console.WriteLine(string.Format("Total number of customers are {0} : ",
client.GetCustomerCount()));
Console.Read();
}
}

And below is the output

>

Quick Note : While using code from this article make sure you mention the
right path for Customers.xml

Multiple wcf services in one solution with


multiple endpoints and hosting
You might have tried one wcf service to learn about WCF or some small application. In real
application with only one WCF service it is difficult to handle applications all aspects. So in this
article I will explain you how to create multiple wcf services to serve different entities in one solution

with different endpoint and bindings. And also tells you how to host these services in IIS 7+ or in
Windows Services.

For this tutorial we will create two WCF services as 1.CustomerService and
2.OrderService

1. Start with WCF Service Library


If you would like to know about how to start with WCF go through the
article Create new WCF service library and test using WCFTestClient

2. Northwind Solution
Create empty solution by opening Visual Studio and click on File menu ->
Project -> Click on Other Project Types from Installed Template -> Select
Blank Solution
Give a name as Northwind.

3. NorthwindServices Service library


Add NorthwindServices WCF Service Library to Northwind solution by
right click on solution -> Add -> New Project -> Choose Visual C# from
Installed templates -> Select WCF -> Select WCF Service Library
Delete default IService1.cs, Service1.cs files from library.

4. Service Contracts

1.

Add ServiceContracts Folder to Northwind Service Library


project.

2.

Add ICustomerService contract to ServiceContracts folder created


in previous step.
Right click on ServiceContracts and add new Interface to folder.
Name it as ICustomerService. Add ServiceContract attribute to
ICustomer.

3.

Add OperationContract to ICustomerService which will be


accessible to clients. Your ICustomerService should look like.

4.
5.

using System.ServiceModel;

6.
7.

namespace NorthwindServices.ServiceContracts

8.

9.

[ServiceContract(Namespace =
"http://dotnetmentors.com/services/customer")]

10.

public interface ICustomerService

11.

12.

[OperationContract]

13.

string GetCustomerName(int CustomerID);

14.
15.

[OperationContract]

16.

string GetCustomerCity(int CustomerID);

17.
18.

[OperationContract]

19.

int GetCustomerCount();

20.

21.

22. Add IOrderService contract to ServiceContracts folder and


itsOperationContract as we added for ICustomerService.
IOrderService should look like

using System.ServiceModel;

namespace NorthwindServices.ServiceContracts
{
[ServiceContract(Namespace = "http://dotnetmentors.com/services/order")]

public interface IOrderService


{
[OperationContract]
string GetOrderDate(int orderID);

[OperationContract]
string GetOrderAmount(int OrderID);

[OperationContract]
string GetShipCountry(int orderID);
}
}

5. Datastore
Add two new XML files name it as Customers.xml and Orders.xml. These
xml files will be used as datastore for OrderService and CustomerService
respectively.
Customers.xml

<?xml version="1.0" standalone="yes"?>


<DocumentElement>
<Customer>
<CustomerID>1</CustomerID>
<CompanyName>Let's Stop N Shop</CompanyName>
<City>Mumbai</City>
</Customer>
<Customer>
<CustomerID>2</CustomerID>

<CompanyName>Hungry Coyote Import Store</CompanyName>


<City>Mumbai</City>
</Customer>
<Customer>
<CustomerID>4</CustomerID>
<CompanyName>Andy's Seasoning</CompanyName>
<City>Delhi</City>
</Customer>
</DocumentElement>

Orders.xml

<?xml version="1.0" standalone="yes"?>


<DocumentElement>
<Orders>
<OrderID>10248</OrderID>
<OrderDate>1996-07-04</OrderDate>
<ShippedDate>1996-07-16</ShippedDate>
<ShipCountry>France</ShipCountry>
<OrderTotal>650</OrderTotal>
</Orders>
<Orders>
<OrderID>10250</OrderID>
<OrderDate>1996-07-08</OrderDate>
<ShippedDate>1996-07-12</ShippedDate>
<ShipCountry>Brazil</ShipCountry>
<OrderTotal>2170</OrderTotal>
</Orders>
<Orders>
<OrderID>10251</OrderID>

<OrderDate>1996-07-08</OrderDate>
<ShippedDate>1996-07-15</ShippedDate>
<ShipCountry>France</ShipCountry>
<OrderTotal>1057</OrderTotal>
</Orders>
</DocumentElement>

6. Implementation of Customer and Order WCF service


1.

Add a Services folder to root of NorthwindServices service


library.

2.

Add a new class to Services folder created in previous step.


Name the class as CustomerService and implement the
ICustomerService service contract.

3.
4.

using NorthwindServices.ServiceContracts;

5.

using System.Xml.Linq;

6.
7.

namespace NorthwindServices.Services

8.

9.
[ServiceBehavior(Namespace="http://dotnetmentors.com/services/customer")]
10.

public class CustomerService : ICustomerService

11.

12.

public string GetCustomerName(int CustomerID)

13.

14.

XDocument doc = XDocument.Load("C:\\Customers.xml");

15.
16.

string companyName =

17.

(from result in doc.Descendants("DocumentElement")

18.

.Descendants("Customer")

19.

where result.Element("CustomerID").Value

20.

== CustomerID.ToString()

21.

select result.Element("CompanyName").Value)

22.

.FirstOrDefault<string>();

23.
24.

return companyName;

25.

26.
27.

public string GetCustomerCity(int CustomerID)

28.

29.

XDocument doc = XDocument.Load("C:\\Customers.xml");

30.
31.

string companyName =

32.

(from result in doc.Descendants("DocumentElement")

33.

.Descendants("Customer")

34.

where result.Element("CustomerID").Value

35.

== CustomerID.ToString()

36.

select result.Element("City").Value)

37.

.FirstOrDefault<string>();

38.
39.

return companyName;

40.

41.
42.

public int GetCustomerCount()

43.

44.

XDocument doc = XDocument.Load("C:\\Customers.xml");

45.
46.

return doc.Descendants("Customer").Count();

47.

48.
49.

}
}

50. Add a new class to Services folder. Name the class


asOrderService and implement the IOrderService service
contract.
51.
52.

using NorthwindServices.ServiceContracts;

53.

using System.Xml.Linq;

54.
55.

namespace NorthwindServices.Services

56.

57.

[ServiceBehavior(Namespace="http://dotnetmentors.com/services/order")]

58.

public class OrderService : IOrderService

59.

60.

public string GetOrderDate(int orderID)

61.

62.

XDocument doc = XDocument.Load("C:\\Orders.xml");

63.
64.

string orderDate =

65.

(from result in doc.Descendants("DocumentElement")

66.

.Descendants("Orders")

67.

where result.Element("OrderID").Value

68.

== orderID.ToString()

69.

select result.Element("OrderDate").Value)

70.

.FirstOrDefault<string>();

71.
72.
73.

return orderDate;
}

74.
75.

public string GetOrderAmount(int orderID)

76.

77.

XDocument doc = XDocument.Load("C:\\Orders.xml");

78.
79.
80.

string orderTotal =
(from result in doc.Descendants("DocumentElement")

81.

.Descendants("Orders")

82.

where result.Element("OrderID").Value

83.

== orderID.ToString()

84.

select result.Element("OrderTotal").Value)

85.

.FirstOrDefault<string>();

86.
87.

return orderTotal;

88.

89.
90.

public string GetShipCountry(int orderID)

91.

92.

XDocument doc = XDocument.Load("C:\\Orders.xml");

93.
94.

string shipCountry =

95.

(from result in doc.Descendants("DocumentElement")

96.

.Descendants("Orders")

97.

where result.Element("OrderID").Value

98.

== orderID.ToString()

99.

select result.Element("ShipCountry").Value)

100.

.FirstOrDefault<string>();

101.
102.

return shipCountry;

103.
104.

}
}

105. }

Sometimes in service implementation exception occurs. Service


exception needs to be handle by using FaultContract.

7. Service Endpoint
Add Service Endpoints for CustomerService and OrderService.

In real time applications wsHttpBinding is used for http communication


like with web applications and netNamedPipeBinding. is used for the
applications which are running on same machine for example to execute
some jobs, update inventory by back office application.
netNamedPipeBinding gives you the best possible performance if client is
on same machine.
So for CustomerService and OrderService we will use both bindings.
Add below service model configuration to your service library
configuration.

<system.serviceModel>
<services>
<service name="NorthwindServices.Services.CustomerService"
behaviorConfiguration ="ServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:7741/NorthwindServices/Services
/CustomerService" />
<add baseAddress="net.pipe://localhost/Services/CustomerService" />
</baseAddresses>
</host>

<endpoint address ="" binding="wsHttpBinding"


contract="NorthwindServices.ServiceContracts.ICustomerService"
bindingNamespace = "http://dotnetmentors.com/services/customer" />
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange"/>

<endpoint address ="" binding ="netNamedPipeBinding"


contract ="NorthwindServices.ServiceContracts.ICustomerService"
bindingNamespace = "http://dotnetmentors.com/services/customer" />
<endpoint address="mex" binding="mexNamedPipeBinding"
contract="IMetadataExchange"/>

</service>

<service name="NorthwindServices.Services.OrderService"
behaviorConfiguration ="ServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:7741/NorthwindServices/Services
/OrderService" />
<add baseAddress="net.pipe://localhost/Services/OrderService" />
</baseAddresses>
</host>

<endpoint address ="" binding="wsHttpBinding"


contract="NorthwindServices.ServiceContracts.IOrderService"
bindingNamespace = "http://dotnetmentors.com/services/order" />

<endpoint address="mex" binding="mexHttpBinding"


contract="IMetadataExchange"/>

<endpoint address = "" binding ="netNamedPipeBinding"


contract = "NorthwindServices.ServiceContracts.IOrderService"
bindingNamespace = "http://dotnetmentors.com/services/order" />
<endpoint address="mex" binding="mexNamedPipeBinding"
contract="IMetadataExchange"/>

</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name ="ServiceBehavior" >
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>

</serviceBehaviors>
</behaviors>
</system.serviceModel>

8. Hosting Services to IIS and Windows Services


We will be hosting Customer service and Order Service to IIS and
Windows Services.
1.

Hosting WCF Services in IIS 7.0+ Go through the article for


hosting services in IIS WCF service in IIS
In article we have use the ProductService to host. You need to follow
same steps for Customer Service and Order Service.
Create a folder Hosts in your service library application and place
the CustomerServiceHost.svc and OrderServiceHost.svc before
hosting the service in IIS.
While hosting WCF service with netNamedPipeBinding in IIS some
bindings errors might occur. This article hosting wcf service with
netNamedPipeBinding in IIS might help you to sesolve those errors.

2.

Hosting WCF Services in Windows Services Host WCF


CustomerService and OrderService in Windows service.
Make sure <System.ServiceModel> of app.config file of Windows
Services and WCF Service Library are identical.

9. CustomerService and OrderService Clients


Add client application as suggested in previous step. Ideally we should add
have two application to use those services.
Console application to use netNamedPipeBindings and web application to
test wsHttpBinding (you can test both bindings from any application as
long as service and client are on same machine.)
1.

Console Application Add reference to CustomerService and


OrderService. Use below addresses to add service reference.

2.
3.

net.pipe://localhost/Services/CustomerService

4.
5.

net.pipe://localhost/Services/OrderService

6.

When you add service you will have client endpoint in your console
applications app.config. You will have both netNamedPipeBinding
and wsHttpBinding endpoint in your client app.config.
Add below code to client application

using NorthwindBackOffice.CustomerServiceRef;
using NorthwindBackOffice.OrderServiceRef;

namespace NorthwindBackOffice
{
class Program
{
static void Main(string[] args)
{
ShowCustomerDetails();
Console.WriteLine();
ShowOrderDetails();
Console.Read();
}

private static void ShowCustomerDetails()


{
string customerCity = string.Empty;
string customerName = string.Empty;
int customerCount = 0;

using (CustomerServiceClient client =


new CustomerServiceClient("NetNamedPipeBinding_ICustomerService"))
{
customerCity = client.GetCustomerCity(2);
customerName = client.GetCustomerName(2);
customerCount = client.GetCustomerCount();
}

Console.WriteLine("******* Customer Data **************");


Console.WriteLine("Customer Name : " + customerName);
Console.WriteLine("Customer City : " + customerCity);
Console.WriteLine("Total customer count : "
+ customerCount.ToString());
}

private static void ShowOrderDetails()


{
string orderAmount = string.Empty;
string orderDate = string.Empty;
string orderShip = string.Empty;

using (OrderServiceClient client =


new OrderServiceClient("NetNamedPipeBinding_IOrderService"))
{
orderAmount = client.GetOrderAmount(10250);
orderDate = client.GetOrderDate(10250);
orderShip = client.GetShipCountry(10250);
}

Console.WriteLine("******* Order Data **************");


Console.WriteLine("Order Amount : " + orderAmount);
Console.WriteLine("Order Date : " + orderDate);

Console.WriteLine("Ship Country : " + orderShip);


}
}
}

Notice that we have mentioned binding name while creating the


instance of service because two endpoints are available for one
service with different bindings.
7.

8.

WebApplication as client for WCF services Add a web


application to solution and add service reference using below
address.
http://localhost:7741/NorthwindServices/Services/CustomerService

9.
10.

http://localhost:7741/NorthwindServices/Services/OrderService

Download source code.

How to host wcf service in IIS 7 or 7.5


This article will give you brief description about required steps to host your wcf service in IIS and test
it using console application.

For creating and hosting WCF service in IIS follow below steps.

1. Create WCF service


Create a new service using Create new WCF service library and test using
WCFTestClient

2. Add Service Host


Add service host for hosting Product Service by right clicking on Project
from solution explorer. Name the service host as ProductServiceHost.svc

3. ServiceHost tag
Add below service host tag to ProductServiceHost.svc. Give fully qualified
name of service to ServiceHost attribute.

<%@ ServiceHost Service="NorthwindServices.ProductService" %>

4. Create Web Site in IIS


Open IIS manager by clicking Windows start -> Run -> enter inetmgr ->
click ok
If IIS is not installed on your machine click here to install.
Go to IIS manager and right click on sites and select Add Web site.

Enter details as shown in below picture


o

Enter site name as NorthwindServices

Change the application pool to ASP.net V4.0

o
o

Select the physical path of folder containing


ProductServiceHost.svc
Enter port number on you wish to host service.

5. Publish Services
Go to your service application and right click on service project and select
publish.

Enter target location as http://localhost:7741/

6. Test the WSDL


Open your browser and enter
http://localhost:7741/ProductServiceHost.svc. You will see the link for
WSDL.

7. Add Client Application


Now add console application to solution. Name it as NorthwindApp.

8. Add Service Reference


Add service reference to NorthwindApp by right click on NorthwindApp
project and click on Add Service Reference. Below window should appear.
Enter the address of service endpoint which you have added in service
app.config.

Enter ProductServiceRef for Namespace and click on OK. Service


reference is added to your client application.

Check Client application's App.config, it should have service endpoint and


client details.

9. Client Implementation
Service reference is now available for Northwind. We can call service
operations. Add the below code to NorthwindApp -> Program.cs file.

class Program
{
static void Main(string[] args)
{
ShowOperations();
}

private static void ShowOperations()


{
ConsoleKeyInfo cki;

do
{
Console.WriteLine();
Console.WriteLine("Enter Product ID or press Esc to quit : ");
cki = Console.ReadKey();
if (!char.IsNumber(cki.KeyChar))
{
Console.WriteLine(" Invalid number");
}
else
{
Int32 number;
if (Int32.TryParse(cki.KeyChar.ToString(), out number))
{
Console.WriteLine();
GetProductName(number);
GetProductQty(number);
GetCategoryName(number);
}
else
{
Console.WriteLine("Unable to parse input");
}
}
} while (cki.Key != ConsoleKey.Escape);

Console.Read();
}

private static void GetProductName(int ProductID)


{
ProductsClient client = new ProductsClient();
string ProductName = client.GetProductName(ProductID);

Console.WriteLine(string.Format("Product name {0} for Product ID {1}",


ProductName, ProductID));
}

private static void GetProductQty(int ProductID)


{
ProductsClient client = new ProductsClient();
int ProductQty = client.GetProductQty(ProductID);
Console.WriteLine(string.Format("Product qty {0} for Product ID {1}",
ProductQty, ProductID));
}

private static void GetCategoryName(int ProductID)


{
ProductsClient client = new ProductsClient();
string CategoryName = client.GetCategoryName(ProductID);
Console.WriteLine(string.Format("Category name {0} for Product ID {1}",
CategoryName, ProductID));
}
}

See more details about Hosting WCF service in IIS with SSL and Transport
Security
Download source code

Example for hosting WCF service in


windows service.
This article demonstrates the required steps to host your WCF service in Windows Service and
consume it in console application.
Hosting WCF service to Windows service gives you following benefits.

1.

Service will be automatically start whenever the hosting computer start. Service can be
manually start, stop or restart.

2.

Service will always be activated and available for clients. No need for runtime activation.

3.

Windows Administrators already knows managing Windows services.

4.

Provides extra layer of security through windows identity.

5.

Gives better performance than service hosted in IIS.

6.

Gives you flexibility to choose any bindings.

Host WCF Product Service to windows Service


1. Create a WCF Service library
Create a new WCF Service library with help of Create new WCF service
library and test using WCFTestClient

2. Add Windows service application for hosting


Add new windows service application by right click on solution and select
new project -> windows from installed template -> Windows Service.
Name the project as NorthwindHosts.

3. Add Product Service Host


Add new class to NorthwindHosts project name it as ProductServiceHost.
You can mark it as internal as it will be refered only by the
NorthwindHosts assembly. Add a reference to NorthwindServices or your
WCF service and System.ServiceModel.
Create object of ServiceHost and write methods for service start and stop
events.

namespace NorthwindHost
{
internal class ProductServiceHost

{
static ServiceHost serviceHost = null;
public ProductServiceHost()
{

internal static void Start()


{
if (serviceHost != null)
{
serviceHost.Close();
}

//Create a ServiceHost for the ProductService type


//and provide base address.
serviceHost =new ServiceHost(typeof(ProductService));

//Open the ServiceHostBase to create listeners


//and start listening for messages.
serviceHost.Open();
}

internal static void Stop()


{
if (serviceHost != null)
{
serviceHost.Close();
serviceHost = null;
}
}
}
}

4. Windows Service Class


Add a new windows service class to NorthwindHost by right clicking on
project -> Add -> New Item -> Select Windows Service from template ->
name it as ServiceHosts
Right click on newly created ServiceHosts.cs and select view code.
ServiceHosts.cs is inherited by ServiceBase. Override the OnStart and
OnStop methods to start and stop ProductServiceHost.

namespace NorthwindHost
{
public partial class ServiceHosts : ServiceBase
{
public ServiceHosts()
{
InitializeComponent();
ServiceName = "Northwind Services";
}

protected override void OnStart(string[] args)


{
ProductServiceHost.Start();
}

protected override void OnStop()


{
ProductServiceHost.Stop();
}
}
}

5. Run ServiceHosts
Open Program.cs from NorthwindHost windows service application and
run the ServiceHosts.

namespace NorthwindHost
{
static class Program
{
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new ServiceHosts()
};
ServiceBase.Run(ServicesToRun);
}
}
}

6. Add Installer
Add Installer class to NorthwindHost windows service application by right
click on NorthwindHost -> select Add -> New Item -> select Installer.cs
from Visual C# templates.
Name the newly created Installer.cs as NorthwindInstaller.cs
Right click NorthwindInstaller from solution explorer and select view
code.
Add reference to System.ServiceProcess and add below code to
NorthwindInstaller constructor.

namespace NorthwindHost
{
[RunInstaller(true)]
public partial class ProjectInstaller
: System.Configuration.Install.Installer
{
private ServiceProcessInstaller process;
private ServiceInstaller service;
public ProjectInstaller()
{
process = new ServiceProcessInstaller();
process.Account = ServiceAccount.LocalSystem;
service = new ServiceInstaller();
service.StartType = ServiceStartMode.Automatic;
service.ServiceName = "Northwind Servces";
service.Description = "Northwind Servces";
Installers.Add(process);
Installers.Add(service);
}
}
}

7. Config settings
Copy <system.serviceModel> settings from your NorthwindServices WCF
service and paste it in NorthwindHost windows service's app.config file
under <configuration> tag.
With this your service is ready for install.

8. Northwind WCF service to Windows services


Click on Windows Start button -> Right click on Visual Studio Command
Prompt 2010 -> Run as Administrator

Make a CD command till your debug folder of NorthwindHosts Windows


Service application and execute InstallUtil NorthwindHost.exe

9. Start Northwind windows Service

Go to Services by clicking Windows Start button -> Run ->


EnterServices.msc . In Windows services application
locate Northwind Services and start the service by right clicking it.
If any error comes while starting service check the errors in windows
event log.
Now your service is ready to consume.
Download Source Code
Understand PerSession Behavior in WCF Services
This article helps you to understand PerSession Behavior in WCF Services, how to implement
PerSession behavior and understand difference between PerCall and PerSession WCF services.

What happens when WCF service configured as Per


Session ?
When client creates a new proxy of WCF service configured
as InstanceContextMode=InstanceContextMode.PerSession, WCF service creates a
dedicated instance for particular client proxy and handle all subsequent calls through this instance
until client closes proxy. Each private session uniquely binds a proxy to particular instance. Note that
the client session has one service instance per proxy. If the client creates another proxy to the same
or a different service endpoint, then new proxy will have different dedicated instance.

As each instance maintains session in service memory, this behavior creates


scalability and transaction issues like classic client-server model. With normal
infrastrucre it is difficult to handle more than a dozen ongoing calls due to cost
associated with each dedicated instance.
WCF supports three kind of behavior - PerCall, PerSession and Single. When
you use bindings like wsHttpBinding which support reliable session,
PerSession is default behavior. For more info on WCF service behavior seewcf
service instance management by InstanceContextMode.

Implementing PerSession service Behavior

Create WCF Service for PerSession Behavior


Create a new WCF service library and client applications as suggested increate
WCF service with PerCall Service Behavior. and understand how it works for
PerCall behavior.
We will make some modification in WCF Service library to work it as
PerSession.
You may give different names to projects.

Configure WCF Service for PerSession Behavior


Assuming that you have created a WCF Service Library and client application
as suggested in previous step or download code files here. And hosted this
WCF Service in IIS.
Open ProductService file from PerSessionWCFService WCF Service
Library application. Modify ServiceBehavior attribute to configure
PerSession.
Your code will look like

[ServiceBehavior(Name = "ProductService",
Namespace = "http://dotnetmentors.com/productservice",
InstanceContextMode = InstanceContextMode.PerSession)]

public class ProductService : IProductService


{
public void SetProductQty(int qty)
{
this.ProductQty = qty;
}

public int GetProductQty()


{
return this.ProductQty;
}

private int ProductQty


{
get;
set;
}
}

Note that we have changed InstanceContextMode property and set it as


PerSession. Even if you removed setting for InstanceContextMode property
the default value PerSession will be applied as you are using binding with
reliable session.

Update Service Reference


You have configured service as PerSession, now build service library, publish
and host it in IIS.
Open client application and update existing Service Reference by right click
on ProductServiceRef under Service References of client application.
Select Update Service Reference

Client application for PerSession WCF Service


Open client application -> Program.cs file. Add code suggested in below
descriptions to main method of Program.cs file.

ProductServiceRef.ProductServiceClient client
= new ProductServiceRef.ProductServiceClient();

It creates a new client proxy for Product Service. WCF service will create new
dedicated instance to handle this proxy. The data which is manipulated by this
instace will be saved in memory for future reference. All request will be handle
by this instance untill you call client.close();

client.SetProductQty(10);
Console.WriteLine(string.Format
("Current Product Qty: {0}", client.GetProductQty()));

client.SetProductQty(20);
Console.WriteLine(string.Format
("Current Product Qty: {0}", client.GetProductQty()));
Console.WriteLine(string.Format
("Current Product Qty: {0}", client.GetProductQty()));

client.Close();

First line is calling OperationContract SetProductQty which takes input


value as 10. At service side when this operation get called it save the value in
private property ProductQty which is avilable for next calls.
Second line of code block calls OperationContract GetProductQty, service
returns value which is saved in property ProductQty. In this case it returns
value as 10. As this is PerSession behavior wcf service saved the value 10 to
ProductQty. If this was PerCall service behavior you would have got 0 (integer
default) for each read call.
Third line of code block again call operation to set value as 20. Next two lines
read values from ProductQty and get it as 20.
The reason behind getting value as 20 for second read call is, the value of
ProductQty as 20 will be retain as long as you do not call client.close() to close
proxy.
Next line closes the current client proxy.

client = new ProductServiceRef.ProductServiceClient();


Console.WriteLine(string.Format
("Current Product Qty: {0}", client.GetProductQty()));

Now you assign new service instance to client object and call operation
contract to read value of ProductQty however you haven't set the value and
previous proxy is closed you will be getting value as 0(integer default).
Your entire code block will look like this.

namespace ClientApp
{
class Program
{

static void Main(string[] args)


{
ProductServiceRef.ProductServiceClient client
= new ProductServiceRef.ProductServiceClient();

client.SetProductQty(10);
Console.WriteLine(string.Format
("Current Product Qty: {0}", client.GetProductQty()));

client.SetProductQty(20);
Console.WriteLine(string.Format
("Current Product Qty: {0}", client.GetProductQty()));
Console.WriteLine(string.Format
("Current Product Qty: {0}", client.GetProductQty()));

client.Close();

client = new ProductServiceRef.ProductServiceClient();


Console.WriteLine(string.Format
("Current Product Qty: {0}", client.GetProductQty()));
client.Close();

Console.Read();
}
}
}

Download source code.

Understand How Per Call Service Instance


mode works in WCF

This article helps you to understand how per call wcf service works and how its instances get created.
This article will also go through a tutorial for implementing and notice execution of Per Call WCF
Service.

What happens in Per Call Service mode?


A WCF service configured as InstanceContextMode.PerCall will create a dedicated instance for
each request irrespective of existing or new client. It does not save any client data in service memory.
Once service returns response to client, instance get disposed.

When and why InstanceContextMode.PerCall

If your service needs to be stateless and scalable.

Your service must have light weight or none initialization execution.

PerCall services are single threaded.

PerCall services are highly scalable. Server crash affects to only current
ongoing instance and its execution, next calls will be routed to another
server.

PerCall services are less expensive than PerSession services as only


those objects will be in service memory for whose client call is in process.

For brief understanding go through WCF instance management using


InstanceContextMode property.
Below picture describes how PerCall instantiation happens

Implementing PerCall service


Create New WCF Service Library
Create a new WCF Service Library by opening your visual studio -> click on
File -> New -> Project -> WCF (from installed template) -> WCF Service
Library.
Name it as PerCallService and click Ok.

Add IProductService WCF ServiceContract


Add new WCF ServiceContract by right click on PerCallService service
library project and click on Add -> New Item -> interface.
Name it as IProductService and click Ok.
Add below code with OperationContracts for IProductService

using System.ServiceModel;

namespace PerCallService
{
[ServiceContract(Name = "ProductService",
Namespace = "http://northwind.com/productservice")]
public interface IProductService
{
[OperationContract]
void SetProductQty(int qty);

[OperationContract]
int GetProductQty();
}
}

Implement IProductService with PerCall


InstanceContextMode
In this step we will implement IProductService service contract created in
previous step. Add new class by right click on PerCallService service library
project and select on Add -> class.
Name it as ProductService and click Ok.
Add below code which implement OperationContract of IProductService.

using System.ServiceModel;

namespace PerCallService
{
[ServiceBehavior(Name = "ProductService",
Namespace = "http://northwind.com/productservice",

InstanceContextMode= InstanceContextMode.PerCall)]
public class ProductService : IProductService
{
public void SetProductQty(int qty)
{
this.ProductQty = qty;
}

public int GetProductQty()


{
return this.ProductQty;
}

private int ProductQty


{
get;
set;
}
}
}

We added one private property ProductQty which is used for reading and
writing value for ProductQty.
We implemented OperationContract SetProductQty which set value of
ProductQty given by service client.
We implemented OperationContract GetProductQty which returns value of
ProductQty.
In ServiceBehavior attribute we marked service as PerCall.

Add ServiceHost for ProductService

Add ServiceHost file by right click on PerCallService service library project


and select on Add -> New Item -> WCF Service or Text File -> name it
asProductServiceHost.svc.
Add below ServiceHost details to ProductServiceHost.svc.

<%@ ServiceHost Service="PerCallService.ProductService" %>

Configure WCF ProductService Endpoint


Open App.Config from solution explorer. Remove existing Service Endpoints
which points to default Service1.
Add below service details which points to new ProductService.

<service name="PerCallService.ProductService">
<host>
<baseAddresses>
<add baseAddress =
"http://localhost:7741/PerCallService/ProductService" />
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding"
contract="PerCallService.IProductService"
bindingNamespace ="http://northwind.com/productservice" >
</endpoint>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>

Host WCF ProductService


Host ProductService in IIS, check how to host WCF service in IIS or
inWindows Service

Client application for PerCall WCF service


Create a new console application which will work as client for ProductService.
Click on Solution Explorer -> Right click on Solution -> Add -> New Project ->
Console Application
Name it as PerCallServiceClient and click Ok.
Add Service Reference to ProductService by right click on References
(PerCallServiceClient project) -> Select Add Service Reference -> In Add
Service Reference dialog box
enterhttp://localhost:7741/ProductServiceHost.svc -> give namespace
asProductServiceRef.
Open Program.cs file of PerCallServiceClient console application. Add below
code in main method.

static void Main(string[] args)


{
ProductServiceRef.ProductServiceClient client
= new ProductServiceRef.ProductServiceClient();
client.SetProductQty(10);
Console.WriteLine(client.GetProductQty());
Console.Read();
}

We called SetProductQty service operation first to set ProductQty as 10.


However when we call GetProductQty we get as 0, as 10 is not saved in
physical memory and SessionMode is set to PerCall so service won't manintain
any state data between client calls.

Now open ProductService wcf service from Service Library and


changeServiceBehavior and remove InstanceContextMode. As we are
usingwsHttpBinding which supports reliable sessions PerSession would be
default value for InstanceContextMode.
Your ServiceBehavior should look like

[ServiceBehavior(Name = "ProductService",
Namespace = "http://northwind.com/productservice")]
public class ProductService :
IProductService
{
// implementation of operation contract.
}

Build service, publish it again, update service reference for client application
and execute client application. You will see the ProductQty as 10. As service is
PerSession, service maintain object state for multiple calls made from same
proxy.

Download source code.

Creating dynamic proxy using WCF


ChannelFactory
This article helps you to generate dynamic wcf service proxy using ChannelFactory. This will also
describes what is ChannelFactory, difference between ChannelFactory and Proxy, and when to use
proxy or ChannelFactory.

What is WCF ChannelFactory


ChannelFactory enables you to dynamically creating a proxy object based on the Service Contract
alone. You do not require to explicitly generating a proxy class or manually define. This is helpful in
scenario where your service address changes frequently or DataContract changes to newer version
and as a client you have lot of references to those services. So after changes happens at service side,
client must update proxy.

Difference between ChannelFactory and Proxy


Proxy

ChannelFactory

You need service URL and metadata


endpoint should be exposed from service
side.

You have to have direct access to


ServiceContracts, DataContracts,
MessageContracts.

Simple to use as you get required


configuration through proxy.

Comparing with Proxy, creatin


ChannelFactory is complex as you need
to configure at code level.

You can create WCF service proxy


using WSDL or by adding Service
Reference in Visual Studio Solution
explorer

You can create ChannelFactory by adding


reference to assembly where required
ServiceContract,DataContract,
MessageContracts resides.

Proxy has below restrications

ChannelFactory has below restrictions

1. Properties needs to have getter and

Proxy

ChannelFactory

setter, you can not have read only


or write only properties.
2. You can not expose class
constructors.
3. Only ServiceContract can be
expose, you can not expose any
other method than
ServiceContracts
OperationContract.

1. It requires direct access to the


ServiceContracts, DataContracts
and any other dependent methods.

When to use Proxy?


Creating proxy by Visual Studio or SvcUtil.exe tool will update client
configuration file to make necessary changes. If you know your services are
generic enough and services should be loosely coupled you should use Proxy.
As it depends on Service schema, any changes to existing service schema force
client to rebuild.

When to use ChannelFactory


In some scenario services needs to be tightly coupled and needs to share not
only ServiceContract but also other dependant methods, contracts etc. When
you do not want to force client to change or rebuild on frequent service
schema, you have to share utility methods, different internal services,
contracts along with ServiceContract then you should use ChannelFactory.
Below details explains about how to use ChannelFactory to create dynamic
proxy

Dynamically creating WCF Proxy using ChannelFactory

Create Shared WCF Contracts


described in introduction, for using ChannelFactory you need to have access to
ServiceContract and related DataContract.
Go through Share WCF Service Contracts assembly which helps you to create a
shared library which includes ServiceConracts and DataContracts which can
be shared by WCF Services and its clients.

WCF Client with ChannelFactory


In this step we will create a WCF client which uses ChannelFactory objects to
call WCF Services.
Open NorthwindDynamicProxy solution which is created in previous step.
Add New Console Application to solution by right click on solution
NorthwindDynamicProxy -> New Project -> Console Application. Name it
asNorthwindClient and click Ok.
Now Add Reference to NorthwindContracts assembly to NorthwindClient
console application so that you will be able to access required contracts.

CategoryServiceClient
In shared assembly we have CategoryService contract which we will
implement using ChannelFactory.
Add new class to NorthwindClient console application and name it
asCategoryServiceClient.
CategoryService has two method
1. GetCategoryName which returns category name based on given category
ID. Below is implementation of this GetCategoryName.

public static string GetCategoryName(int categoryID)


{
string categoryName = string.Empty;
WSHttpBinding myBinding = new WSHttpBinding();

EndpointAddress myEndpoint = new


EndpointAddress("http://localhost:7741/CategoryServiceHost.svc");
ChannelFactory<ICategoryService> myChannelFactory =
new ChannelFactory<ICategoryService>(myBinding, myEndpoint);

ICategoryService instance = myChannelFactory.CreateChannel();

categoryName = instance.GetCategoryName(categoryID);

myChannelFactory.Close();

return categoryName;
}

2. GetCategoryDetails which returns category details as Category


DataContract. Below is GetCategoryDetails of this method.

public static Category GetCategoryDetails(int categoryID)


{
Category category = new Category();

WSHttpBinding myBinding = new WSHttpBinding();


EndpointAddress myEndpoint = new
EndpointAddress("http://localhost:7741/CategoryServiceHost.svc");
ChannelFactory<ICategoryService> myChannelFactory
= new ChannelFactory<ICategoryService>(myBinding, myEndpoint);

ICategoryService instance = myChannelFactory.CreateChannel();

category = instance.GetCategoryDetails(categoryID);

myChannelFactory.Close();

return category;
}

We assume that you have created a WCF service and hosted in IIS as
suggested in first step. In this step we create a declartive endpoint to
CategoryServiceHost.
ChannelFactory<ICategoryService> creates new instance of
CategoryService and ChannelFactory.CreateChannel() returns instance
using which we can call service operations dynamically.

Call to dynamic service proxy class


Open Program.cs file of NorthwindClient console application. From
Program.cs file we will call CategoryServiceClient's methods which calls
CategoryService with dynamic proxy and returns output.
Add below code to Program.cs

using NorthwindContracts.DataContracts;
using NorthwindContracts.ServiceContracts;

namespace NorthwindClient
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(CategoryServiceClient.GetCategoryName(10));

Category category =
CategoryServiceClient.GetCategoryDetails(10);
if (category != null)

{
Console.WriteLine("Category ID " + category.CategoryID);
Console.WriteLine("Category Name: "
+ category.CategoryName);
Console.WriteLine("Category Description:"
+ category.CategoryDescription);
}

Console.Read();
}
}
}

Change existing WCF contracts


In this step we will change Category data contract and will test dependent
clients. Open NorthwindContracts class library project.
Open CategoryDataContract from DataContract folder.
Add below new DataMember.

[DataMember]
public string CategoryURL { get; set; }

Now open NorthwindServices WCF Service Library project


andCategoryService from CategoryServices folder.
Change implementation of GetCategoryDetails method as

public Category GetCategoryDetails(int categoryID)


{

Category category = new Category();


category.CategoryID = 1;
category.CategoryName = "Beverages";
category.CategoryDescription =
"Soft drinks, coffees, teas, beers, and ales";
category.CategoryURL = "http://northwind.com/Beverages";

return category;
}

Notice that we have added CategoryURL in addition to existing


implementation. Now run your client code without changing anything. Client
code should give you same output shown previously. As Proxy is crated
dynamically you do not need to make any changes or rebuild to client code.
Now change client code from Program.cs to display CategoryURL as

Category category = CategoryServiceClient.GetCategoryDetails(10);


if (category != null)
{
Console.WriteLine("Category ID " + category.CategoryID);
Console.WriteLine("Category Name: " + category.CategoryName);
Console.WriteLine("Category Description:" +
category.CategoryDescription);
Console.WriteLine("Category URL: " + category.CategoryURL);
}

Notice that we did not change anything to CategoryServiceClient which


actually creates ChannelFactory and dynamic proxy to services.

Download source code.

How to enable wcf tracing and wcf message


logging
This article describes how to use WCF tracing and message logging with various options. With WCF
tracing from System.Diagnostics you can configure trace source, emit traces, activity tracing and its
propagation.

WCF Tracing:
WCF tracing enables you to diagnose data, fault messages and its analysis. Tracing is better option
than debugging to understand the application's behavior and its flow. Tracing gives you the details of
all application components like fault and code exceptions, system events, operation calls. Depending
on the Switch Value traces will be generated.

WCF tracing is not enabled by default you need to configure it with the switch
value and tracelistener.
Switch Value: Switch value decides what level of trace needs to be
generated. Below default values are available for Switch Value
1.

Off: Tracing is disabled and no trace will be generated.

2.

Critical: Trace will be generated for unhandled exceptions.

3.

Error: Trace will be generated for all exceptions.

4.

5.

Warning: Traces all possible problems that are occurred or possibility


of occurring. Recommended for production environment with
propagateActivity="true"
Information: Only for successful execution of milestones.

6.

Verbose: Tracing more detail of successful execution. Recommended


for debugging purpose.

7.

ActivityTracing: Traces communication across components of entire


application.

8.

All: Traces everything which can be done by above trace levels.

Trace Listener: WCF services and clients add trace data to listeners
configured app.config file. There are couple of predefined trace listeners like
XmlWriterTraceListener which can be used to save trace.
TheinitializeData property must be set to some physical file.

Steps to configure Tracing


1. Create basic WCF service
Go through the article for creating service library Create new WCF service
library and test using WCFTestClient.

2. Host WCF Service library


Host Service as suggested in Hosting WCF service in IIS. or hosting in
Windows service

3. Configure Tracing
Open the app.config file of WCF service library and add the configuration
for system.diagnostics.

<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="Critical,Information,ActivityTracing"
propagateActivity="true">
<listeners>
<add name="messages"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="c:\logs\messages.svclog" />
</listeners>
</source>

</sources>
<trace autoflush="true" />
</system.diagnostics>

In this configuration we are using "Critical,Information,ActivityTracing"


as switch value. This will generate traces for all unhandled exceptions,
successful execution and communication between two components.
XmlWriterTraceListener will create the traces in xml format. The property
value of initializeData will mention the physical location of trace file.
<trace autoflush="true" /> will flush the traces to file automatically.

4. Use of TraceViewer
Execute some of the service operations using client application. The file
messages.svclog must have created under C:\logs folder. Open the file by
using SvcTraceViewer.exe.

Configure Message Logging


Message logging allows you to log entire request and response message to log
files. For enabling message logging you need to use trace
listenerSystem.ServiceModel.MessageLogging and properties
of<messagelogging>
System.ServiceModel.MessageLogging has below attributes :
1.

logEntireMessage: boolean property with default value of false. If set


to true entire message that is message header and body will be logged
other wise only message header will be logged.

2.

logMalformedMessages: boolean property with default value of false


indicates whether to malformed messages needs to be logged.

3.

logMessagesAtServiceLevel: boolean property with default value of


false indicates whether messages get traced at service level.

4.

logMessagesAtTransportLevel: boolean property with default value


of false indicates whether messages gets traced at transport level.

5.

maxMessagesToLog: integer property with default value of 1000.


This property specifies maximum number of messages can be logged.
Malformed messages are not considered for this.

6.

maxSizeOfMessageToLog: integer property with default value of


262144. The value of this property indicates maximum size of message to
log. Messages more than size will not log.

Add below message logging configuration to .config file.

<system.diagnostics>
<sources>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add name="messages"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="c:\logs\northwindservices.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>

<system.serviceModel>
<diagnostics>
<messageLogging
logEntireMessage="false"
logMalformedMessages="true"
logMessagesAtServiceLevel="true"
logMessagesAtTransportLevel="false"
maxMessagesToLog="500"
maxSizeOfMessageToLog="5000"/>
</diagnostics>
</system.serviceModel>

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