Olark Livehelp

Tuesday, February 2, 2010

Basics and sample example of Language Integrated Query –(LINQ to Dataset)

Few Best Feature

Write query against in memory collection other quenchable sources using any . NET Language

Using LINQ to SQL we can directly write Db related queries in the code itself

We can write Data Access Code for XML using LINQ to XML

We can write common data access provider against different data source using LINQ to ENTITIES

We can write reach Queries against data using LINQ to DATASET

Simplicity:

simplify the data access code and maintainability of code

Query data in any .NET Programming Language:

we can write LINQ queries in the programming languages in stead of learning SQL dialect

ex – var employee = from emp in

tblemployee

where dept = 'sales'

select emp

Strongly Typed Object in our Data access code

Query against strongly typed data objects easily. Write data access code in object oriented manner as used in the rest of the application

Productivity

Increase productivity, reduce runtime errors by using strongly typed objects instead of traditional SQL queries

Optimize Development Efforts

Become more productive and optimize the overall development efforts by using the consistent query language for all aspect of the application

Reduce Bugs and Errors

Work with strongly typed CLR Objects that reduce runtime errors in the application, identify query related errors at the compile time and reduce the debugging efforts by using strongly typed objects

Be more productive with the visual studio

Flexibility

Use of consistent LINQ syntax across all data source. Use LINQ with any data source

LINQ to SQL, LINQ to DATASET, LINQ to XML and LINQ to Entities

LINQ Query


LINQ query consist of the Three part of the query operations

  1. Obtain the data source
  2. Create the query
  3. Execute query

    // The Three Parts of a LINQ Query:

// 1. Data source.

int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 };

// 2. Query creation.

// Array implicitly supports the generic IEnumerable<T> interface

// numQuery is an IEnumerable<int>

var numQuery =

from num in numbers

where (num % 2) == 0

select num;

// 3. Query execution.

foreach (int num in numQuery)

{

Console.Write("{0,1} ", num);

}

Developer who writes queries, most visible language integrated part of LINQ is the Query Expression, which is written in the declarative syntax, by using query syntax we can perform complex filtering, ordering and grouping operations on different data sources with minimum code.

Variable in query expression is strongly typed, although in many cases we don't need to provide type explicitly

LINQ queries can be written as Query Syntax and Method syntax

Most queries in the LINQ documentation are written in the query syntax however the CLR does not have any notion for query syntax itself therefore during compilation query expression are converted into something that CLR can understand These methods are called standard query operators, and they have names such as Where, Select, GroupBy, Join, Max, Average, and so on. You can call them directly by using method syntax instead of query syntax.

In general query syntax is preferred over the method syntax coz is is usually more simpler and can understand easily but in fact there is no semantic difference in between the query syntax and the method syntax there are some operation such as number of element that matched the specified condition, maximum value in the data source can be expressed only as the method syntax.

Query Expression syntax and Method syntax LINQ Query


int[] numbers = { 5, 10, 8, 3, 6, 12};

//Query syntax:

IEnumerable<int> numQuery1 =

from num in numbers

where num % 2 == 0

orderby num

select num;

//Method syntax:

IEnumerable<int> numQuery2 = numbers.Where(num => num % 2 == 0).OrderBy(n => n);

foreach (int i in numQuery1)

{

Console.Write(i + " ");

}

Console.WriteLine(System.Environment.NewLine);

foreach (int i in numQuery2)

{

Console.Write(i + " ");

}

// Keep the console open in debug mode.

Console.WriteLine(System.Environment.NewLine);

Console.WriteLine("Press any key to exit");

Console.ReadKey();

/*

Output:

6 8 10 12

6 8 10 12

*/

output from the above two example is same.

To understand the query based syntax is very easy.

Now we will poke up in the Method based syntax

on the right side of the query expression where clause is expressed as the instance method on the numbers object like numbers.Where, here we will find the the where which is not the default method found on array but infact this is the extension method The standard query operators(like Where/Select/SelectMany/Join / and Orderby) are implemented as a new kind of method called extension methods. Extensions methods "extend" an existing type; they can be called as if they were instance methods on the type.

Lambda Expressions

In method syntax conditional expression (num % 2 == 0) is passed as Where(num => num % 2 == 0) This inline expression is called as Lambda Expression

This is the conveient way of writing the code otherwise which will be written in the cumbersome manner as anonymous method, generic expression or expression tree.

The symbaol (=>) read as GOES TO

num on the left side of the operator is the input body of the lambda is just same as the query expression or it can include any other complex logic return value is just expression result.

Query Exceution

Deferred Execution

In LINQ the excutio of query is different than the query itself.we will not receive any data by just creating the query variable.

Each query is not executable until we iterate over the query variable over foreach loop

