Internet Explorer
Development and news about IE
Events are being served to the belgian community. First of all we have the Msdn Event on Dotnet Framework 3.0, and like Tom says be quick to get the last seats. And should you want more, there is more like Wim says in his blog, a msdn evening session on IE7 for developers, Cyra Richardson the lead program manager for Layout and Rendering for the IE team will be talking about the new features of IE7, register here.
And for the Framework 3.0 freaks, there is a Microsoft Pre-Release Software Microsoft .NET Framework 3.0 - Release Candidate released on 01/09/2006 and it works with Orcas. Should you have any problems, suggestions or errors give feedback on the Microsoft Feedback site, on the following urls
I know I promised an updated version of the really simple sample, but I got hooked on the Simple List Extensions. So first I'm going to give a small sample on SLE combined with the Microsoft Feeds API. In our company we develop call center solutions and a small part of the application is a scoreboard, this scoreboard gives the scores of all projects and agents, how good is a project and what is an agent scoring. These scores are calculated by an application and every project as a custom algorithm, some of the calculations take minutes to finish since historical data is sometimes needed. At this moment this application stores the scores in a sql table, another application the scoreboard loops through the table and showes the scores in a graphical manner. This way you can start multiple scoreboards without more load on the sql databases. At this time managers asked too see the the scores at home, "get it online" as they say. Well this is where SLE comes in play, generate an rss feed from the calculator application and your done, the scoreboard application only uses the rss feeds as source. No impact on the sql server and rss is readable without a custom application from any location.
Great, the following sample is a prove of concept and I wanted to share this with you all.
First of all we need a feed, just put an xml file on a webfolder and you have a feed. the following is an example of such an xml file.
It looks like a regular rss file but we added the cf:treatAs element, this element informs the Rss Platform Engine that this rss stream is a list. More over we can add additional sorting with the cf:sort element. The rss feed now looks like this in IE7, we see the sorting in action through the "The Agent" and "The Score" buttons.

