Saturday, July 28, 2007
We have written a webservices example using three different forms of the same service. These webservices allow you to retrieve and update data and are built upon the Microsoft SQL Northwind Employees table using EntitySpaces 2007.0.730.0 maintenance release which will be published this weekend (July 28th, 2007).  You can download both the WSConsumer application and the webservices (including source code) at the end of this article. The webservice is included so you can the see the source and run it locally if desired. The WSConsumer is setup to hit the services listed below on our site.

    Xml - http://www.entityspaces.net/webservices/csharp/ES_Xml.asmx

    XmlProxy - http://www.entityspaces.net/webservices/csharp/ES_XmlProxy.asmx

    Binary - http://www.entityspaces.net/webservices/csharp/ES_Binary.asmx

 

The Xml Webservice

The XML webservice is a basic SOAP example. It simply returns the Employees entity or the EmployeesCollection and everything is serialized accordingly. This type of webservice, the more traditional, doesn't require the webservice consumer to have any knowledge or link to any of your code.

[WebMethod]
public Employees GetEmployee(int i)
{
    Employees emp = new Employees();
    if (emp.LoadByPrimaryKey(i))
        return emp;
    else
        return null;
}

[WebMethod]
public EmployeesCollection GetAllEmployees()
{
    EmployeesCollection emps = new EmployeesCollection();
    if (emps.LoadAll())
        return emps;
    else
        return null;
}

Most people are familiar with traditional webservices. If you are interested in saving data through your webservice all the necessary code is in the demo app. However, security issues when allowing users to update data are not covered, those are left up to the developer to consider.

The XmlProxy Webservice (and WCF)

This is by far the most interesting and powerful example. The EntitySpaces proxy classes can be used in webservice scenarios in which you have control over both the webservice and the consumer as this example requires the proxy to be on both sides of the equation. Additionally, the EntitySpaces proxy classes are perfect for use as your WCF wire format. When we generated the proxy classes for the demo we did not check the "Support WCF" checkbox. We only generated the proxy portion which can be used on it's own without WCF. Some of the features of the proxy classes are follows:

  • Perfect for WCF communications.
  • Very easy to use wrappers
  • Very lightweight format which can serialize only the dirty rows and dirty columns.
  • Manages Added, Modified, and Deleted state for you.
  • Transparent Save logic.

If you're using EntitySpaces in WCF scenarios you can glean a lot from this section, it's shows exactly how your WCF packets will look. In this sample we need to manually serialize them into string form but in WCF scenarios you would just return the actual proxy's in your methods and the serialization is done for you. Take a look at our GetEmployee() method and notice the serialization so that we can return a raw string. Notice how we use the Proxy to wrap the real Employees object.

[WebMethod]
public string GetEmployee(int i)
{
    Employees emp = new Employees();
    if (emp.LoadByPrimaryKey(i))
    {
        // The Generated Proxy class
        EmployeesProxyStub proxy = new EmployeesProxyStub(emp);

        // Manually Serialize into string form (we want to deserialize it on the other side)
        XmlSerializer sf = new XmlSerializer(typeof(EmployeesProxyStub));
        StringWriter sw = new StringWriter();
        sf.Serialize(sw, proxy);

        return sw.ToString();
    }
    else
        return null;
}

 

The output of our call to the GetEmployee() method above can be seen below.

<?xml version="1.0" encoding="utf-16"?>
    <EmployeesProxyStub xmlns:xsi="
" xmlns:xsd="">
    <EmployeeID>1</EmployeeID>
    <LastName>Davolio</LastName>
    <FirstName>Jimmy</FirstName>
    <Title>Sales Representative</Title>
    <TitleOfCourtesy>Ms.</TitleOfCourtesy>
    <BirthDate>1948-12-08T00:00:00</BirthDate>
    <HireDate>1992-05-01T00:00:00</HireDate>
    <Address>507 - 20th Ave. E.Apt. 2A</Address>
    <City>Seattlesss</City>
    <Region>WA</Region>
    <PostalCode>78890</PostalCode>
    <Country>USA</Country>
    <HomePhone>(206) 555-9857</HomePhone>
    <Extension>989</Extension>
    <Notes>Some notes by Rick</Notes>
    <ReportsTo>161</ReportsTo>
   
<esRowState>Unchanged</esRowState>
</EmployeesProxyStub>

 

Notice the esRowState is "Unchanged". Now let's deserialize this in our client (in the demo the client is called WSConsumer). The code necessary to do this (taken from the WSConsumer application) is shown below.

// Call the XmlProxy Service
string data = wsProxyService.GetEmployee(1);

XmlSerializer xs = new XmlSerializer(typeof(BusinessObjects.EmployeesProxyStub));
StringReader sr = new StringReader(data);

// Deserialize into our Proxy
BusinessObjects.EmployeesProxyStub proxy =
xs.Deserialize(sr) as BusinessObjects.EmployeesProxyStub;

// Ask the proxy for the true Employees object
Employees emp = proxy.Entity;

