Introducing Web Friendly Feeds aka Friendly Feeds (Updated for CTP2)
Phani Raj
Hello all , with the recent release of ADO.NET Data v1.5 Services CTP 1 , we introduced a new feature called as “Web Friendly Feeds”.
With the release of CTP2 , we have introduced support for 2 additional ATOM:Entry elements you can map to:
- entry:Summary
- entry:Updated
What is this feature about ?
This is what the markup for one of the the resources of Customers looks like in ADO.NET Data Services v1 .
<?xml version="1.0" encoding="utf-8" standalone="yes" ?> <entry xml:base=http://localhost:26503/northwind.svc/
xmlns:d=http://schemas.microsoft.com/ado/2007/08/dataservices
xmlns:m=http://schemas.microsoft.com/ado/2007/08/dataservices/metadata
xmlns="http://www.w3.org/2005/Atom"> <id>http://localhost:26503/northwind.svc/Customers('ALFKI')</id> <title type="text" /> <updated>2009-03-18T20:30:20Z</updated> <author> <name /> </author> <category term="NorthwindModel.Customers" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> <content type="application/xml"> <m:properties> <d:CustomerID>ALFKI</d:CustomerID> <d:CompanyName>Alfreds Futterkiste</d:CompanyName> <d:ContactName>Maria Anders</d:ContactName> <d:ContactTitle>Sales Representative</d:ContactTitle> <d:Address>Obere Str. 57</d:Address> <d:City>Berlin</d:City> <d:Region m:null="true" /> <d:PostalCode>12209</d:PostalCode> <d:Country>Germany</d:Country> <d:Phone>030-0074321</d:Phone> <d:Fax>030-0076545</d:Fax> </m:properties> </content> </entry>
In the markup above , a couple of things are missing
1) The <title> element is empty
<title type="text" />
2) The author/name element is empty
<author> <name /> </author>
In v 1.5 , through Friendly Feeds , we will now be able to assign a property of the “Customers” entity type to turn up in these element locations in the atom:entry payload.
Now , let’s say that we wanted to map the “ContactName” as the author name element of the entry element and Title to be “ContactTitle” as the title of the entry element.
Then , the payload would look like this :
<entry > <id>http://localhost:26503/northwind.svc/Customers('ALFKI')</id> <title type="text">Sales Representative</title> <updated>2009-03-18T20:46:42Z</updated> <author> <name>Maria Anders</name> </author> <category term="NorthwindModel.Customers" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> <content type="application/xml"> <m:properties> <d:CustomerID>ALFKI</d:CustomerID> <d:CompanyName>Alfreds Futterkiste</d:CompanyName> <d:ContactName>Maria Anders</d:ContactName> <d:ContactTitle>Sales Representative</d:ContactTitle> <d:Address>Obere Str. 57</d:Address> <d:City>Berlin</d:City> <d:Region m:null="true" /> <d:PostalCode>12209</d:PostalCode> <d:Country>Germany</d:Country> <d:Phone>030-0074321</d:Phone> <d:Fax>030-0076545</d:Fax> </m:properties> </content> </entry>
This also means , that IE now displays the Title & author Name elements when you browse to the “Customers” entity set .
Which elements in the atom:entry element can I map to an entity type properties ?
- entry:author/email
- entry:author/name
- entry:author/uri
- entry:published
- entry:rights
- entry:summary
- entry:title
- entry:updated
- entry:summary
Once a property is mapped , if keeping the value of the property in the entry:contents section doesn’t make sense,can I remove it ?
Yes , absolutely , in the above case , we can remove the ContactName & ContactTitle elements from being repeated in the <contents> section.
Ex:
<entry> <id>http://localhost:26503/northwind.svc/Customers('ALFKI')</id> <title type="text">Sales Representative</title> <updated>2009-03-18T21:04:20Z</updated> <author> <name>Maria Anders</name> </author> <category term="NorthwindModel.Customers" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> <content type="application/xml"> <m:properties> <d:CustomerID>ALFKI</d:CustomerID> <d:CompanyName>Alfreds Futterkiste</d:CompanyName> <d:Address>Obere Str. 57</d:Address> <d:City>Berlin</d:City> <d:Region m:null="true" /> <d:PostalCode>12209</d:PostalCode> <d:Country>Germany</d:Country> <d:Phone>030-0074321</d:Phone> <d:Fax>030-0076545</d:Fax> </m:properties> </content> </entry>
Great , what else can I do with this new feature ?
Well, did I mention you can embed your own markup in the <entry> element for an entity type !!!
consider the following entity type , BlogPost , which looks like this
public class BlogPost { public double Lat { get; set; } public double Long { get; set; } public int BlogPostID { get; set; } public string Title { get; set; } public string Body { get; set; } public string Author { get; set; } public string PostURI { get; set; } public string ContentSummary{get;set;} }
This type represents the entry for a blog post , and also contains the Geographical location information about where the post was made ( Lat /Long)
and also the author information. Now , if this data was exposed via a Data Service, the payload would contain the Lat/Long/Published fields as part of
the entry:content element and wouldn’t have any special meaning.
The author element should be the Author field of the atom:entry , and the Published field to be the atom:published.
the Lat & Long fields should be a georss element that shows the location at which the Blog Post was made.
In short , it should look like this :
<entry> <id>http://localhost/AstoriaBoard/Services/BlogSvc.svc/Posts(1)</id> <title type="text">Entities, How many ways do I count thee ?</title> <summary type="html">
<img class='imgClass' width='150px' height='150px' src='/AStoriaBoard/mug.jpg'/><br/>Its a common ask that we introduce aggregatin
</summary> <published>2009-03-18T14:29:43-07:00</published> <updated>2009-03-18T21:29:43Z</updated> <author> <name>Phani Raj</name> </author> <link rel="edit" title="BlogPost" href="Posts(1)" /> <category term="Blogs.BlogPost" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> <content type="application/xml"> <m:properties> <d:BlogPostID m:type="Edm.Int32">1</d:BlogPostID> <d:Body>Its a common ask that we introduce aggregating mechanisms in Data services
so that one can do a Count of the number of entities present in an EntitySet easily.
In this blog post , I will outline one method of implementing a “Count” method that works for you.
The interface to the count method will be</d:Body> <d:Author>Phani Raj</d:Author> <d:PostURI m:null="true" /> </m:properties> </content> <geo xmlns="http://www.georss.org/georss"> <long>-80.244445</long> <lat>25.730752</lat> </geo> </entry>
Now that we got this markup , I feel like we should do something with it . How about showing this information on a MAP ?
I know !! We have a mapping solution , Virtual Earth , lets try and see if we can feed this feed to Virtual Earth and make it see our GeoRss markup.
Recently , ( November 2008 ), the Live team released the Map control as an asp.net control . Download it here :http://dev.live.com/tools/
Add this control to an aspx page in the same website as the Data Service .
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <style> .imgClass{ border: solid 2px #99ccff;} </style> </head> <body> <form id="form1" runat="server"> <script language="javascript"> function pageLoad() { HookUpWorkAround(); } </script> <div id="mapContainer"> <ve:Map ID="geoRssMap" runat="server" Height="600px" Width="75%" ZoomLevel="4" /> </div> <asp:ScriptManager ID="scrpManager" runat="server"> <Scripts> <asp:ScriptReference Path="~/Scripts/VEWorkAround.js" /> </Scripts> </asp:ScriptManager> </form> </body> </html>
In the code-behind file ,
using System; using Microsoft.Live.ServerControls.VE; public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { //Clear out any mapped locations geoRssMap.Clear(); //Create a new shapelayer to import ShapeLayer geoRssLayer = new ShapeLayer(); //Point the shape layer at the data source returning the mapping information ShapeSourceSpecification georssSpec = new ShapeSourceSpecification( DataType.GeoRSS, "Services/BlogSvc.svc/Posts", geoRssLayer ); //Bind the feed to the map geoRssMap.ImportShapeLayerData(georssSpec, null, false); } }
You might be wondering why we need the HookUpWorkAround() function and what it does , I’ll explain that in a later blog post .
After this , set the web page as the startup page and browse to the page in FireFox , I’ll explain why Firefox in a later blog post .
And voila !! This is what the page looks like :
You can download the sample project that demonstrates this feature by clicking on the link at the bottom of this post
All this demonstrates the what and not the how , we shall discuss the how in future blog posts.
In the meantime ,enjoy this sample app and try out your own mashups.