Published Wednesday, December 19, 2007 9:30 AM by mtaulty

ADO.NET Data Services - Experimenting with .NET Client Access Whilst Sniffing the HTTP Traffic.

What flows backwards and forwards between a .NET "Data Services" client and its service? I've exposed Northwind.

Querying

Let's do a query from a .NET client (with generated code from the webdatagen tool);

      NorthwindEntities en = new NorthwindEntities(
       "http://mthpvista/DSTest/WebDataService.svc");

      en.MergeOption = MergeOption.AppendOnly;

      Customers c = (from x in en.Customers
                     where x.CustomerID == "ALFKI"
                     select x).First();


      Console.ReadLine();

 

And here's the response - essentially, that LINQ query translates into a URI;

Customers('ALFKI')

and the response I get back is formatted for ATOM;

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xml:base="http://mthpvista/DSTest/WebDataService.svc/" xmlns:ads="http://schemas.microsoft.com/ado/2007/08/dataweb" xmlns:adsm="http://schemas.microsoft.com/ado/2007/08/dataweb/metadata" adsm:type="NorthwindModel.Customers" xmlns="http://www.w3.org/2005/Atom">
  <id>http://mthpvista/DSTest/WebDataService.svc/Customers('ALFKI')</id>
  <updated />
  <title />
  <author>
    <name />
  </author>
  <link rel="edit" href="Customers('ALFKI')" title="Customers" />
  <content type="application/xml">
    <ads:CustomerID>ALFKI</ads:CustomerID>
    <ads:CompanyName>cOMPANY5</ads:CompanyName>
    <ads:ContactName>Maria Anders</ads:ContactName>
    <ads:ContactTitle>Eggs</ads:ContactTitle>
    <ads:Address>Obere Str. 57</ads:Address>
    <ads:City>Berlin</ads:City>
    <ads:Region ads:null="true" />
    <ads:PostalCode>12209</ads:PostalCode>
    <ads:Country>Spain</ads:Country>
    <ads:Phone>030-0074321</ads:Phone>
    <ads:Fax>Foo</ads:Fax>
  </content>
  <link rel="related" title="Orders" href="Customers('ALFKI')/Orders" type="application/atom+xml;type=feed" />
</entry>

Inserting

What happens when I do an insert? That is, run some code such as;

      NorthwindEntities en = new NorthwindEntities(
       "http://mthpvista/DSTest/WebDataService.svc");

      en.MergeOption = MergeOption.AppendOnly;

      Orders o = new Orders();
      Customers c = new Customers()
      {
        CustomerID = "POST1",
        CompanyName = "New Company"
      };

      en.AddObject("Orders", o);
      en.AddObject("Customers", c);
      o.Customers = c;
      en.AddBinding(c, "Orders", o);

      en.SaveChanges();

Big note - I'm not at all sure about that preceding code yet. I seem to have to both call the AddBinding() method and set the Order's Customer property - all feels a bit like "overkill" to me but (so far) that's what I have working.

First, we POST to /DSTest/WebDataService.svc/Orders

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xmlns:ads="http://schemas.microsoft.com/ado/2007/08/dataweb" xmlns:adsm="http://schemas.microsoft.com/ado/2007/08/dataweb/metadata" xmlns="http://www.w3.org/2005/Atom">
  <content type="application/xml">
    <ads:Freight ads:null="true" />
    <ads:OrderDate ads:null="true" />
    <ads:OrderID>0</ads:OrderID>
    <ads:RequiredDate ads:null="true" />
    <ads:ShipAddress ads:null="true" />
    <ads:ShipCity ads:null="true" />
    <ads:ShipCountry ads:null="true" />
    <ads:ShipName ads:null="true" />
    <ads:ShipPostalCode ads:null="true" />
    <ads:ShipRegion ads:null="true" />
    <ads:ShippedDate ads:null="true" />
  </content>
</entry>