A query is executed in a foreach statement, and foreach requires IEnumerable or IEnumerable<(Of <(T>)>). Types that support IEnumerable<(Of <(T>)>) or a derived interface such as the generic IQueryable<(Of <(T>)>) are called queryable types.

Because the query variable itself never holds the query results, you can execute it as often as you like. For example, you may have a database that is being updated continually by a separate application. In your application, you could create one query that retrieves the latest data, and you could execute it repeatedly at some interval to retrieve different results every time.

Forcing Immediate Execution

Queries that perform aggregation functions over a range of source elements must first irate through the source elements Queries such as Count, Max, Average, First These execute without the explicit foreach statement bcoz the query itself must use the foreach to return the resulted single value like this

var evenNumQuery =

from num in numbers

where (num % 2) == 0

select num;

int evenNumCount = evenNumQuery.Count();

to force immediate execution of any query and cache its result we can use ToList(TSource) or ToArray(TSource) methods like below

List<int> numQuery2 =

(from num in numbers

where (num % 2) == 0

select num).ToList();


// or like this:

// numQuery3 is still an int[]


var numQuery3 =

(from num in numbers

where (num % 2) == 0

select num).ToArray();

We can also force execution by putting the foreach loop immediately after the query expression. However, by calling ToList or ToArray We can also cache all the data in a single collection object.

Some RnD with LINQ to Dataset. Following example which is the simple empty aspx page to test the normal functionality of the LINQ. This is done as a part of digging the practice carried out by me to test the various simple aspect of the LINQ coding.

Following is the code behind code of the empty aspx page which we can use to test LINQ functionality on the fly along with the few basics mentioned in the c


using System;

using System.Configuration;

using System.Data;

using System.Reflection;

using System.Linq;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml.Linq;

using System.Text;

using System.Collections.Generic;



public partial class _Default : System.Web.UI.Page

