How to manage web feed entries (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 access a service document and modify the feed resources it contains using the Windows.Web.AtomPub namespace, which is the Windows Runtime implementation of the Atom Publication Protocol.

Prerequisites

The following examples use JavaScript and are based on the AtomPub 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

1. Service documents

Before we review the example code, it helps to have a basic understanding of how service documents are used to define the structure of feed content for a web service.

The service document encapsulates at least one workspace element, which represents one or more collections. In other words, web publications like personal blogs and web pages are considered workspaces, and the contained collections represent individual feeds; each containing a number of entries.

The following syntax is a short example of a service document:

<?xml version="1.0" encoding='utf-8'?>
<service xmlns="http://www.w3.org/2007/app"
         xmlns:atom="http://www.w3.org/2005/Atom">
    <workspace>
        <atom:title>Main Site</atom:title>
        <collection
            href="http://example.org/blog/main" >
            <atom:title>My Blog Entries</atom:title>
            <categories
               href="http://example.com/cats/forMain.cats" />
        </collection>
        <collection
            href="http://example.org/blog/pic" >
            <atom:title>Pictures</atom:title>
            <accept>image/png</accept>
            <accept>image/jpeg</accept>
            <accept>image/gif</accept>
        </collection>
    </workspace>
</service>

To retrieve a service document, pass the associated Uri to retrieveServiceDocumentAsync. To retrieve, edit, or delete specific feed entries an app will need to parse a retrieved ServiceDocument for the absolute URIs associated with individual entries.

2. Initializing the client with authentication credentials

The following examples use classes in the Windows.Web.AtomPub namespace for feed management operations, and classes in the Windows.Web.Syndication namespace to represent individual feed elements. Additionally, most web publication services will require some form of authentication, features provided by the Windows.Security namespace.

The following example demonstrates how to set credentials and include them in the initialization of an AtomPubClient instance.


//define some variables

// The default values for the site.
var baseUri = "http://<Your Wordpress Site>.wordpress.com/";
var user = "";
var password = "";

// The default Service Document and Edit 'URIs'
var editUri = "./wp-app.php/posts";
var serviceDocUri = "./wp-app.php/service";
var feedUri = "./?feed=atom";
var currentFeed = null;
var currentItemIndex = 0;
        
var client;

var item;

// Get current credentialS and create the AtomPub client
function createClient() {
    client = new Windows.Web.AtomPub.AtomPubClient();
    // Don't save the results to the client's cache
    client.bypassCacheOnRetrieve = true;

    if ((user !== "") && (password !== "")) {
        var credential = new Windows.Security.Credentials.PasswordCredential();
        credential.userName = user;
        credential.password = password;
        client.serverCredential = credential;
    }
    else {
        client.serverCredential = null;
    }
}

3. Creating a new post within a collection

A new post can be added to an existing collection by creating a new SyndicationItem object and populating it with the desired content. When the SyndicationItem is ready, pass the object, a short string describing the entry, and the feed Uri to createResourceAsync method on the AtomPubClient.

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.

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 createResourceAsync 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.

// Called when an async function generates an error.
function onError(err) {
    displayError(err);

    // Match error number with a WebErrorStatus value, in order to deal
    // with a specific error.
    var errorStatus = Windows.Web.WebError.getStatus(err.number);
    if (errorStatus === Windows.Web.WebErrorStatus.unauthorized) {
        displayLog("Wrong username or password!");
    }
}

function createPost (uriString, postTitle, postContent, postSummary, postAuthor) {

    var resourceUri;
    try {
        resourceUri = new Windows.Foundation.Uri(uriString);
    } catch (error) {
        displayLog("Error: Invalid URI");
    return;

    var syndicationItem;

    item = new Windows.Web.Syndication.SyndicationItem();
    item.title = new Windows.Web.Syndication.SyndicationText(postTitle);
    item.summary = new Windows.Web.Syndication.SyndicationText(postSummary);
    item.content = new Windows.Web.Syndication.SyndicationContent(postContent, Windows.Web.Syndication.SyndicationTextType.Text);
    item.authors[0] = new Windows.Web.Syndication.SyndicationPerson(postAuthor);
    // Note: Also other item fields can be set such as 'syndicationItem.Categories[0]'

    return client.createResourceAsync(resourceUri, item.title.text, item);
}).done(function (result) {
    if (result) {
        displayLog("Posted at " + result.editUri.displayUri);
        displayLog("New post created.");
    }
 }, onError);

4. Editing a post within a collection

To edit an existing entry in a collection, pass the associated Uri to the retrieveFeedAsync method on the SyndicationClient. Prepare a SyndicationItem with new values, and pass the object to updateResourceAsync on the AtomPubClient along with the Uri used to retrieve the entry.

function editPost (uriString, postTitle, postContent, postSummary, postAuthor) {

    var resourceUri;
    try {
        resourceUri = new Windows.Foundation.Uri(uriString);
    } catch (error) {
        displayLog("Error: Invalid URI");
    return;

    var updatedItem = new Windows.Web.Syndication.SyndicationItem();
    updatedItem.title = new Windows.Web.Syndication.SyndicationText(postTitle);
    updatedItem.summary = new Windows.Web.Syndication.SyndicationText(postSummary);
    updatedItem.content = new Windows.Web.Syndication.SyndicationContent(postContent, Windows.Web.Syndication.SyndicationTextType.Text);
    updatedItem.authors[0] = new Windows.Web.Syndication.SyndicationPerson(postAuthor);
    // Note: Also other item fields can be set such as 'syndicationItem.Categories[0]'

    client.updateResourceAsync(resourceUri, updatedItem).done(function () {
        displayLog("Updating item completed.");
    }
 }, onError);
}

5. Deleting a post from a collection

To delete an entry from a collection pass the editUri property from the SyndicationItem instance to deleteResourceItemAsync method on the AtomPubClient instance.

function deletePost(uriString, currentFeed) {

    var resourceUri;
    try {
        resourceUri = new Windows.Foundation.Uri(uriString);
    } catch (error) {
        displayLog("Error: Invalid URI");
    return;

   // If we retrieve the feed via the resourceUri then we will be logged in and will be
   // able to modify/delete the resource.

   client.retrieveFeedAsync(resourceUri).done(function (feed) {
       currentFeed = feed;
       currentItemIndex = 0;

       displayLog("Got feed");
       var title = "(no title)";
       if (currentFeed.title) {
           title = currentFeed.title.text;
       }
       displayLog("Title: " + title);

       var currentItem = getCurrentItem();
       if (currentItem) {
           displayLog("EditUri: " + currentItem.editUri);
       }

       displayStatus("Fetching feed completed.");
   }, onError);
    
   client.deleteResourceItemAsync(currentItem).done(function() {
       displayLog("Deleting item completed.");
    
       // Our feed is now out of date.  Re-fetch the feed before deleting something else.
       currentFeed = null;
    }, onError);
    }

Summary and next steps

In this topic we retrieved a service document, added new collection entries, modified existing collection entries, and deleted collection entries within that document. For a quick demonstration of basic feed retrieval, see How to access a web feed.

Other

Asynchronous programming in JavaScript using promises

How to set network capabilities

How to handle exceptions in network apps

How to access a web feed

Roadmap for Windows Runtime apps using JavaScript using JavaScript

Reference

AtomPubClient

SyndicationItem

Windows.Web.AtomPub

Windows.Web.Syndication

Samples

AtomPub sample

Syndication sample