Now let's modify the "emp" object we just deserialized and save it back through our service

emp.FirstName = "Joe";
emp.LastName = " EntitySpaces";

// True here means dirty columns only (primary keys are of course always sent)
BusinessObjects.EmployeesProxyStub proxy =
    new BusinessObjects.EmployeesProxyStub(this.emp, true);

XmlSerializer sf = new XmlSerializer(typeof(BusinessObjects.EmployeesProxyStub));
StringWriter sw = new StringWriter();
sf.Serialize(sw, proxy);

string packet = sw.ToString();

wsProxyService.SaveEmployee(packet);

Let's take a look at the packet sent back from the WSConsumer application to the webservice that was generated from the above code.

<?xml version="1.0" encoding="utf-16"?>
    <EmployeesProxyStub xmlns:xsi="
" xmlns:xsd="">
    <EmployeeID>1</EmployeeID>
    <LastName>EntitySpaces</LastName>
    <FirstName>Joe</FirstName> 
    <esRowState>Modified</esRowState>
</EmployeesProxyStub>

Notice that only the dirty columns are sent back and the esRowState is set to "Modified". We're almost at the end of this sequence, let's see how our XmlProxy webservice implements the SaveEmployee method.

[WebMethod]
public void SaveEmployee(string data)
{

    // Deserialize into our Proxy
    XmlSerializer xs = new XmlSerializer(typeof(EmployeesProxyStub));
    StringReader sr = new StringReader(data);

    EmployeesProxyStub proxy = xs.Deserialize(sr) as EmployeesProxyStub;

    // Ask for the real Employee entity
    Employees emp = proxy.entity;
    if (emp != null)
    {
        // Simply Save it, the added, modified, deleted state is 100% managed by the proxy
        emp.Save();
    }
}

Could it be any easier? Although not shown here (but demonstrated in the WSConsumer application) you can modify and transmit entire collections just as easily. The XmlProxy approach is the best way to go in all scenarios in which you are in control of both ends of the equation. Nothing could be easier or faster.

The Binary Webservice

The binary webservice approach can also be used in two way communication scenario's and while it is very easy to use, like the XmlProxy approach, it is far more bulky and bloated, however, the data is somewhat more secure in that it is not human readable.

[WebMethod]
public byte[] GetEmployee(int id)
{
    Employees obj = new Employees();
    if (obj.LoadByPrimaryKey(id))
    {
        BinaryFormatter bf = new BinaryFormatter();
        MemoryStream ms = new MemoryStream();
        bf.Serialize(ms, obj);

       return ms.ToArray();
    }
    else
        return null;
}

The packet transmitted will look something like this, only much larger.

AAEAAAD/////AQAAAAAAAAAMAgAAAD1CdXNPYmosIFZlcnNpb249MS4wLjAuMCwgQ3
VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1udWxsDAMAAABZRW50aXR5U3BhY2
VzLkNvcmUsIFZlcnNpb249MjAwNy4wLjczMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1Ymxp
Y0tleVRva2VuPTFjMjY4MTk5ZmIyMWJmZTgMBAAAAElTeXN0ZW0sIFZlcnNpb249Mi4wLjA
uMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5D
AUAAABOU3lzdGVtLkRhdGEsIFZlcnNpb249Mi4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQ
dWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAZQnVzaW5lc3NPYmplY3RzLkV
tcGxveWVlcw8AAAAfX0VtcGxveWVlc0NvbGxlY3Rpb25CeVJlcG9ydHNUbxpfVXBUb1RlcnJp
dG9yaWVzQ29sbGVjdGlvbh5fRW1wbG95ZWVUZXJyaXRvcmllc0NvbGxlY3Rpb24qX0VtcGxv
eWVlVGVycml0b3JpZXNDb2xsZWN0aW9uQnlFbXBsb3llZUlEHV9PcmRlcnNDb2xsZWN0aW9
uQnlFbXBsb3llZUlEBXF1ZXJ5GV9VcFRvRW1wbG95ZWVzQnlSZXBvcnRzVG8PbW9kaWZpZ
WRDb2x1bW5zA2Zrcxtlc0VtcGxveWVlcytQcm9wZXJ0eUNoY

And that is not all that is transmitted for a just a single employee object. The reason this is so large is that everything is serialized in binary serialization, the underlying DataTable, it's columns, rows, everything.

 

Summary

We encourage you to download and run our WebServices demo, it comes with the v2007.0730 Trial assemblies necessary to run the WSConsumer against our hosted webservices, and shows you the packets as they go back and forth (except in the case of the Xml service, there is no easy way to intercept the soap packets). There re some big improvements (though minor changes in code) in the v2007.0730 release that greatly improve the EntitySpaces proxy classes.

You can download the full source to both the WSConsumer and Webservices here ==> DOWNLOAD

NOTE: There is an enforced two second delay between requests to cut down on the traffic for these demo services.

EntitySpaces

From mobile devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with medium trust requirements, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

The EntitySpaces Team
--

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

Comments are closed.