{

protected void Page_Load(object sender, EventArgs e)

{

FewBasicsofLinq();

LessThanGreaterThanTest();

DataSet ds = CreateSampleDataset();

SimpleWhereCondition(ds);

LinqtoObjectTest(ds);

FieldTExample(ds);

DelegateLinqTest(ds);

DataRowComparerUniontest(ds);

ShapingQueries(ds);

GropuingResults(ds);

JoinExample(ds);

AsDataViewTestExample(ds);

CopyToDattableTestExample(ds);

}


protected void FewBasicsofLinq()

{

Response.Write("###################################################################################</br>");

Response.Write("1) LINQ queries target IEnumerable<T> sources. The DataSets DataTable and the DataTables DataRowCollection do not implement IEnumerable<DataRow> so these types cannot be used as sources for LINQ query expressions. To work around this issue, an extension method called <b>AsEnumerable</b> was added to the DataTable type. This extension method takes a source DataTable and wraps it in an object of the type EnumerableRowCollection which implements IEnumerable<DataRow>. This allows DataTables to be a source for LINQ query expressions.</br>");

Response.Write("2) In fact, the DataTable.AsEnumerable method turns a given DataTable into a sequence of objects where the element type is DataRow. (see linqtoobject</br>");

Response.Write("3) As a general rule, all access to DataRow column values should be done through the Field<T> method when developing LINQ to DataSet query expressions. This makes the query expression much less error prone and generally provides much cleaner code. </br>");

Response.Write("4) DataSet is an entirely in-memory cache, all LINQ queries against it are translated directly into .NET IL (intermediate language). This is different from LINQ technologies such as LINQ to SQL or LINQ to Entities which require the LINQ query to be translated to the target source's query language, and are therefore limited by what can be translated. As a result, LINQ to DataSet queries can be arbitrarily complex and can contain anything that can be expressed in the host language. </br>");

Response.Write("5) When working with LINQ to DataSet, you should also keep in mind how the LINQ set query operators (Union, Distinct, Intersection, Except) work. These operators all have two overloads, one which takes an IEqualityComparer<T> and one that does not. When calling one of the set query operators where the source(s) is IEnumerable<DataRow>, the set operator implementation will call DataRow.Equals() to compare elements when an IEqualityComparer<DataRow> comparer is not passed in. For developers familiar with the well known relational semantics of set operators, the results will be quite unexpected since the DataRow.Equals method will compare DataRow references and not the underlying values. <b>To support more traditional relational semantics LINQ to DataSet includes a type called DataRowComparer which includes a default DataRow comparer for comparing two DataRows.</b> </br>");


Response.Write("###################################################################################</br>");



}


protected void LessThanGreaterThanTest()

{

int[] no = { 10, 13, 1, 4, 12, 3, 4, 9, 8, 120, 1234 };


var nogreaterthan80 = from n in no

where n > 80

orderby n ascending

select n;


Response.Write("No Greater Than 80 : </br>");

foreach (var number in nogreaterthan80)

{

Response.Write(number + "</br>");

}

Response.Write("###################################################################################</br>");


var nolessthan120 = from n in no

where n < 120

orderby n descending

select n;


Response.Write("No Less Than 120 : </br>");

foreach (var number in nolessthan120)

{

Response.Write(number + "</br>");

}

Response.Write("###################################################################################</br>");

}


protected DataSet CreateSampleDataset()

{


Response.Write("###################################################################################</br>");

DataSet ds = new DataSet("Parks");


DataTable parksDataTable = ds.Tables.Add("National Parks");

parksDataTable.Columns.Add("ID", typeof(int));

parksDataTable.Columns.Add("Name", typeof(string));

parksDataTable.Columns.Add("YearEstablished", typeof(int));

parksDataTable.Columns.Add("Country", typeof(string));

parksDataTable.Columns.Add("Rating", typeof(int));


DataTable countriesDataTable = ds.Tables.Add("Countries");

countriesDataTable.Columns.Add("ID", typeof(int));

countriesDataTable.Columns.Add("Name", typeof(string));

countriesDataTable.Columns.Add("Population", typeof(long));

countriesDataTable.Columns.Add("ContinentID", typeof(int));


DataTable continentsDataTable = ds.Tables.Add("Continents");

continentsDataTable.Columns.Add("ID", typeof(int));

continentsDataTable.Columns.Add("Name", typeof(string));


DataRelation ContinentCountryDataRelation = ds.Relations.Add(

continentsDataTable.Columns["ID"],

countriesDataTable.Columns["ContinentID"]);


continentsDataTable.Rows.Add(

new object[] { 1, "North America" });

continentsDataTable.Rows.Add(

new object[] { 2, "South America" });

continentsDataTable.Rows.Add(

new object[] { 3, "Asia" });


countriesDataTable.Rows.Add(

new object[] { 1, "Canada", 31612000, 1 });

countriesDataTable.Rows.Add(

new object[] { 2, "USA", 302249000, 1 });

countriesDataTable.Rows.Add(

new object[] { 3, "Argentina", 39921833, 2 });

countriesDataTable.Rows.Add(

new object[] { 4, "Japan", 127433000, 3 });

countriesDataTable.Rows.Add(

new object[] { 5, "South Korea", 49024737, 3 });


parksDataTable.Rows.Add(

new object[] { 1, "Jasper", 1907, "Canada", 8 });

parksDataTable.Rows.Add(

new object[] { 2, "Yoho", 1886, "Canada", 7 });

parksDataTable.Rows.Add(

new object[] { 3, "North Cascade", 1968, "USA", 9 });

parksDataTable.Rows.Add(

new object[] { 4, "Lago Puelo", 1971, "Argentina", 8 });

parksDataTable.Rows.Add(

new object[] { 5, "Bandai-Asahi", 1950, "Japan", null });

parksDataTable.Rows.Add(

new object[] { 6, "Saikai", 1955, "Japan", 6 });

parksDataTable.Rows.Add(

new object[] { 7, "Jirisan", 1967, "South Korea", 8 });

Response.Write("<b>Dataset Created !!!!</b><br>");

Response.Write("###################################################################################</br>");

return ds;

}


protected void SimpleWhereCondition(DataSet ds)

{

Response.Write("###################################################################################</br>");

Response.Write("<b>Simple where condition</b><br>");

var wherecountryname = from park in ds.Tables["National Parks"].AsEnumerable()

where (string)park["Country"] == "Japan"

select park;

DumpResults(wherecountryname);

Response.Write("###################################################################################</br>");

}


protected void LinqtoObjectTest(DataSet ds)

{

Response.Write("###################################################################################</br>");

Response.Write("<b>Linq To Object</b><br>");

List<DataRow> list = new List<DataRow>(ds.Tables["Continents"].Rows.Cast<DataRow>());

var querylinqtoobject = from park in list

where (string)park["Name"] == "Asia"

select park;

DumpResults(querylinqtoobject);

Response.Write("###################################################################################</br>");

}


protected void FieldTExample(DataSet ds)

{

Response.Write("###################################################################################</br>");

Response.Write("<b>field<T> Example</b><br>");

var fldtex = from park in ds.Tables["National Parks"].AsEnumerable()

where park.Field<int?>("Rating") > 8

select park;


DumpResults(fldtex);

Response.Write("###################################################################################</br>");

}


//CALLING DELEGATE checkPopulation from linq to dataset queries


protected void DelegateLinqTest(DataSet ds)

{

Response.Write("###################################################################################</br>");

Response.Write("<b>Delgate Linq Example</b><br>");

Func<long, bool> checkPopulation = delegate(long i)

{return i < 100000000;};


var delgatelinqtest = from country in

ds.Tables["Countries"].AsEnumerable()

where country.Field<string>("Name").Length > 3 &&

!country.HasErrors &&

checkPopulation(

country.Field<long>("Population"))

select country;

DumpResults(delgatelinqtest);

Response.Write("###################################################################################</br>");


}


protected void DataRowComparerUniontest(DataSet ds)

{

Response.Write("###################################################################################</br>");

Response.Write("<b>Data Row comparer Union Test</b><br>");

var source1 = from park in ds.Tables["National Parks"].AsEnumerable()

where park.Field<int?>("Rating") < 8

select park;


var source2 = from park in ds.Tables["National Parks"].AsEnumerable()

where park.Field<int>("YearEstablished") > 1960

select park;


var unionResults = source1.Union(source2, DataRowComparer.Default);

DumpResults(unionResults);

Response.Write("###################################################################################</br>");

//use DataRowCompared for explanation view the head topic no 5)

}



protected void ShapingQueries(DataSet ds)

{

Response.Write("###################################################################################</br>");

Response.Write("<b>Shaping Queries</b><br>");


var shapingqueries = from park in ds.Tables["National Parks"].AsEnumerable()

orderby park.Field<int>("YearEstablished")

select new

{

ParkName = park.Field<string>("Name"),

Established =

park.Field<int>("YearEstablished")

};


DumpResults(shapingqueries);

Response.Write("###################################################################################</br>");

//use DataRowCompared for explanation view the head topic no 5)

}



protected void GropuingResults(DataSet ds)

{

Response.Write("###################################################################################</br>");

Response.Write("<b>Grouping Results</b><br>");


var groupingrslt = from park in ds.Tables["National Parks"].AsEnumerable()

group park by park.Field<string>("Country") into g

select new { Country = g.Key, Count = g.Count() };


DumpResults(groupingrslt);

Response.Write("###################################################################################</br>");

//use DataRowCompared for explanation view the head topic no 5)

}


protected void JoinExample(DataSet ds)

{

//Response.Write("###################################################################################</br>");

//Response.Write("<b>Join Example Results</b><br>");


//var joinexampl = from park in ds.Tables["National Parks"].AsEnumerable()

// join country in ds.Tables["Countries"].AsEnumerable()

// on park.Field<string>("Country") equals

// country.Field<string>("Name")

// select new

// {

// ParkName = park.Field<string>("Name"),

// Country = country.Field<string>("Name"),

// Continent = country.

// GetParentRow(

// ContinentCountryDataRelation)

// .Field<string>("Name")

// };


//DumpResults(joinexampl);

//Response.Write("###################################################################################</br>");

//use DataRowCompared for explanation view the head topic no 5)

}



protected void AsDataViewTestExample(DataSet ds)

{

Response.Write("###################################################################################</br>");

Response.Write("<b>AsDataViewTest Example Results</b><br>");

DataView dataView = (from park in

ds.Tables["National Parks"].AsEnumerable()

where park.Field<int?>("YearEstablished") < 1960

orderby park.Field<string>("Country")

select park).AsDataView();


DataRowView[] drv = dataView.FindRows("Canada");


foreach (object obj in drv.Cast<Object>())

{

Response.Write(obj);

}


Response.Write("###################################################################################</br>");

//use DataRowCompared for explanation view the head topic no 5)

}


protected void CopyToDattableTestExample(DataSet ds)

{

Response.Write("###################################################################################</br>");

Response.Write("<b>CopyToDattableTest Example Results</b><br>");


DataTable newParksTable = (from park in

ds.Tables["National Parks"].AsEnumerable()

where park.Field<int?>("YearEstablished") < 1960

orderby park.Field<int?>("YearEstablished")

select park).CopyToDataTable();



Response.Write("###################################################################################</br>");

//use DataRowCompared for explanation view the head topic no 5)

}





//Method to Display the query result

public void DumpResults<T>(IEnumerable<T> source)

{

StringBuilder sb = new StringBuilder();

if (typeof(T) == typeof(DataRow))

{

foreach (DataRow dr in source.Cast<DataRow>())

{

foreach (object o in dr.ItemArray)

{

sb.Append((o == DBNull.Value ? "DBNull" : o) + " ");

}

sb.Append("<br>");

}

}

else

{

foreach (T t in source)

{

foreach (PropertyInfo pi in typeof(T).GetProperties())

{

object o = pi.GetValue(t, null);

sb.Append(o + " ");

}

sb.Append("<br>");

}

}

Response.Write(sb.ToString());

}


}


