How to access a web feed (HTML)

[This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation]

This topic shows how to retrieve and display a web feed using classes in the Windows.Web.Syndication namespace in your Windows Runtime app.

Prerequisites

The following examples use JavaScript and are based on the Syndication sample. For general help creating a Windows Runtime app using JavaScript, see Create your first Windows Runtime app using JavaScript. Additionally, JavaScript promises are used in this topic to complete asynchronous operations. For more information on this programming pattern, see Asynchronous programming in JavaScript using promises.

To ensure your Windows Runtime app is network ready, you must set any network capabilities that are needed in the project Package.appxmanifest file. If your app needs to connect as a client to remote services on the Internet, then the Internet (Client) capability is needed. If the app needs to connect as a client to remote services on a home network or work network, then the Home/Work Networking capability is needed. For more information, see How to set network capabilities.

Instructions

Retrieving a syndicated content from a web feed

Now we will review some code that demonstrates how to retrieve a feed, and then display each individual item that the feed contains. Before we can configure and send the request, we'll define a few variables we'll be using during the operation, and initialize an instance of SyndicationClient, which defines the methods and properties we'll use to retrieve and display the feed.

The Uri constructor throws an exception if the uriString passed to the constructor is not a valid URI. So we validate the uriString using a try/catch block.

var currentFeed = null;
var currentItemIndex = 0;
        
var client = new Windows.Web.Syndication.SyndicationClient();

// The URI is validated by catching exceptions thrown by the Uri constructor.
var uri = null;
try {
    uri = new Windows.Foundation.Uri(uriString);
} catch (error) {
    WinJS.log && WinJS.log("Error: Invalid URI");
    return;
}

Next we configure the request by setting any Server credentials (the serverCredential property), proxy credentials (the proxyCredential property), and HTTP headers (the setRequestHeader method) needed. With the basic request parameters configured, a valid Uri object, created using a feed URI string provided by the app. The Uri object is then passed to the retrieveFeedAsync function to request the feed.

Assuming the desired feed content was returned, the code iterates through each feed item, calling displayCurrentItem (which we define next), to display items and their contents as a list through the UI.

You must write code to handle exceptions when you call most asynchronous network methods. Your exception handler can retrieve more detailed information on the cause of the exception to better understand the failure and make appropriate decisions. For more information, see How to handle exceptions in network apps.

The retrieveFeedAsync method throws an exception if a connection could not be established with the HTTP server or the Uri object does not point to a valid AtomPub or RSS feed. The sample code uses an onError function to catch any exceptions and print out more detailed information on the exception if an error occurs.

function onError(err) {
    WinJS.log && WinJS.log(err, "sample", "error");

    // Match error number with a ErrorStatus value.
    // Use Windows.Web.WebErrorStatus.getStatus() to retrieve HTTP error status codes.
    var errorStatus = Windows.Web.Syndication.SyndicationError.getStatus(err.number);
    if (errorStatus === Windows.Web.Syndication.SyndicationErrorStatus.invalidXml) {
        displayLog("An invalid XML exception was thrown. Please make sure to use a URI that points to a RSS or Atom feed.");
    }
}

// Retrieve and display feed at given feed address.
function retreiveFeed(uri) {

    // Although most HTTP servers do not require User-Agent header, 
    // others will reject the request or return a different response if this header is missing.
    // Use the setRequestHeader() method to add custom headers.
    client.setRequestHeader("User-Agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");

    client.retrieveFeedAsync(uri).done(function (feed) {
        currentFeed = feed;

        WinJS.log && WinJS.log("Feed download complete.", "sample", "status");

        var title = "(no title)";
        if (currentFeed.title) {
            title = currentFeed.title.text;
        }
        document.getElementById("CurrentFeedTitle").innerText = title;

        currentItemIndex = 0;
        if (currentFeed.items.size > 0) {
            displayCurrentItem();
        }

        // List the items.
        displayLog("Items: " + currentFeed.items.size);
     }, onError);
}

In the previous step, retrieveFeedAsync returned the requested feed content and the example code got to work iterating through available feed items. Each of these items is represented using a SyndicationItem object that contains all of the item properties and content afforded by the relevant syndication standard (RSS or Atom). In the following example we observe the displayCurrentItem function working through each item and displaying its content through various named UI elements.

function displayCurrentItem() {
    var item = currentFeed.items[currentItemIndex];

    // Display item number.
    document.getElementById("Index").innerText = (currentItemIndex + 1) + " of " + currentFeed.items.size;

    // Display title.
    var title = "(no title)";
    if (item.title) {
        title = item.title.text;
    }
    document.getElementById("ItemTitle").innerText = title;

    // Display the main link.
    var link = "";
    if (item.links.size > 0) {
        link = item.links[0].uri.absoluteUri;
    }

    var link = document.getElementById("Link");
    link.innerText = link;
    link.href = link;

    // Display the body as HTML.
    var content = "(no content)";
    if (item.content) {
        content = item.content.text;
    }
    else if (item.summary) {
        content = item.summary.text;
    }
    document.getElementById("WebView").innerHTML = window.toStaticHTML(content);

As suggested earlier, the type of content represented by a SyndicationItem object will differ depending on the feed standard (RSS or Atom) employed to publish the feed. For example, an Atom feed is capable of providing a list of contributors, but an RSS feed is not. However, extension elements included in a feed item that are not supported by either standard (e.g., Dublin Core extension elements) can be accessed using the SyndicationItem.elementExtensions property and then displayed as demonstrated in the following example code:


    // displayCurrentItem function continued
    var bindableNodes = [];
    for (var i = 0; i < item.elementExtensions.size; i++) {
        var bindableNode = {
            nodeName: item.elementExtensions[i].nodeName,
             nodeNamespace: item.elementExtensions[i].nodeNamespace,
             nodeValue: item.elementExtensions[i].nodeValue,
        };
        bindableNodes.push(bindableNode);
    }

    var dataList = new WinJS.Binding.List(bindableNodes);
    var listView = document.getElementById("extensionsListView").winControl;
    WinJS.UI.setOptions(listView, {
        itemDataSource: dataList.dataSource

    });
}

Summary and next steps

In this topic, we retrieved a feed associated with a supplied URI, and displayed the feed content item by item.

For more advanced features like the ability to add, edit, and delete entries within a web feed, see How to manage web feed entries.

Other

Asynchronous programming in JavaScript using promises

How to set network capabilities

How to handle exceptions in network apps

How to manage web feed entries

Roadmap for Windows Runtime apps using JavaScript using JavaScript

Reference

SyndicationClient

SyndicationItem

Windows.Web.AtomPub

Windows.Web.Syndication

Samples

AtomPub sample

Syndication sample