Thursday, December 31, 2009

The "Fancy Proxy" - having fun with WCF - 1-Simple TCP

This article is part of The "Fancy Proxy" tutorial - implementing a few advance ideas in WCF in one solution.

This is the 1st step - Simple TCP

Ok...so let's start than...

1st step, lets implement the easiest WCF "hello world" - just to warm up.

We'll start with the contract:

[ServiceContract]
public interface ISampleContract
{
[OperationContract]
string GetData(Guid identifier);

[OperationContract]
void Execute(Guid identifier);
}


Next we'll implement this interface on server side - our "bussiness logic":

public class testFancyProxyService:ISampleContract
{
public string GetData(Guid identifier)
{
Console.WriteLine("recieved GetData request (id {0})", identifier);

//in real life we'll probably get data using the identifier
return "hello world..";
}

public void Execute(Guid identifier)
{
Console.WriteLine("recieved Execute request (id {0})", identifier);
}
}


Next, lets host the service:

class Program
{
private static ServiceHost serviceHost = null;

static void Main(string[] args)
{
try
{
startListening();

Console.WriteLine("Server is up, press any key to stop it...");
Console.Read();
}
catch (Exception ex)
{
Console.WriteLine(string.Format("Error: {0}\n\n Stack:{1}", ex.Message, ex.StackTrace));
Console.Read();
}
finally
{
stopListening();
}
}

private static void startListening()
{
serviceHost = new ServiceHost(typeof(testFancyProxyServer.testFancyProxyService));

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

private static void stopListening()
{
if (serviceHost != null)
{
if (serviceHost.State == CommunicationState.Opened)
{
serviceHost.Close();
}
}
}
}


Configure the server's endpoint to listen on any available TCP port and that's it for the server.

<endpoint address="net.tcp://localhost:8080/testFancyProxy" binding="netTcpBinding"
contract="testFancyProxyContracts.ISampleContract" /;>


Same thing on client side - we'll code a small proxy (yes, you can instead use "add service reference" on visual studio :-)):


public class testFancyProxyProxy:ISampleContract
{
private ChannelFactory channelFactory;
private ISampleContract proxy;

public testFancyProxyProxy()
{
channelFactory = new ChannelFactory("tcpEndPoint");
proxy = channelFactory.CreateChannel();
}

#region ISampleContract Members

public string GetData(Guid identifier)
{
return proxy.GetData(identifier);
}

public void Execute(Guid identifier)
{
proxy.Execute(identifier);
}

#endregion
}


Configure the client and test it:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint address="net.tcp://localhost:8080/testFancyProxy/"
binding="netTcpBinding"
contract="testFancyProxyContracts.ISampleContract"
name="tcpEndPoint"/>
</client>
</system.serviceModel>
</configuration>


Testing...:

public class testFancyProxyConsumer
{
private testFancyProxyClient.testFancyProxyProxy proxy;

public void Run()
{
proxy = new testFancyProxyProxy();

Console.WriteLine(proxy.GetData(Guid.NewGuid()));

Console.WriteLine("calling Execute..");
proxy.Execute(Guid.NewGuid());

}
}







That's it!! 1st step - nice & simple..this project will be the base of the next steps.

Till next step...
Diego

PS: source download

The "Fancy Proxy" - having fun with WCF

A little project I was doing at home lately lead me to search for a solution to disconnected application.

In my imaginination I imagined an application that knows to work both "online" and "offline"...not just that but also knows how to switch between them when needed and ofcourse - controlled from WCF configuration or other infrastructure that will be as "transparent" as possible for the programmer who writes the application.

Sounds a little like science fiction? not quite...

Gathering information from all sort of good articles & blogs I've reach to a nice project which I've decieded to share with you in a kind of tutorial structure to help ,who ever finds this interesting, step by step.
I know the code could & should pass a bit of polish, but hey! remember it's just an idea not production material :-)

Each step in this "tutorial" represents a step in the way for the full solution, this is only to help understand each concept seperatly, feel free to jump over a few steps or go directly to the final step...

1- Simple TCP
2- Simple MSMQ
3- Simple Duplex
4- MSMQ Duplex
5- Simple Dynamic proxy
6- Dynamic & Duplex proxy

Feel free to ask or comment...

Diego

Tuesday, December 22, 2009

XmlDataDocument - Synchronizing DataSet and XmlDocument

Introduction

XmlDataDocument object combines relational data model (DataSet) and hierarchical data model (XML document) and performs transparent synchronization between them to ensure that at any point of time, both models contain the same data.
This means that any change made to the DataSet is authomatically reflected in the corresponding XMLDocument.

XmlDataDocument Using Example

In order to demonstrate how to work with XmlDataDocument object, we will create a simple dataset (representing books database):


DataSet newDS = new DataSet("BooksDS");

DataTable authorsTable = new DataTable("Authors");
authorsTable.Columns.Add("AuthorID", typeof(int));
authorsTable.Columns.Add("FirstName", typeof(string));
authorsTable.Columns.Add("LastName", typeof(string));
authorsTable.PrimaryKey = new DataColumn [] { authorsTable.Columns["AuthorID"]};

authorsTable.Rows.Add(1, "Benjamin", "Franklin");
authorsTable.Rows.Add(2, "Herman", "Melville");

newDS.Tables.Add(authorsTable);

DataTable booksTable = new DataTable("Books");
booksTable.Columns.Add("BookID", typeof(int));
booksTable.Columns.Add("AuthorID", typeof(int));
booksTable.Columns.Add("BookTitle", typeof(string));
booksTable.Columns.Add("Genre", typeof(string));
booksTable.Columns.Add("PublicationDate", typeof(DateTime));
booksTable.Columns.Add("ISBN", typeof(string));
booksTable.PrimaryKey = new DataColumn[] { booksTable.Columns["BookID"] };

booksTable.Rows.Add(1, 1, "The Autobiography of Benjamin Franklin", "autobiography", DateTime.Now, "1-2-234234-4");
booksTable.Rows.Add(2, 2, "The Confidence Man", "novele", DateTime.Now, "5-2-234234-4");

newDS.Tables.Add(booksTable);

newDS.Relations.Add("AuthorsBooks",
newDS.Tables["Authors"].Columns["AuthorID"],
newDS.Tables["Books"].Columns["AuthorID"]);
newDS.Relations[0].Nested = true;



Now, we can create an instance of XmlDataDocument by feeding its constructor with newDS



XmlDataDocument xmlDoc = new XmlDataDocument(newDS);


Since XmlDataDocument inherits from XmlDocument, we have all XML-related objects within it.
In addition, XmlDataDocument contains DataSet object which references our newDS instance and allows access to relational view.

We can persist our XmlDataDocument into XML file and check how the inner XML looks like:



xmlDoc.Save("books.xml");


Fllowing XML file is generated:



<booksds>
<authors>
<authorid>1</authorid>
<firstname>Benjamin</firstname>
<lastname>Franklin</lastname>
<books>
<bookid>1</bookid>
<authorid>1</authorid>
<booktitle>The Autobiography of Benjamin Franklin</booktitle>
<genre>autobiography</genre>
<publicationdate>2009-12-22T12:15:06.7278538+02:00</publicationdate>
<isbn>1-2-234234-4</isbn>
</books>
</authors>
<authors>
<authorid>2</authorid>
<firstname>Herman</firstname>
<lastname>Melville</lastname>
<books>
<bookid>2</bookid>
<authorid>2</authorid>
<booktitle>The Confidence Man</booktitle>
<genre>novele</genre>
<publicationdate>2009-12-22T12:15:06.7278538+02:00</publicationdate>
<isbn>5-2-234234-4</isbn>
</books>
</authors>
</booksds>


Let's change some field value in newDS and save XML again:


newDS.Tables["Books"].Rows[0]["BookTitle"] = "The Revised biography of Benjamin Franklin";
xmlDoc.Save("books.xml");


As we can see, the change is automatically reflected in xmlDoc:



<booksds>
<authors>
<authorid>1</authorid>
<firstname>Benjamin</firstname>
<lastname>Franklin</lastname>
<books>
<bookid>1</bookid>
<authorid>1</authorid>
<booktitle><strong><span >The Revised</span> </strong>biography of Benjamin Franklin</booktitle>
<genre>autobiography</genre>
<publicationdate>2009-12-22T12:15:06.7278538+02:00</publicationdate>
<isbn>1-2-234234-4</isbn>
</books>
</authors>
<authors>
<authorid>2</authorid>
<firstname>Herman</firstname>
<lastname>Melville</lastname>
<books>
<bookid>2</bookid>
<authorid>2</authorid>
<booktitle>The Confidence Man</booktitle>
<genre>novele</genre>
<publicationdate>2009-12-22T12:15:06.7278538+02:00</publicationdate>
<isbn>5-2-234234-4</isbn>
</books>
</authors>
</booksds>


You can find the detailed info about this powerful object here:
http://msdn.microsoft.com/en-us/library/1t4362sd.aspx
http://msdn.microsoft.com/en-us/library/system.xml.xmldatadocument.aspx

Thats' it,
Mark.