LAMBDA EXPRESSION


Lambda expression is the anonymous function which can contain the expression and statement can can be used to create delegate and expression tree


Lambda expression use the Lambda Operator(=>) read as GOES TO .


The left side of the lambda expression specifies the input if any and right side holds the expression or statement block. The lambda expression p => p * p read as "p goes to p time p" this expression can be assigned as delegate types as follows


delegate int del(int i);

static void Main(string[] args)

{

del myDelegate = p => p * p;

int j = myDelegate(5); //j = 25

}


Lambdas are not allowed on the left side of the is or as operator.


All restrictions that apply to anonymous methods also apply to lambda expressions.


Expression Lambadas


A lambda expression with an expression on the right hand side is called expression lambda. Expression lambda are used extensively in the construction of the expression trees


An expression lambda returns the expression result and takes the following basic form


(input parameter) => expression


parenthesis are optional if the input parameter is single otherwise it is compulsory. Two or more parameter enclosed in the parenthesis separated by comma


(x, y) => x == y


sometime it is difficult or impossible for compiler to infer the input data type, in that case we can specify the data type explicitly as follows


(int x, string s) => s.Length > x


even we can specify zero input parameter with empty parenthesis like as


() => SomeMethod()


Statement Lambda


statement lambda resembles the expression lambda except that the statement is enclosed in the parenthesis


