Bing.com, Microsoft's new search engine, provides RSS feeds of all Web searches.
All one needs to do is append "&format=rss" to the search querystring.
Additionally, you can add "&count=200" to get up to (but not more
than) 200 search results. So a canonical "template-ized" Bing.com
RSS Search url would look something like this:
string url = "http://www.bing.com/search?format=rss&count=200&q=" + srch;
where "srch" is the user's search term (which can include any of the very
useful additional search operators, such as "site:" , "contains:",
"hasfeed:", and so on.
You can also search feeds with a search url constructed like the following:
http://www.bing.com/search?q=feed%3A+Silverlight&format=rss&count=200
Unfortunately, bing.com does not expose either a clientaccesspolicy.xml or a crossdomain.xml
policy file, so consuming the RSS search results directly from a Silverlight
client application is not possible. We would either have to use a proxy, such
as Yahoo Pipes, or - as in this case, I simply use a Silverlight 3 RIA Domain
service that is deployed to the server alongside the actual Silverlight app.
(NOTE: the Live.com / Bing.com web API does expose policy files).
You do not need to have a DataModel to use the new Silverlight 3 Domain Service class
- it has the ability to add [ServiceOperation] custom methods. As long as they
return one of the listed types, the Silverlight 3 RIA Services infrastructure
will automatically take care of autogenerating the client-side proxy class deriving
from DomainContext, which you can happily program against in your Silverlight
3 Application. You'll be provided with all the asynchronous methods and events
you need, right out of the box. No need to add ServiceReferences, either. You
can even share classes between server and client by naming them as "MyClass.shared.cs".
There is a special build rule that will automatically copy such files over to
your Silverlight app. In this case, since XElement is one of the supported types for
the ServiceOperation attributed method type, I am "good to go".
In this example I provide two ways to consume the feed results. First, I simply return
the Xml data as a string, and we use XElement.Parse at the client, along with
a simple LINQ query, to create a List< RssItem> that is bound to a DataGrid
with a StackPanel DataTemplate for the layout. The other method takes advantage
of the fact that XElement is one of the supported return types for the DomainService.
In that case, I use XElement.Parse on the server, and return the XElement object
to the Silverlight Client.
We have a simple page with a TextBox for the search phrase at the top, along with
two buttons - one to use the string method, and the other to use the XElement
method. Either button will return identical results:

Let's have a look at the server side DomainService class first:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web.Ria;
using System.Web.Ria.Data;
using System.Web.DomainServices;
[EnableClientAccess()]
public class BingService : DomainService
{
[ServiceOperation]
public string RSSResult(string srch)
{
string result = String.Empty;
WebClient
wc = new WebClient();
string url = "http://www.bing.com/search?format=rss&count=200&q=" + srch;
try
{
result
= wc.DownloadString(url);
}
catch (WebException wex)
{
result
= wex.Message;
}
finally
{
wc.Dispose();
}
return result;
}
[ServiceOperation]
public XElement RSSResultXml(string srch)
{
string result = String.Empty;
WebClient
wc = new WebClient();
string url = "http://www.bing.com/search?format=rss&count=200&q=" + srch;
try
{
result
= wc.DownloadString(url);
}
catch (WebException wex)
{
result
= wex.Message;
}
finally
{
wc.Dispose();
}
XElement
xeresult = XElement.Parse(result);
return xeresult;
}
}
Above, you see the two ServiceOperation methods. We just take the search term that
is sent via the Silverlight Client, append it to the "Template" url
for a search, and use the WebClient class to download the result string. Depending
on which method used, we either load this into an XElement, or return the raw
string. Note the required [EnableClientAccess()] attribute at class level.
When you build this, it will autogenerate your DomainContext class in the client
Silverlight app - ready to use (in this case, "BingContext"); the following
code shows the usage:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using BingSearch.Web;
using System.Xml.Linq;
namespace BingSearch
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void Button1_Click(object sender, RoutedEventArgs e)
{
string srch = this.searchTerm.Text;
BingContext
ctx = new BingContext();
ctx.RSSResultCompleted
+= new EventHandler<System.Windows.Ria.Data.InvokeEventArgs>(ctx_RSSResultCompleted);
ctx.RSSResult(srch);
}
void ctx_RSSResultCompleted(object sender, System.Windows.Ria.Data.InvokeEventArgs e)
{
string rss = (string)e.ReturnValue;
XElement
elem = XElement.Parse(rss);
var
items = elem.Descendants("item");
var
i = items.FirstOrDefault();
string s =i.Element("description").Value!=null? (string)i.Element("description").Value:String.Empty;
string t = (string)i.Element("title").Value;
string l = (string)i.Element("link").Value;
string p = (string)i.Element("pubDate").Value;
var
results = (from itm in items
select new RssItem()
{
title = (string)itm.Element("title").Value,
description = (string)itm.Element("description").Value,
link = (string)itm.Element("link").Value,
pubDate = (string)itm.Element("pubDate").Value
}).ToList();
this.rssGrid.ItemsSource = results;
}
private void Button2_Click(object sender, RoutedEventArgs e)
{
string srch = this.searchTerm.Text;
BingContext
ctx = new BingContext();
ctx.RSSResultXmlCompleted
+= new EventHandler<System.Windows.Ria.Data.InvokeEventArgs>(ctx_RSSResultXmlCompleted);
ctx.RSSResultXml(srch);
}
void ctx_RSSResultXmlCompleted(object sender, System.Windows.Ria.Data.InvokeEventArgs e)
{
XElement
elem =(XElement) e.ReturnValue;
var
items = elem.Descendants("item");
var
i = items.FirstOrDefault();
string s = (string)i.Element("description").Value;
string t = (string)i.Element("title").Value;
string l = (string)i.Element("link").Value;
string p = (string)i.Element("pubDate").Value;
var
results = (from itm in items
select new RssItem()
{
title = (string)itm.Element("title").Value,
description = (string)itm.Element("description").Value,
link = (string)itm.Element("link").Value,
pubDate = (string)itm.Element("pubDate").Value
}).ToList();
this.rssGrid.ItemsSource = results;
}
}
There are many more features to Silverlight 3 RIA Services - validation, two-way
databinding, paging, the DomainDataSource control, and much more. I hope this
short sample will give you some good ideas.
You can download the Visual Studio 2008 / Silverlight 3 solution here.