Of course this is all great, but what if we wanted to use this feed in a custom application. As an example I will show you how to load the items in a listbox, and what is more the listbox will be updated every time the feed is downloaded. The application contains two major methods "BindFeedEvents" and "UpdateScoreBoard". First of all we are going to look at the UpdateScoreBoard method, this method loads the feed and gets the items of the feed, once it has an item it reads the score and agent elements from the scoreboard namespace. In order to read these items we need to read the xml stream from the item, there is no way to get the elements (why not ? This would be a great feature on the next release of the Feeds API). We load the xml in a document and select the nodes through an XPath expression, do not forget to add a NamespaceManager because we are using a different namespace than the default namespace. Here's the code.
private void UpdateScoreBoard() {
ListBox1.Items.Clear();
IFeedsManager manager = new FeedsManagerClass();
IFeedFolder rootFolder = (IFeedFolder)manager.RootFolder;
IFeed feed = (IFeed)rootFolder.GetFeed("ScoreBoard Project1");
foreach (IFeedItem item in (IFeedsEnum)feed.Items) {
XmlDocument document = new XmlDocument();
document.LoadXml(item.Xml(FEEDS_XML_INCLUDE_FLAGS.FXIF_NONE));
XmlNamespaceManager namespaceManager = new XmlNamespaceManager(document.NameTable);
namespaceManager.AddNamespace("scoreboard", "http://www.widec.be/blog/rss/samples/scoreboard");
XmlNode scoreNode = document.SelectSingleNode("item/scoreboard:score", namespaceManager);
XmlNode agentNode = document.SelectSingleNode("item/scoreboard:agent", namespaceManager);
if (scoreNode != null && agentNode != null) {
ListBox1.Items.Add(agentNode.InnerText + " - " + scoreNode.InnerText);
}
}
}
Since we want the listbox to be updated once the Rss Platform Engine refreshes the feed we need to bind events on the feed. We do this like I previously showed in my post "Microsoft Feeds API, event handlers", if you want an example in VB.Net there is one on the RSS team blog called Events in VB.NET. Again I have declared an IFeedEvents_Event interface on the form, this interface will hold the eventwatcher from the feed. How this is done is showed in the following code.
private void BindFeedEvents() {
IFeedsManager manager = new FeedsManagerClass();
IFeedFolder rootFolder = (IFeedFolder)manager.RootFolder;
IFeed feed = (IFeed)rootFolder.GetFeed("ScoreBoard Project1");
FeedEvents = (IFeedEvents_Event)feed.GetWatcher(FEEDS_EVENTS_SCOPE.FES_SELF_ONLY,
FEEDS_EVENTS_MASK.FEM_FEEDEVENTS);
FeedEvents.FeedDownloadCompleted +=
new IFeedEvents_FeedDownloadCompletedEventHandler(Feed_FeedDownloadComplete);
}
All we need to do now is declare an event handler to execute the code we want and we want the scoreboard to be updated. Here's the handler.
private void Feed_FeedDownloadComplete(string path, FEEDS_DOWNLOAD_ERROR error) {
UpdateScoreBoard();
}
After the InitializeComponent call in the constructor of the form you place a call to BindFeedEvents method and when you start the form you are instantly connected with updates on the feed. The complete source of the application is availlable here.
When coding this sample I had the following remarks.
- Why is the Feeds API not managed code ? This would be much easier to code and hey we live in 2006, why create solutions in COM ?
- Why is there no way to get custom elements out of the items, in a managed assembly this would be as easy as 1 + 1 = 2, as I showed in this sample.
- The possibilities of the feeds API go way beyond reading posts of blogs. It's a whole new way of thinking and developing, a big thanks to the RSS team, great work !!!
Allright, It has been 3 months now since my latest post, but I'm back. Been busy working with some projects and I have new stuff ready. Since the RSS team released a new beta I'm going to get my sample on the Microsoft Feeds API up-to-date on the new release. If you can't wait for the sample to finish (planned this weekend) you can already checkout the RssTeam blog for more information.
For the Belgian community check out the new msdn event on ".Net Framework 3.0 Development"
I also want to thank Jay A. Allen for his praising words on my Micrsoft Feeds API: Really Simple Sample posts. I'm looking forward to his "river of news" approach sample which will be without doubt a sensational sample.
Like promised the next episode of the Really Simple Sample. In this episode I will present the next step of importing and exporting feed lists through an xml file. The format can now handle recursive folders and feeds like it is supposed to be. I have coded the FeedImportExport class, an instance of this class can import and export feeds and folders from/to an xml file, it makes use of the data classes FeedData, FeedFolderData and FeedImports.
using System;
using System.Collections.Generic;
using System.Text;
namespace Widec.Feeds{
public class FeedData {
[System.Xml.Serialization.XmlAttribute("name")]
public string Name;
[System.Xml.Serialization.XmlAttribute("url")]
public string Url;
}
public class FeedFolderData {
[System.Xml.Serialization.XmlAttribute("name")]
public string Name;
[System.Xml.Serialization.XmlElement("feed")]
public List Feeds;
[System.Xml.Serialization.XmlElement("folder")]
public List Folders;
}
[System.Xml.Serialization.XmlRoot("mfi")]
public class FeedImports {
[System.Xml.Serialization.XmlElement("folder")]
public List Folders;
[System.Xml.Serialization.XmlElement("feed")]
public List Feeds;
public static FeedImports Deserialize(string filename) {
using (System.IO.FileStream stream = new System.IO.FileStream(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read)) {
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(FeedImports));
return (FeedImports)serializer.Deserialize(stream);
}
}
public void Serialize(string filename) {
using (System.IO.FileStream stream = new System.IO.FileStream(filename,
System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite)) {
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(FeedImports));
serializer.Serialize(stream,this);
}
}
}
}
The FeedImportExport class is a basic recursive import and export reader/writer. You use the Import and Export method to do your work, these methods call the recursive ImportFeed/ExportFeed and ImportFeedFolder/ExportFeedFolder methods. The Export method has one additional feature, it splits the pathname of the FeedFolder and generates the needed folder elements in the xml.
using System;
using System.Collections.Generic;
using System.Text;
using Feeds;
namespace Widec.Feeds {
public class FeedImportExport{
public void Import(FeedImports import) {
IFeedsManager manager = new FeedsManagerClass();
IFeedFolder rootFolder = (IFeedFolder)manager.RootFolder;
if (import.Folders != null) {
foreach (FeedFolderData folderData in import.Folders) {
ImportFeedFolder(folderData, rootFolder);
}
}
if (import.Feeds != null) {
foreach (FeedData feedData in import.Feeds) {
ImportFeed(feedData, rootFolder);
}
}
}
public FeedImports Export(string folderPath) {
FeedImports import = new FeedImports();
import.Folders = new List();
IFeedsManager manager = new FeedsManagerClass();
IFeedFolder exportFolder = (IFeedFolder)manager.GetFolder(folderPath);
string[] Folders = folderPath.Split('\\');
FeedFolderData data = null;
foreach (string folderName in Folders) {
FeedFolderData folderData = new FeedFolderData();
folderData.Name = folderName;
if (data == null){
import.Folders.Add(folderData);
}else{
data.Folders = new List();
data.Folders.Add(folderData);
}
data = folderData;
}
foreach (IFeed feed in (IFeedsEnum)exportFolder.Feeds) {
ExportFeed(feed, data);
}
foreach (IFeedFolder folder in (IFeedsEnum)exportFolder.Subfolders) {
ExportFeedFolder(folder, data);
}
return import;
}
private void ExportFeed(IFeed feed, FeedFolderData folderData) {
if (folderData.Feeds == null) {
folderData.Feeds = new List();
}
FeedData data = new FeedData();
data.Name = feed.name;
data.Url = feed.url;
folderData.Feeds.Add(data);
}
private void ExportFeedFolder(IFeedFolder folder, FeedFolderData folderData) {
if (folderData.Folders == null) {
folderData.Folders = new List();
}
FeedFolderData current = new FeedFolderData();
current.Name = folder.name;
folderData.Folders.Add(current);
foreach (IFeedFolder subFolder in (IFeedsEnum)folder.Subfolders) {
ExportFeedFolder(subFolder, current);
}
foreach (IFeed feed in (IFeedsEnum)folder.Feeds) {
ExportFeed(feed, current);
}
}
private void ImportFeed(FeedData data, IFeedFolder folder){
if (!folder.ExistsFeed(data.Name)) {
folder.CreateFeed(data.Name, data.Url);
}
}
private void ImportFeedFolder(FeedFolderData data, IFeedFolder folder){
IFeedFolder importFolder;
if (folder.ExistsSubfolder(data.Name)) {
importFolder = (IFeedFolder)folder.GetSubfolder(data.Name);
} else {
importFolder = (IFeedFolder)folder.CreateSubfolder(data.Name);
}
if (data.Feeds != null) {
foreach (FeedData feedData in data.Feeds) {
ImportFeed(feedData, importFolder);
}
}
if (data.Folders != null) {
foreach (FeedFolderData folderData in data.Folders) {
ImportFeedFolder(folderData, importFolder);
}
}
}
}
}
Really simple, but a very handy class. Next time I will create a form to view, import and export the Common Feed List and show how to use the FeedEnclosure.AsyncDownload and FeedEnclosure.CancelAsyncDownload, so stay tuned. At that time I will include the complete sample code.
A nice extention on IE7 is the developer toolbar, this toolbar has some nice features for developers. Forget the view source menuitem, make some place in your brain for new stuff.
Some features are
- The toolbar will show you the complete DOM of the document and while you're browsing the DOM in a treeview, it will indicate the current element in the webpage and if you don't like to browse the DOM then click an item on the page and that element will be shown in the DOM including all properties of that element.
- You can disable "Cache", "Images", "Cookies","Scripts","Popup Blocker" and "All CSS".
- You can show all class names, id's, links, tab indexes and access keys. Very handy when testing the UI or debugging why some element get's rendered in a strange way.
- You can indicate all elements in a page with a specific color.
- You can show image dimensions, filesize, path, alt text and an image report, which gives a detailed report about the images on a page.
- You can resize the window to a specific size (800x600,1024x768...)
- You can validate your html, css, feed, links and more.
- You can mesuare the distance in pixels between elements.
So, it seems that there is a new tool for serious developers, get it at Microsoft downloads
I'm working on an extended version of the "Really Simple Sample", so stay tuned for more...
In the post "Vista takes rss to the next level" I already talked about the integration of RSS in IE7, that was almost 6 months ago and now there is the long awaited API. It was worth waiting. Through the API called "Microsoft Feeds API" you can control feeds in the operating system, yes the operating system, make no mistake IE7 RSS integration is a layer on top of the Common Feed List in the operating system. This is the power of the Common Feed List, it is integrated in the OS and available to all applications, manageable through an API.
Because I was already excited by this new feature I'm now going to present a little sample. The sample takes an import file and generates the feeds in the Common Feed List, can be really useable for exchanging feeds between friends.
The application is a Windows Forms application with 1 button, if you press the button you can select an import file and this xml file will be deserialized. All feeds will be added to the Common Feed List.
The xml file is deserialized to the following objects.
public
class FeedData {
[System.Xml.Serialization.XmlAttribute("name")]
public string Name; [System.Xml.Serialization.XmlAttribute("url")]
public string Url;}
public class FeedFolderData { [System.Xml.Serialization.XmlAttribute("name")]
public string Name; [System.Xml.Serialization.XmlElement("feed")]
public List Feeds;
}
[System.Xml.Serialization.XmlRoot("mfi")]
public class FeedImports { [System.Xml.Serialization.XmlElement("folder")]
public List Folders;
public static FeedImports Deserialize(string filename) { using (System.IO.FileStream stream = new System.IO.FileStream(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read)) { System.Xml.Serialization.XmlSerializer serializer =
new System.Xml.Serialization.XmlSerializer(typeof(FeedImports)); return (FeedImports)serializer.Deserialize(stream);
}
}
Through this really simple format we can import xml files, the ImportFeeds method on the form does just that. It start with creating the FeedsManager the manager of Common Feed List, once we have this we can start manipulating the feeds. Then the method get the rootfolder of the Common Feed List, in this folder you can create feeds or subfolders just like in your favourites. Then we run over all folder and feed imports and create the folders or feeds if needed.
private
void ImportFeeds(FeedImports imports) { // Create the feedmanager class. IFeedsManager manager =
new FeedsManagerClass();
// Get the root folder of all feeds on the system. IFeedFolder rootFolder = (IFeedFolder)manager.RootFolder;
if (imports.Folders == null) { return; }
foreach(FeedFolderData folderData in imports.Folders){ IFeedFolder folder;
if (rootFolder.ExistsSubfolder(folderData.Name)) { folder = (IFeedFolder)rootFolder.GetSubfolder(folderData.Name);
}
else{ folder = (IFeedFolder)rootFolder.CreateSubfolder(folderData.Name);
}
if (folderData.Feeds == null) { continue; }
foreach (FeedData feedData in folderData.Feeds) { if (!folder.ExistsFeed(feedData.Name)) { folder.CreateFeed(feedData.Name, feedData.Url);
}
}
}
Working with the Feeds API is really simple, you can also control the shedules of every feed, download enclosures, get the image of a feed and much more. For a complete overview of the API go to Microsoft Feeds API on msdn and to keep track of the latest updates and changes go to Team RSS Blog.
If you want to test the sample or experiment with it you can download it here, included is an import file with the rss feeds from Belgian Bloggers, this way you can quickly test the sample and also complete your feeds list.
Did someone noticed this, not only did Longhorn become Windows Vista, but also "Microsoft Internet Explorer" became "Windows Internet Explorer". Is this a silent hint that IE7 will integrate even better with windows? If it is then I'm looking forward to it, because this is how software should be build, tightly integrated with all other software of the system so users can learn to work with software in a unified manner and make the learning curve less steep.
The Internet Explorer development team has launched a new MSDN column called "Exploring Internet Explorer" and here you will find answers to the riddles and mysteries of Internet Explorer as they put it so well. The first article is about
Zones and Proxies where Eric Lawrence talks about the Local Intranet Zone or LIZ in short in combination with Proxies.