(input parameter ) => (statement;)


body of the statement lambda can consist of any number of lines but practically they are not more than two three lines


delegate void TestDelegate(string s);


TestDelegate myDel = n => { string s = n + " " + "World"; Console.WriteLine(s); };

myDel("Hello");


Statement lambdas, like anonymous methods, cannot be used to create expression trees.

Sunday, January 17, 2010

WCF Basics / fundamentals how to

Overview

Windows Communication Foundation takes combines many existing communication technologies, such as Web Services, Windows Remoting, Microsoft Message Queuing (MSMQ), and abstracts them into a single technology (WCF). In most cases, this simplifies the way WE communicate with other applications. It also allows us to communicate with other applications without being coupled to a specific technology. Therefore, we could use Web Services over SOAP to begin with, and later move to remote procedure calls (RPC) without changing our code

The Basics

Conceptual Overview

Windows Communication Foundation (WCF) is a runtime and a set of APIs for creating systems that send messages between services and clients.

The same infrastructure and APIs are used to create applications that communicate with other applications on the same computer system or on a system that resides in another company and is accessed over the Internet.

Messaging and Endpoints

WCF is based on the notion of message-based communication, and anything that can be modeled as a message (for example, an HTTP request or an MSMQ message) can be represented in a uniform way in the programming model. This enables a unified API across different transport mechanisms.

The model distinguishes between clients, which are applications that initiate communication, and services, which are applications that wait for clients to communicate with them and respond to that communication. A single application can act as both a client and a service.

Messages are sent between endpoints. Endpoints are places where messages are sent or received (or both), and they define all the information required for the message exchange. A service exposes one or more application endpoints (as well as zero or more infrastructure endpoints), and the client generates an endpoint that is compatible with one of the service's endpoints.

An endpoint describes in a standard-based way where messages should be sent, how they should be sent, and what the messages should look like. A service can expose this information as metadata that clients can process to generate appropriate WCF clients and communication stacks.

Communication Protocols

One required element of the communication stack is the transport protocol. Messages can be sent over intranets and the Internet using common transports, such as HTTP and TCP. Other transports are included that support communication with Microsoft Message Queuing (MSMQ) applications and nodes on a Peer Networking mesh. More transport mechanisms can be added using the built-in extension points of WCF.

Another required element in the communication stack is the encoding that specifies how any given message is formatted. WCF provides the following encodings:

  • Text encoding, an interoperable encoding.
  • Message Transmission Optimization Mechanism (MTOM) encoding, which is an interoperable way for efficiently sending unstructured binary data to and from a service.
  • Binary encoding for efficient transfer.

More encoding mechanisms (for example, a compression encoding) can be added using the built-in extension points of WCF.

Message Patterns

WCF supports several messaging patterns, including request-reply, one-way, and duplex communication. Different transports support different messaging patterns, and thus affect the types of interactions that they support. The WCF APIs and runtime also help you to send messages securely and reliably.

WCF Terms

Other concepts and terms used in the WCF documentation include the following.

message

A message is a self-contained unit of data that may consist of several parts, including a body and headers.

service

A service is a construct that exposes one or more endpoints, with each endpoint exposing one or more service operations.

endpoint

An endpoint is a construct at which messages are sent or received (or both). It comprises a location (an address) that defines where messages can be sent, a specification of the communication mechanism (a binding) that described how messages should be sent, and a definition for a set of messages that can be sent or received (or both) at that location (a service contract) that describes what message can be sent.

An WCF service is exposed to the world as a collection of endpoints.

application endpoint

An endpoint exposed by the application and that corresponds to a service contract implemented by the application.

infrastructure endpoint

