WCF Syndication
HTTP Programming with WCF and the .NET Framework 3.5
Justin Smith
This article is based on a prerelase version of Visual Studio 2008. All information herein is subject to change.
This article discusses:
- HTTP message basics
- Adding information to URIs
- WCF and HTTP
- RSS and ATOM with WCF
|
This article uses the following technologies:
Windows Communication Foundation |
Contents
When it was first released as part of the Microsoft®.NET Framework 3.0, Windows®Communication
Foundation (WCF) included a universal object model for Plain Old XML
(POX) and SOAP messaging over a wide variety of transports. Because WCF
also contains deep support for WS-* Web service standards, it is able to
interoperate with other modern service platforms with relatively little
difficulty. WCF in the .NET Framework 3.0 is highly extensible and
includes solid manageability features like message logging, activity
tracing, service throttling, instance management, and threading
controls.
WCF in the .NET Framework 3.5 builds on the extensibility
points in the .NET Framework 3.0 to include first-class support for
building services that adhere to the principles of the Web. This
includes an easy-to-use HTTP programming model, JavaScript Object
Notation (JSON) messaging capabilities, and a new syndication API that
makes it easy to create and consume syndicated content. With this
feature set, WCF is now the service platform of choice for connecting
services to Web clients, whether they are ASP.NET AJAX controls,
SilverlightTMclients, or even browsers.
These features also work in partial trust scenarios (like ASP.NET
medium trust) so you can host WCF services in widely available hosting
environments. To round it all out, there's also new tooling integrated
into Visual Studio®2008 that dramatically reduces the amount of time it takes to get a service up and running.
Combining
Web-centric communication with SOAP and WS-* standards into one service
stack and object model is one of the features that makes WCF in the
.NET Framework 3.5 so compelling. This means you can build a service
that communicates within or across enterprise boundaries using SOAP and
WS-*, and you can configure that same service to communicate externally
using the protocols of the Web. In effect, WCF takes care of the
plumbing in your service and lets you focus more closely on the
functionality your service exposes.
This
article explains some of the new Web-centric features of WCF in the
.NET Framework 3.5. It starts with a level-setting discussion about some
of the important architectural principles in HTTP and the Web, then
moves to the new HTTP programming model in WCF, and, finally, to the new
syndication API.
HTTP Message Basics
You
probably use the Web almost every day, but how often do you think about
the core concepts that make the Web work? It's not in my nature to
carry on about architectural concepts, but some of the key ideas baked
into the Web may not be obvious at first glance. In my view, a good
understanding of these principles is a necessary first step when
building services that adhere to the protocols of the Web. Keep in mind
that entire books are dedicated to this topic, so I'll only hit the high
points in this article. When in doubt, consult the HTTP/1.1
specification (RFC 2616).
HTTP
is the native protocol that runs the Web. HTTP is a request/response
protocol: every time you use your browser to navigate to a new Web page,
you send an HTTP request message to an HTTP server (or proxy), which
will return a response message to your browser. HTTP defines several
methods (often called verbs informally) that identify operations that an
HTTP server can perform (for example, GET, POST, PUT, and DELETE). The
HTTP protocol also defines the notion of a resource that is the “target”
of the request. Resources are identified by a URI which appears as data
in the HTTP request message. Here is a trimmed down version of an HTTP
request:
POST /myservice/PostAlbum HTTP/1.1
HOST: www.cloudsample.net
Content-Type: text/xml
<albumInfo>
<albumId>15</albumId>
</albumInfo>
In
this example, the resource URI is
http://www.cloudsamples.net/myservice/PostAlbum and the HTTP method is
POST. POST is the most common HTTP method for causing side-effects and
has the most “liberal” interpretation in the protocol specification (and
in common practice). The request message also has an XML payload (also
known as the “entity body”) that contains a value for the albumId field.
The
POST method is most commonly used for updating data over the web.
However, most web traffic simply reads information, which happens using
the GET method. A GET request asks for a data value (called a
representation) that corresponds to the specified URI. Here’s a simple
HTTP GET request:
GET /myservice/GetAlbum/15 HTTP/1.1
HOST: www.cloudsamples.net
GET
requests have no payload – rather, the request consists solely of the
request URI plus headers. In general, headers are used for content
negotiation and cache management, with the URI containing the
“significant” information needed to identify the resource in question.
This emphasis on the URI is a recurring theme in web-centric
applications.
HTTP
response messages contain a status code, zero or more headers, and an
optional payload/entity body. HTTP status code tells the client what
happened, and the headers and payload convey the response information.
Here’s a simple HTTP response that corresponds to our GET request above:
HTTP/1.1 200 OK
Content-Type: text/xml
Expires: Thu, 01 Jan 2009 13:00:00 GMT
<Album id="15" title="The rest of the story" />
This
response indicates that the request was successfully processed (hence
the 200 status code) and that the representation of the resource is the
XML value that appears in payload. The Expires header indicates that
this response can be cached until 1PM January 1, 2009. The value of
standardized cache management headers is that web infrastructure (e.g.,
proxies, client software) can reduce network traffic and processing cost
by satisfying GET requests without a full client-server round-trip (and
subsequent server processing costs). For a great treatment on how HTTP
cache management works, go to Mark Nottingham’s tutorial at
http://www.mnot.net/cache_docs/
Expressing Additional Information
Applications
that receive an HTTP GET use the information embedded in the URI to
determine which resource to send as a reply. To illustrate, consider
this set of URIs:
contoso.com/artists/Flaming+Hammer/HitMe
contoso.com/artists/Northwind/Overdone
In
this case, Contoso Corporation has an application that serves resources
related to music. You can probably deduce from these examples how the
name of the artist and the name of the album can map into a URI:
contoso.com/artists/[artist]/[album]
When
the application receives an HTTP GET message for
http://contoso.com/artists/Northwind/Overdone, it should return a
resource related to Northwind's Overdone album. There's clearly a
pattern to the URI. It consists of some base information
(contoso.com/artists) and some URI segments (or "holes") that will
contain the values of the artist and album.
It
is also common to embed the same sort of information in query string
parameters. Though the format is different from the previous examples,
the end result is the same. Here is a set of URI holes with a query
string parameter:
contoso.com/artists/Flaming+Hammer?album=HitMe
contoso.com/artists/Northwind?album=Overdone
In this case, the URI and the query string are using the following syntax:
contoso.com/artists/[artist]?album=[album]
HTTP uses an extensible set of headers for expressing
additional information. This information can be related to caching, the
type of data in the message, the name of the sending application, the
length of the content, the host operating system, and much more. Figure 1 shows an HTTP GET message (lines 1-8) and the reply message (lines 9-14) with several common headers.