Then we get a response which contains;

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xml:base="http://mthpvista/DSTest/WebDataService.svc/" xmlns:ads="http://schemas.microsoft.com/ado/2007/08/dataweb" xmlns:adsm="http://schemas.microsoft.com/ado/2007/08/dataweb/metadata" adsm:type="NorthwindModel.Orders" xmlns="http://www.w3.org/2005/Atom">
  <id>http://mthpvista/DSTest/WebDataService.svc/Orders(11165)</id>
  <updated />
  <title />
  <author>
    <name />
  </author>
  <link rel="edit" href="Orders(11165)" title="Orders" />
  <content type="application/xml">
    <ads:OrderID adsm:type="Int32">11165</ads:OrderID>
    <ads:OrderDate adsm:type="Nullable`1[System.DateTime]" ads:null="true" />
    <ads:RequiredDate adsm:type="Nullable`1[System.DateTime]" ads:null="true" />
    <ads:ShippedDate adsm:type="Nullable`1[System.DateTime]" ads:null="true" />
    <ads:Freight adsm:type="Nullable`1[System.Decimal]" ads:null="true" />
    <ads:ShipName ads:null="true" />
    <ads:ShipAddress ads:null="true" />
    <ads:ShipCity ads:null="true" />
    <ads:ShipRegion ads:null="true" />
    <ads:ShipPostalCode ads:null="true" />
    <ads:ShipCountry ads:null="true" />
  </content>
  <link rel="related" title="Customers" href="Orders(11165)/Customers" type="application/atom+xml;type=entry" />
  <link rel="related" title="Employees" href="Orders(11165)/Employees" type="application/atom+xml;type=entry" />
  <link rel="related" title="Order_Details" href="Orders(11165)/Order_Details" type="application/atom+xml;type=feed" />
  <link rel="related" title="Shippers" href="Orders(11165)/Shippers" type="application/atom+xml;type=entry" />
</entry>

Then we POST to /DSTest/WebDataService.svc/Customers;

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xmlns:ads="http://schemas.microsoft.com/ado/2007/08/dataweb" xmlns:adsm="http://schemas.microsoft.com/ado/2007/08/dataweb/metadata" xmlns="http://www.w3.org/2005/Atom">
  <content type="application/xml">
    <ads:Address ads:null="true" />
    <ads:City ads:null="true" />
    <ads:CompanyName>New Company</ads:CompanyName>
    <ads:ContactName ads:null="true" />
    <ads:ContactTitle ads:null="true" />
    <ads:Country ads:null="true" />
    <ads:CustomerID>POST1</ads:CustomerID>
    <ads:Fax ads:null="true" />
    <ads:Phone ads:null="true" />
    <ads:PostalCode ads:null="true" />
    <ads:Region ads:null="true" />
  </content>
</entry>

the response comes back;

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xml:base="http://mthpvista/DSTest/WebDataService.svc/" xmlns:ads="http://schemas.microsoft.com/ado/2007/08/dataweb" xmlns:adsm="http://schemas.microsoft.com/ado/2007/08/dataweb/metadata" adsm:type="NorthwindModel.Customers" xmlns="http://www.w3.org/2005/Atom">
  <id>http://mthpvista/DSTest/WebDataService.svc/Customers('POST1')</id>
  <updated />
  <title />
  <author>
    <name />
  </author>
  <link rel="edit" href="Customers('POST1')" title="Customers" />
  <content type="application/xml">
    <ads:CustomerID>POST1</ads:CustomerID>
    <ads:CompanyName>New Company</ads:CompanyName>
    <ads:ContactName ads:null="true" />
    <ads:ContactTitle ads:null="true" />
    <ads:Address ads:null="true" />
    <ads:City ads:null="true" />
    <ads:Region ads:null="true" />
    <ads:PostalCode ads:null="true" />
    <ads:Country ads:null="true" />
    <ads:Phone ads:null="true" />
    <ads:Fax ads:null="true" />
  </content>
  <link rel="related" title="Orders" href="Customers('POST1')/Orders" type="application/atom+xml;type=feed" />
</entry>

Then we POST to /DSTest/WebDataService.svc/Customers('POST1')/Orders;

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xmlns:ads="http://schemas.microsoft.com/ado/2007/08/dataweb" xmlns="http://www.w3.org/2005/Atom">
  <id>http://mthpvista/DSTest/WebDataService.svc/Orders(11165)</id>
</entry>

I'm not sure yet if that's exactly the right exchange pattern but in the RESTful world that's perhaps how you do things. I guess what's confusing me is the POST at the end - I'd kind of expect this to be a PUT but you're arguably creating a new relationship so perhaps that's why it's there like that.

Deleting