An endpoint that is exposed by the infrastructure to facilitate functionality that is needed or provided by the service that does not relate to a service contract. For example, a service might have an infrastructure endpoint that provides metadata information.

address

An address specifies the location where messages are received. It is specified as a Uniform Resource Identifier (URI). The URI schema part names the transport mechanism to use to reach the address, such as HTTP and TCP. The hierarchical part of the URI contains a unique location whose format is dependent on the transport mechanism.

The endpoint address enables you to create unique endpoint addresses for each endpoint in a service, or under certain conditions share an address across endpoints. The following example shows an address using the HTTPS protocol with a non-default port:


HTTPS://prawinway:8005/ServiceModelSamples/CalculatorService

binding

A binding defines how an endpoint communicates to the world. It is constructed of a set of components called binding elements that "stack" one on top of the other to create the communication infrastructure. At the very least, a binding defines the transport (such as HTTP or TCP) and the encoding being used (such as text or binary). A binding can contain binding elements that specify details like the security mechanisms used to secure messages, or the message pattern used by an endpoint. For more information, see Configuring Windows Communication Foundation Services.

binding element

A binding element represents a particular piece of the binding, such as a transport, an encoding, an implementation of an infrastructure-level protocol (such as WS-ReliableMessaging), or any other component of the communication stack.

behaviors

A behavior is a component that controls various run-time aspects of a service, an endpoint, a particular operation, or a client. Behaviors are grouped according to scope: common behaviors affect all endpoints globally, service behaviors affect only service-related aspects, endpoint behaviors affect only endpoint-related properties, and operation-level behaviors affect particular operations. For example, one service behavior is throttling, which specifies how a service reacts when an excess of messages threaten to overwhelm its handling capabilities. An endpoint behavior, on the other hand, controls only aspects relevant to endpoints, such as how and where to find a security credential.

system-provided bindings

WCF includes a number of system-provided bindings. These are collections of binding elements that are optimized for specific scenarios. For example, the WSHttpBinding is designed for interoperability with services that implement various WS-* specifications. These predefined bindings save time by presenting only those options that can be correctly applied to the specific scenario. If a predefined binding does not meet your requirements, you can create your own custom binding.

configuration versus coding

Control of an application can be done either through coding, through configuration, or through a combination of both. Configuration has the advantage of allowing someone other than the developer (for example, a network administrator) to set client and service parameters after the code is written and without having to recompile. Configuration not only enables you to set values like endpoint addresses, but also allows further control by enabling you to add endpoints, bindings, and behaviors. Coding allows the developer to retain strict control over all components of the service or client, and any settings done through the configuration can be inspected and if needed overridden by the code.

service operation

A service operation is a procedure defined in a service's code that implements the functionality for an operation. This operation is exposed to clients as methods on a WCF client. The method may return a value, and may take an optional number of arguments, or take no arguments, and return no response. For example, an operation that functions as a simple "Hello" can be used as a notification of a client's presence and to begin a series of operations.

service contract

The service contract ties together multiple related operations into a single functional unit. The contract can define service-level settings, such as the namespace of the service, a corresponding callback contract, and other such settings. In most cases, the contract is defined by creating an interface in the programming language of your choice and applying the ServiceContractAttribute attribute to the interface. The actual service code results by implementing the interface.

operation contract

An operation contract defines the parameters and return type of an operation. When creating an interface that defines the service contract, you signify an operation contract by applying the OperationContractAttribute attribute to each method definition that is part of the contract. The operations can be modeled as taking a single message and returning a single message, or as taking a set of types and returning a type. In the latter case, the system will determine the format for the messages that need to be exchanged for that operation.

message contract

A message contract describes the format of a message. For example, it declares whether message elements should go in headers versus the body, what level of security should be applied to what elements of the message, and so on.

fault contract

A fault contract can be associated with a service operation to denote errors that can be returned to the caller. An operation can have zero or more faults associated with it. These errors are SOAP faults that are modeled as exceptions in the programming model.

data contract

The data types a service uses must be described in metadata to enable others to interoperate with the service. The descriptions of the data types are known as the data contract, and the types can be used in any part of a message, for example, as parameters or return types. If the service is using only simple types, there is no need to explicitly use data contracts.

hosting

A service must be hosted in some process. A host is an application that controls the lifetime of the service. Services can be self-hosted or managed by an existing hosting process.

self-hosted service

A self-hosted service is one that runs within a process application that the developer created. The developer controls its lifetime, sets the properties of the service, opens the service (which sets it into a listening mode), and closes the service.

hosting process

A hosting process is an application that is designed to host services. These include Internet Information Services (IIS), Windows Activation Services (WAS), and Windows Services. In these hosted scenarios, the host controls the lifetime of the service. For example, using IIS you can set up a virtual directory that contains the service assembly and configuration file. When a message is received, IIS starts the service and controls its lifetime.