Figure 1 HTTP GET Request and Response
1 GET /PictureServices/Feed.svc/picture/Pictures;Bridge.jpg HTTP/1.1
2 Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,
application/x-ms-application, application/vnd.ms-xpsdocument,
application/xaml+xml, application/x-ms-xbap,
application/vnd.ms-excel, application/vnd.ms-powerpoint,
application/msword, application/x-shockwave-flash,
application/x-silverlight, */*
3 Accept-Language: en-us
4 UA-CPU: x86
5 Accept-Encoding: gzip, deflate
6 User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1;
.NET CLR 2.0.50727; InfoPath.2; .NET CLR 1.1.4322;
.NET CLR 3.5.20706; .NET CLR 3.0.590; MS-RTC LM 8)
7 Host: www.cloudsamples.net
8 Proxy-Connection: Keep-Alive
9 HTTP/1.1 200 OK
10 Content-Type: image/jpeg
11 Server: Microsoft-IIS/7.0
12 X-Powered-By: ASP.NET
13 Date: Sat, 15 Sep 2007 18:57:11 GMT
14 Content-Length: 106333
The
Accept header in the HTTP GET request indicates which data formats the
client would like to receive. As you can see from the long list of
values, the client can receive several kinds of data (images, office
documents, Silverlight apps, and so on). The response to the HTTP GET
contains data whose format is described by the value of the Content-Type
header (image/jpeg as shown on line 10). This simple mechanism allows
the sending and receiving application to coordinate data formats. Using
MIME types in headers for data format coordination is not as expressive
as the Web Services Description Language (WSDL) and XML Schema
Definition (XSD) grammars of SOAP Web services, but it's enough for the
Web.
REST and the Web
By looking at some key parts of HTTP, you have also seen some
of the important principles that hold the Web together. In 2000, a PhD
student named Roy Fielding finished a dissertation that, among other
things, codified these principles into an architectural style known as
Representational State Transfer (REST). (You can find Roy's dissertation
at
ics.uci.edu/~fielding/pubs/dissertation/top.htm.)
Books,
software conferences, and a seemingly innumerable collection of blogs
have discussed the REST architectural style in fine-grained detail. It's
not possible to cover all of its facets here, but the important
principles to take away are:
- Embrace the URI
- HTTP GET is special
- Content-Type is the data model
By
baking these principles into your applications, you dramatically
increase the interoperability and reach of your application's
functionality. Interoperability and reach are key drivers behind most
Web services initiatives. After all, a Web service is really a way to
expose some functionality via a structured messaging scheme. The
principles of the Web (HTTP request/response) are actually describing a
subset of possible messaging schemes. Practically all platforms,
applications, operating systems, and users understand the principles of
the Web, so embracing them in your Web service application gives it
improved reach and interoperability.
HTTP Programming with WCF
Building
on the foundation of these Web basics, let's take a look at using WCF
in the .NET Framework 3.5 to build applications that adhere to the
principles of the Web. I'll start by examining some of the new building
blocks of the HTTP programming model and progress upwards through the
system.
If
you're going to "embrace the URI," you will probably have to get used
to building and parsing URIs. When done by hand, this task is
error-prone and tedious. However, the new System.UriTemplate and
System.UriTemplateMatch types do the heavy lifting of creating and
parsing URIs, and are some of the fundamental building blocks for the
new HTTP capabilities of WCF.
The
UriTemplate type is the basic building block for defining the URI holes
discussed earlier. The constructor of the UriTemplate type accepts a
String that represents the holes in a URI. Once instantiated, a
UriTemplate object exposes two instance methods for binding text values
to the holes defined at instantiation. These methods return a URI whose
holes are populated with values.
A
UriTemplate object also exposes an instance method named Match for
extracting the values of the holes of a System.Uri object. The Match
instance method accepts two System.Uri objects. The first Uri is a base
address, and the second Uri is candidate for matching. A
System.UriTemplateMatch object is returned from the Match method. The
UriTemplateMatch object contains a collection of values for the holes
defined at UriTemplate instantiation time.
The code in Figure 2 illustrates how to use
the UriTemplate and UriTemplateMatch types to round-trip a Uri. The
result of this code is the following output:

Figure 2 Creating a Template-Based URI
// create a URI bound to the template
Uri baseAddress = new Uri(@"http://localhost:2000");
UriTemplate template = new UriTemplate("{artist}?album={album}");
Uri boundUri = template.BindByPosition(baseAddress, "Northwind",
"Overdone");
Console.WriteLine(boundUri.ToString());
// retrieve the value of the artist segment
UriTemplateMatch match = template.Match(baseAddress, boundUri);
String bandName = match.BoundVariables["artist"];
Console.WriteLine("the name of the artist is {0}", bandName);
http://localhost:2000/Northwind?album=Overdone
the name of the artist is Northwind
The
System.UriTemplate and System.UriTemplateMatch types are missing the
usual WCF System.ServiceModel moniker in the namespace. That's because
their functionality is such that you don't have to use them inside a WCF
application. They are quite handy anytime you need to create or parse a
URI.
Though
the UriTemplate and UriTemplateMatch types are quite easy to use, the
WCF team wanted to make it even easier to use these two types in a WCF
service. The goal was to offer a simple and intuitive way to map URI
segments and query string parameters into application functionality. I
think the model as shown in the following code fits the bill:
[ServiceContract]
public interface IPictureService
{
[OperationContract]
[WebGet(UriTemplate = "picture/{pictureId}")]
Stream GetPicture(String pictureId);
[OperationContract]
[WebGet(UriTemplate = "picture/t/{pictureId}")]
Stream GetPictureThumbnail(String pictureId);
}
The
UriTemplate surfaces as an instance property on the WebGetAttribute,
which, in turn, is applied to a service contract. Notice that the token
between the curly braces maps to the name of the method parameter.
Though this sample shows only one parameter, you can add many
parameters, arrange them in any order, add them as query string
parameters, and even use wildcards.
At
run time, the value of the UriTemplate property is passed to the
UriTemplate constructor. Both the Client runtime and the Dispatcher use
the UriTemplate property value in this manner. The Dispatcher uses it to
match incoming messages to an operation, and the Client uses it to
ensure that a method on a proxy gets sent to the right URI. It's an
easy-to-use, simple, and effective way to "embrace the URI" in your
services.
HTTP Verbs in WCF Contracts
HTTP
programming with WCF in the .NET Framework 3.5 makes it easy to map
operations in a service contract to HTTP verbs. As you can probably tell
from the name, applying the WebGetAttribute to an operation makes that
operation available via an HTTP GET. As you saw in the previous code
snippet, the WebGetAttribute defines an instance property named
UriTemplate.
There
are other instance properties on the WebGetAttribute type. The most
notable are RequestFormat and ResponseFormat. As their names imply, the
values of these properties dictate the message format for the operation.
The RequestFormat and ResponseFormat properties are of type
WebMessageFormat, an enumerated type that has two values: Xml and Json.
The WCF infrastructure uses the values of these properties to set up the
channel stack with the appropriate message encoder. A property value of
WebMessageFormat.Xml will result in a channel stack that uses the XML
encoder. Setting the value to WebMessageFormat.Json will result in a
channel stack that uses the JSON encoder included in the .NET Framework
3.5. Since there are properties for both sides of the HTTP message
exchange, it is possible for an application to receive an XML message
and return a JSON message (or vice-versa).
The other attribute related to HTTP verbs is
WebInvokeAttribute. Applying this attribute to an operation makes that
operation available by any HTTP verb other than HTTP GET. The separation
in the object model between HTTP GET and all other verbs reflects the
frequency HTTP GET is used versus the other HTTP verbs. The
WebInvokeAttribute object model is similar to the WebGetAttribute, but
it includes an instance property named Method. The value of this
property associates a particular HTTP verb to the operation. The Method
property is of type String, so you can set the value to any standard
HTTP verb, and even non-standard HTTP verbs. Figure 3 illustrates how to use the WebInvokeAttribute in a service contract.

Figure 3 Using WebInvokeAttribute
[ServiceContract]
public interface IPictureService
{
[OperationContract]
[WebGet(UriTemplate = "picture/{pictureId}")]
Stream GetPicture(String pictureId);
[OperationContract]
[WebGet(UriTemplate = "picture/t/{pictureId}")]
Stream GetPictureThumbnail(String pictureId);
[OperationContract]
[WebInvoke(UriTemplate="update", Method="POST")]
void UpdatePictureInfo(PictureInfo info);
}
The
UpdatePictureInfo method has a parameter of type PictureInfo. At run
time, a serialized version of a PictureInfo object is the payload of an
HTTP POST message. Passing data this way allows applications to ship
complex data types that are not otherwise expressible in a URI.
WCF
in the .NET Framework 3.5 also makes it easy to interact with HTTP
headers. Request and response HTTP headers are exposed via the
System.ServiceModel.Web.WebOperationContext type. The
WebOperationContext type is an extension of the
System.ServiceModel.OperationContext type introduced in WCF in the .NET
Framework 3.0, and its usage pattern is similar. Both are intended to be
used within the implementation of a service object. The
WebOperationContext type exposes members that simplify reading or
setting HTTP header values, as well as retrieving information about the
URI used to access the service object. The HTTP headers are stored as a
collection, and the most common ones are exposed as individual
properties. This example shows how to use the WebOperationContext type
to follow the data model of the Web by setting the Content-Type header
for an HTTP response:
public Stream GetPicture(string pictureId)
{
// retrieve the Stream (omitted)
Stream stream;
// set the Content-Type to image/jpeg
WebOperationContext.Current.OutgoingResponse.ContentType =
"image/jpeg";
return stream;
}
Binding and Hosting
So
far, you've seen how to map URI segments to application functionality,
how to map operations to HTTP verbs, and how to interact with HTTP
headers. Now let's see how to connect these features together into a
functioning service. To do this, you'll need to look at a few more types
that are new in WCF.
WCF
in the .NET Framework 3.0 introduced the concept of a binding, the
abstraction over the transport and protocols of an endpoint. The .NET
Framework 3.0 shipped with several bindings that included support for a
wide array of transport and protocol choices.
WCF
in the .NET Framework 3.5 includes a new binding named
System.ServiceModel.WebHttpBinding. This binding is the abstraction of
the principles of the Web and follows the same usage model as the
binding types in the .NET Framework 3.0, so you can add it to an
endpoint just like you would any other binding.
WCF
in the .NET Framework 3.0 also introduced the concept of an endpoint
behavior. A behavior is a way to extend the execution path of the
messaging infrastructure. There are several behaviors that ship with the
.NET Framework, and it is also easy to create your own.
WCF
in the .NET Framework 3.5 includes a new endpoint behavior named
System.ServiceModel.Description.WebHttpBehavior. This behavior does
several tasks. For receiving applications, it sets up the filtering
infrastructure to ensure, among other things, that received messages are
dispatched to the appropriate method on the service object. In the .NET
Framework 3.0 WCF used a combination of SOAP Action and target address
as dispatch keys. The filtering mechanism setup by the WebHttpBehavior
extends the existing filtering mechanisms to key off of UriTemplate
matches and HTTP verbs.
Figure 4
shows how you can use WebHttpBinding and WebHttpBehavior to build a
receiving application that embraces the principles of the Web. The
advantage of this approach is that you can add one of these endpoints to
an existing ServiceHost and by doing this you end up with one
ServiceHost that has both SOAP/WS-* endpoints and REST endpoints.

Figure 4 Using WebHttpBinding and WebHttpBehavior
ServiceHost host = new ServiceHost(typeof(IPictureContract),
new Uri("http://localhost:5000"));
// instantiate a WebHttpBinding
WebHttpBinding binding = new WebHttpBinding();
// add an endpoint, using the WebHttpBinding
ServiceEndpoint ep = host.AddServiceEndpoint(
typeof(IPictureContract), binding, String.Empty);
// add the WebHttpBehavior to the endpoint
ep.Behaviors.Add(new WebHttpBehavior());
// open the ServiceHost to start listening
host.Open();
Sending
applications follow the same usage model, but the WebHttpBehavior
should be added to the endpoint behavior collection on the
ChannelFactory<T> object. As per typical WCF practice, these
options are also available in configuration files.
WCF
in the .NET Framework 3.5 takes this easy-to-use model even further so
that you don't have to add either WebHttpBinding or WebHttpBehavior in
some cases. The new API includes two types that serve this purpose:
System.ServiceModel.Web.WebServiceHost and
System.ServiceModel.Web.WebServiceHostFactory. The WebServiceHost type
automatically adds the WebHttpBehavior to all endpoints and does some
extra validation at run time to ensure that all endpoints are compatible
with the behavior. This saves you the step of adding the
WebHttpBehavior to an endpoint.
The
WebServiceHostFactory type was designed for use in IIS-hosted scenarios
to remove the need for any imperative or configuration file hosting
information. WCF in the .NET Framework 3.0 introduced the .svc file as
an activation target for hosting WCF services in IIS. These files
contain directives that look similar to page directives in ASP.NET.
Adding WebServiceHostFactory to the Factory property of the .svc file
directive creates a ServiceHost, adds an endpoint that uses the
appropriate contract with the WebHttpBinding, adds WebHttpBehavior to
that endpoint, and opens the ServiceHost:
<%@ ServiceHost
Language="C#"
Service="PictureService"
Factory="System.ServiceModel.Web.WebServiceHostFactory" %>
The web.config file for the service does not contain any WCF-related entries.
The New Syndication API
Imagine
an RSS feed. If you are at all like me, you immediately think of a news
feed or a blog. Syndications—RSS and ATOM are syndication formats—are
able to express much more. In the abstract, syndicated content is simply
a way to represent a set of data. That set of data could be practically
anything: the number of wombats in residence within a 50-mile radius of
Sydney, the last 10 purchase orders over $100, or the number of
boomerangs Contoso produced last month.
The
.NET Framework 3.5 includes rich support for creating and consuming
syndicated content. It supports creating and consuming both RSS 2.0 and
ATOM 1.0 formats, various means of adding syndication extensions, and
even the capability to implement additional formats. The programming
model shields the developer from syndication format particulars, thereby
helping to make it easy to use.
Up
until version 3.5, there was no standard way to create or consume
syndicated content with the .NET Framework. Though the new syndication
functionality was written by the WCF team, it is not dependent on WCF.
In fact, all of the syndication-related types are part of the
System.Syndication namespace, though they reside in the
System.ServiceModel.Web.dll assembly. You can use the syndication
capabilities of the .NET Framework 3.5 from any process that hosts an
AppDomain (ASP.NET, WPF applications, NT Services, and so on). This
capability implies that you can serve or consume syndicated content over
any transport, not just HTTP. However, when coupled with the HTTP
programming model in WCF, you can add syndication to existing SOAP/WS-*
services as well.
The
new syndication API includes types that abstract an individual
syndication feed and the items in a feed, as well as types that can
transform that feed into a particular format. The
System.Syndication.SyndicationFeed type is a format-neutral
representation of a syndication feed. A SyndicationFeed contains a list
of SyndicationItem objects. A SyndicationFeed without a set of
SyndicationItem objects is like a pod without any peas, because a
SyndicationItem object is just a representation of an item in a feed.
Once
a SyndicationFeed has been populated with a set of SyndicationItem
objects, a SyndicationFeedFormatter<T> can transform that feed
into a particular format. There are two types derived from
SyndicationFeedFormatter<T>: Rss20FeedFormatter and
Atom10FeedFormatter. As their names imply, these types transform an
instance of a SyndicationFeed into the RSS 2.0 and ATOM 1.0 formats,
respectively.
Creating a SyndicationFeed
There
are two ways to create a SyndicationFeed object. You can instantiate
one and populate its members manually, or you can populate the entire
SyndicationFeed from an existing feed. Both are easy to do and shield
the developer from the quirks of a particular wire format. This code
demonstrates how to build a SyndicationFeed object manually.
SyndicationFeed feed = new SyndicationFeed();
feed.Title.Text = "The Cybertopian Chronicle";
Title is just one of many properties you can set, so check the documentation for additional possibilities.
It
is often the case that you want to read an existing feed and do
something based on the contents of that feed. In the new syndication
API, you can instantiate a SyndicationFeed and automatically populate
its state from an existing feed. All you need to start is the URI of the
existing feed or an XmlReader that's poised to read one. This code
shows how to connect to an existing feed on the Web and extract some
information from it:
Uri feedUri = new Uri("http://blogs.msdn.com/justinjsmith/atom.xml");
SyndicationFeed feed = SyndicationFeed.Load(feedUri);
Console.WriteLine(feed.Title.Text);
// outputs "The Cybertopian Chronicle"
The
SyndicationItem type contains more than 35 members. Many of these are
properties related to setting or retrieving fields like the item
identifier, last updated time, published date, title, or the actual
content. There are also numerous members that make it easy to extend the
content stored in a SyndicationItem. There are many extensions to RSS
and ATOM (Microsoft Simple List Extensions, Yahoo Media RSS, and GeoRSS,
among many others), and both SyndicationFeed and SyndicationItem can be
extended to include any existing RSS or ATOM extension.
Feeds
can have many items, and loading them all at once is not an option for
large feeds. The SyndicationFeed addresses this situation by exposing
its set of SyndicationItem object as an
IEnumerable<SyndicationItem>. This implementation makes it easier
to deal with large numbers of SyndicationItem objects because it
leverages the iterator capability of the .NET Framework 2.0. It's also
possible to iterate over a set of SyndicationItem objects using LINQ.
This can dramatically reduce the amount of code required to extract
information from a feed.
The syndication API defines several types that transform a
SyndicationFeed into the RSS 2.0 and ATOM 1.0 formats. In fact, you can
build one SyndicationFeed, populate it with SyndicationItem objects,
then expose that feed as both RSS and ATOM. Figure 5 demonstrates how to retrieve an ATOM 1.0 feed, transform it to RSS 2.0, and output the new RSS representation to the console.

Figure 5 Transforming a Feed
// read an ATOM feed
Uri feedUri = new Uri("http://blogs.msdn.com/justinjsmith/atom.xml");
SyndicationFeed feed = SyndicationFeed.Load(feedUri);
// transform it to RSS
Rss20FeedFormatter formatter = new Rss20FeedFormatter(feed);
XmlWriter writer = XmlWriter.Create(Console.Out, null);
// write it to the Console
formatter.WriteTo(writer);
writer.Flush();
When you partner the syndication API with the HTTP programming
model in WCF, you are able to expose a feed from a customized URI and
return RSS or ATOM based on the composition of that URI. Figure 6
shows how to define an operation in a service contract that uses a
query string parameter from a received HTTP GET to return either an RSS
or an ATOM feed. Notice the use of the
SyndicationFeedFormatter<SyndicationFeed> in the operation
contract. Both Rss20FeedFormatter and Atom10FeedFormatter derive from
SyndicationFeedFormatter<TSyndicationFeed>.

Figure 6 Exposing a Feed from a Customized URI
[ServiceKnownType(typeof(Atom10FeedFormatter))]
[ServiceKnownType(typeof(Rss20FeedFormatter))]
[ServiceContract]
interface IPictureService {
[OperationContract]
[WebGet(UriTemplate="Pictures?format={format}")]
SyndicationFeedFormatter<SyndicationFeed> Feed(String format);
}
class PictureService : IPictureService {
public SyndicationFeedFormatter<SyndicationFeed> Feed(String format){
// create the syndication feed
SyndicationFeed feed = new SyndicationFeed();
// add the items to the feed (omitted)
// check the argument & return the right format
if(format.ToLower() == "rss"){
return new Rss20FeedFormatter(feed);
}
return new Atom10FeedFormatter(feed);
}
}
Tying It All Together
To summarize, you've seen some of the basics of HTTP, how this
relates to principles of the Web, how to use WCF to bake those
principles into your application, and how to use the new syndication API
to serve and consume RSS and ATOM feeds. To further demonstrate the
capabilities of these new features, you can see them running together in
a sample application called PictureServices at
www.cloudsamples.net/pictureservices. You can run the sample online,
browse the source code, and download the entire sample. Figure 7 shows PictureServices in action.
Figure 7 The PictureServices Feed (Click the image for a larger view)
In
a nutshell, PictureServices can retrieve pictures from a local machine
or from a Flickr feed. The application uses a simple provider model, and
there are currently three providers: Windows Desktop Search, a folder
on your file system, and Flickr. Once PictureServices retrieves the
files from a provider, it syndicates those pictures and serves them
locally. From a browser you can click through a feed and retrieve
individual pictures. There's quite a bit more in the sample, so feel
free to explore. For links to more information about the technologies
discussed here, see the "Additional Resources" sidebar in this article.
Justin Smith
works at Microsoft as a Technical Evangelist devoted to Web
services. His areas of focus are WCF and BizTalk Services. Justin is
also the author of Inside Windows Communication Foundation (Microsoft
Press, 2007) and a frequent presenter at software development
conferences. Read his blog at
blogs.msdn.com/justinjsmith.
No comments:
Post a Comment
hi Happy Reading.......................