What about a delete? It seems to be as simple as sending a DELETE to the right URI. However, I have to admit that so far I can't manage to get code like this to work;

NorthwindEntities en = new NorthwindEntities(
        "http://mthpvista/DSTest/WebDataService.svc");

      en.MergeOption = MergeOption.AppendOnly;

      var query = from c in en.Customers
                  where c.CustomerID == "POST1"
                  select c;

      foreach (Customers c in query)
      {
        en.LoadProperty(c, "Orders");

        foreach (Orders o in c.Orders)
        {
          en.DeleteObject(o);
        }
        en.DeleteObject(c);
      }
      en.SaveChanges();

I tried to first off use the $expand syntax to bring the orders back in one go but I find that no matter which syntax I use, I can't get a Customer and all their Orders to be deleted. I seem to be able to either delete the customer or the orders but not both in one go. I need to return to this! :-)

Updating

For a simple update what happens? Piece of code such as;

 NorthwindEntities en = new NorthwindEntities(
       "http://mthpvista/DSTest/WebDataService.svc");

      en.MergeOption = MergeOption.AppendOnly;

      var alfki = (from c in en.Customers
                   where c.CustomerID == "ALFKI"
                   select c).First();

      alfki.Country = "France";
      en.UpdateObject(alfki);

      en.SaveChanges();

First off, I see the GET for the ALFKI customer and then the PUT for the new values (PUT /DSTest/WebDataService.svc/Customers('ALFKI'));

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xmlns:ads="http://schemas.microsoft.com/ado/2007/08/dataweb" xmlns:adsm="http://schemas.microsoft.com/ado/2007/08/dataweb/metadata" xmlns="http://www.w3.org/2005/Atom">
  <id>http://mthpvista/DSTest/WebDataService.svc/Customers('ALFKI')</id>
  <content type="application/xml">
    <ads:Address>Obere Str. 57</ads:Address>
    <ads:City>Berlin</ads:City>
    <ads:CompanyName>cOMPANY5</ads:CompanyName>
    <ads:ContactName>Maria Anders</ads:ContactName>
    <ads:ContactTitle>Eggs</ads:ContactTitle>
    <ads:Country>France</ads:Country>
    <ads:CustomerID>ALFKI</ads:CustomerID>
    <ads:Fax>Foo</ads:Fax>
    <ads:Phone>030-0074321</ads:Phone>
    <ads:PostalCode>12209</ads:PostalCode>
    <ads:Region ads:null="true" />
  </content>
</entry>
Note that this is only going to give you current values so you'd be hard-pressed to do much in the way of "differencing" on the server-side in response to this.

Filed Under: ,

# ADO.NET Data Services - Using LINQ to SQL rather than LINQ to Entities @ Wednesday, December 19, 2007 10:05 AM

Something that's been foxing me is that I've read about ADO.NET Data Services now supporting a &quot;provider&quot;...

Mike Taulty's Blog

# ADO.NET Data Services - Experimenting with .NET Client Access &#8230; | ok @ Wednesday, December 19, 2007 10:28 AM

PingBack from http://real-sports-news.info/adonet-data-services-experimenting-with-net-client-access

ADO.NET Data Services - Experimenting with .NET Client Access … | ok

# ADO.NET Data Services - Experimenting with .NET Client Access &#8230; | ok @ Wednesday, December 19, 2007 10:28 AM

PingBack from http://real-sports-news.info/adonet-data-services-experimenting-with-net-client-access-2

ADO.NET Data Services - Experimenting with .NET Client Access … | ok

# Interesting Finds: December 20, 2007 @ Thursday, December 20, 2007 7:44 AM

Jason Haley

# Ode To Mike Taulty at Lost In Tangent @ Thursday, December 20, 2007 10:15 AM

PingBack from http://lostintangent.com/2007/12/20/ode-to-mike-taulty/

Ode To Mike Taulty at Lost In Tangent

# ?????????????????? ???????????????????? ????????????, ???? ???????????????????????????? ????????&#8230; &laquo; ???????? ???????????? ?????????????? @ Monday, January 14, 2008 2:19 PM

PingBack from http://seregaborzov.wordpress.com/2008/01/15/some-programming-csharp-links/

?????????????????? ???????????????????? ????????????, ???? ???????????????????????????? ????????… « ???????? ???????????? ??????????????