instancing

A service has an instancing model. There are three instancing models: "single," in which a single CLR object services all the clients; "per call," in which a new CLR object is created to handle each client call; and "per session," in which a set of CLR objects are created, one for each separate session. The choice of an instancing model depends on the application requirements and the expected usage pattern of the service.

client application

A client application is a program that exchanges messages with one or more endpoints. The client application begins by creating an instance of a WCF client and calling methods of the WCF client. It is important to note that a single application can be both a client and a service.

channel

A channel is a concrete implementation of a binding element. The binding represents the configuration, and the channel is the implementation associated with that configuration. Therefore, there is a channel associated with each binding element. Channels stack on top of each other to create the concrete implementation of the binding: the channel stack.

WCF client

A WCF client is a client-application construct that exposes the service operations as methods (in the .NET Framework programming language of your choice, such as Visual Basic or Visual C#). Any application can host a WCF client, including an application that hosts a service. Therefore, it is possible to create a service that includes WCF clients of other services.

A WCF client can be automatically generated by using the ServiceModel Metadata Utility Tool (Svcutil.exe) and pointing it at a running service that publishes metadata.

metadata

The metadata of a service describes the characteristics of the service that an external entity needs to understand to communicate with the service. Metadata can be consumed by the ServiceModel Metadata Utility Tool (Svcutil.exe) to generate a WCF client and accompanying configuration that a client application can use to interact with the service.

The metadata exposed by the service includes XML schema documents, which define the data contract of the service, and WSDL documents, which describe the methods of the service.

When enabled, metadata for the service is automatically generated by WCF by inspecting the service and its endpoints. To publish metadata from a service, you must explicitly enable the metadata behavior.

security

Security in WCF includes confidentiality (encryption of messages to prevent eavesdropping), integrity (the means for detection of tampering with the message), authentication (the means for validation of servers and clients), and authorization (the control of access to resources). These functions are provided by either leveraging existing security mechanisms, such as TLS over HTTP (also known as HTTPS), or by implementing one or more of the various WS-* security specifications.

transport security mode

Security can be provided by one of three modes: transport mode, message security mode, and transport with message credential mode. The transport security mode specifies that confidentiality, integrity, and authentication are provided by the transport layer mechanisms (such as HTTPS). When using a transport like HTTPS, this mode has the advantage of being efficient in its performance, and well understood because of its prevalence on the Internet. The disadvantage is that this kind of security is applied separately on each hop in the communication path, making the communication susceptible to a "man in the middle" attack.

message security mode

Message security mode specifies that security is provided by implementing one or more of the security specifications, such as the specification named "Web Services Security: SOAP Message Security" (available at http://go.microsoft.com/fwlink/?LinkId=94684). Each message contains the necessary mechanisms to provide security during its transit, and to enable the receivers to detect tampering and to decrypt the messages. In this sense, the security is encapsulated within every message, providing end-to-end security across multiple hops. Because security information becomes part of the message, it is also possible to include multiple kinds of credentials with the message (these are referred to as claims). This approach also has the advantage of enabling the message to travel securely over any transport, including multiple transports between its origin and destination. The disadvantage of this approach is the complexity of the cryptographic mechanisms employed, resulting in performance implications.

transport with message credential security mode

This mode uses the transport layer to provide confidentiality, authentication, and integrity of the messages, while each of the messages can contain multiple credentials (claims) required by the receivers of the message


There are a few basic tasks when creating a WCF service. The basic tasks that must be

performed are, in order:


  1. Define the service contract. A service contract specifies the signature of a service, the data it exchanges, and other contractually required data.
  2. Implement the contract. To implement a service contract, create the class that implements the contract and specify some custom behaviors that the runtime should have.
  3. Configure the service by specifying endpoint information and other behavior information.
  4. Host the service in an application.
  5. Build a client application.


For more information, see http://msdn2.microsoft.com/en-us/library/ms732098.aspx

Example

To display a step-by-step enactment of the above steps, let's define a web service that reports the current date/time:

1.1 Define a Service Contract

First, let's create a project to house our service contract. Let's call it WCFDateTime.Service.

1.2 Define a Service Contract

Then, let's define an interface that represents the service we're going to provide. In this case, let's call it IDateTimeService.

public interface IDateTimeService

{

}


1.3 Define a Service Contract

We need to add a method to our service that will return the current date/time:

public interface IDateTimeService

{

DateTime GetCurrentDateTime();

}


1.4 Define a Service Contract

Now, we need to decorate our code with attributes so that WCF will recognize our interface and its methods. Namely, we will add the following attributes:

  • ServiceContractAttribute
    • Identifies an interface as a WCF service contract
  • OperationContractAttribute
    • Identifies methods of an interface as WCF service operations, that is, methods that can be called through WCF

using System.ServiceModel;


[ServiceContract]

public interface IDateTimeService

{

[OperationContract]

DateTime GetCurrentDateTime();

}


In order to use the above attributes, you'll need to add a reference to the System.ServiceModel assembly. The service contract is now ready to be used.


2.1 Implement the Contract

Now that we've defined our service contract, we can move on to implementing it. First, let's create another project to house our server application. Let's call it WCFDateTime.Server, and make it a Console Application project.

2.2 Implement the Contract

Now, let's implement the IDateTimeService. The implementation is going to run on our server, to provide the date/time to whoever is going to consume our service.

In the WCFDateTime.Server project, let's create a class called DateTimeService and have it implement IDateTimeService:

using WCFDateTime.Service;


public class DateTimeService : IDateTimeService

{

}


Remember to add a reference to the WCFDateTime.Service project so you can use IDateTimeService.


2.3 Implement the Contract

The above code will obviously not compile, because we did not implement the GetCurrentDateTime method:

public class DateTimeService : IDateTimeService

{

public DateTime GetCurrentDateTime()

{

return DateTime.Now;

}

}

That's it! The DateTimeService is now ready to be used.


3.1 Configure the Service

Now we need to configure our service so it can be consumed by client applications. The simplest way to accomplish this is by adding an application configuration file (app.config or web.config) to the WCFDateTime.Server project:

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

<configuration>

<system.serviceModel>

<services>

<service name="WCFDateTime.Server.DateTimeService">

<endpoint

address="http://localhost:8081/DateTimeService"

binding="wsHttpBinding"

contract="WCFDateTime.Service.IDateTimeService" />

</service>

</services>

</system.serviceModel>

</configuration>

When defining an endpoint for WCF, remember your A-B-Cs:

  1. Address (where)
  2. Binding (how)
  3. Contract (what)


The address specifies the address where you want the service to be located.

The binding specifies the transport you want to use in order to provide the service.

The contract specifies what service will be provided

4.1 Host the Service in an Application

Now that WCF has been configured, the simplest way to host this service is to create a Console Application and use the ServiceHost class. First, add a reference to the System.ServiceModel assembly. Then, In the program.cs file of WCFDateTime.Server, do the following:


using System.ServiceModel;


namespace WCFDateTime.Server

{

class Program

{

static public void Main(string[] args)

{

// Get a host for our service

ServiceHost serviceHost = new ServiceHost(

typeof(DateTimeService)

);


// Open the service host to start listening for incoming requests

serviceHost.Open();


// The service can now be accessed

Console.WriteLine("The service is ready.");

Console.WriteLine("Press <ENTER> to terminate service.");

Console.ReadLine();


// Close the service host

serviceHost.Close();

}

}

}


By simply running this application, we expose our service so that client applications can use it.


1 Build a Client Application

To build a client application, we must create a new project for it. Let's call it WCFDateTime.Client, and make it a Console Application as well.


2 Build a Client Application

Now, we need to add an Application Configuration file, and give it some settings that will allow us to connect to the service we just created:

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

<configuration>

<system.serviceModel>

<client>

<endpoint

address="http://localhost:8081/DateTimeService"

binding="wsHttpBinding"

contract="WCFDateTime.Service.IDateTimeService"

name="MyDateTimeService">

</endpoint>

</client>

</system.serviceModel>

</configuration>


Now that our we've configured our WCF client, we can connect to it. There are two ways to connect to the WCF service we previously created:

  1. Client proxy generation
  2. Channel factories

Most Microsoft articles will point you in the direction of using client proxies; however, for our purposes, channel factories are quicker to implement and more robust in a Model/View/Presenter architecture.


3 Build a Client Application

Now, add a reference to the System.ServiceModel and WCFDateTime.Service assemblies, and then add the following to the program.cs file:

using System.ServiceModel;

using WCFDateTime.Service;


class Program

{

public static void Main(string[] args)

{

// Get a channel factory for our service,

// using the configuration for "MyDateTimeService"

// in the application configuration file.

ChannelFactory<IDateTimeService> channelFactory =

new ChannelFactory<IDateTimeService>("MyDateTimeService");


// Get an instance of our service

IDateTimeService service = channelFactory.CreateChannel();


// Get the server's date/time

DateTime dt = service.GetCurrentDateTime();


// Write the current server date/time

Console.WriteLine("The current server time is " + dt);


// Close the connection to our service

channelFactory.Close();

}

}


4 Build a Client Application

Your client application is now ready to run! Simply start the WCFDateTime.Server application, and once it's running, run the WCFDateTime.Client application to see it work!

This example is ok for testing purpose but when it comes to real time implementation of WCF things goes something unexpected as excepted ;)