Entries in XML (8)
Silverlight 2.0 Video Tutorials
Silverlight 2.0 provides a new and exciting framework for building rich applications using C#, VB.NET or other languages that are capable of running on multiple operating systems and in multiple browsers. Scott Guthrie recently posted a great set of tutorials on Silverlight 2.0 that are an excellent resource for getting started building Silverlight 2.0 applications.
Scott recently approved converting the tutorials into video so I've been busy the past few days putting together video tutorials that cover Silverlight 2.0 and the Digg.com application Scott wrote about. Links to the written tutorials and video tutorials are shown below.
Silverlight 2.0 Video Tutorials
| Part 1: Creating "Hello World" with Silverlight 2 and VS 2008 | Tutorial | Video Tutorial |
| Part 2: Using Layout Management | Tutorial | Video Tutorial |
| Part 3: Using Networking to Retrieve Data and Populate a DataGrid | Tutorial | Video Tutorial |
| Part 4: Using Style Elements to Better Encapsulate Look and Feel | Tutorial | Video Tutorial |
| Part 5: Using the ListBox and DataBinding to Display List Data | Tutorial | Video Tutorial |
| Part 6: Using User Controls to Implement Master/Details Scenarios | Tutorial | Video Tutorial |
| Part 7: Using Templates to Customize Control Look and Feel | Tutorial | Video Tutorial |
| Part 8: Creating a Digg Desktop Version of our Application using WPF | Tutorial | Video Tutorial |
View other cool videos on Silverlight 2.0 and additional .NET technologies from the Mix 08 conference:
Upcoming .NET Courses in 2008

I've had several people here in the Phoenix area and others I've met at ASP.NET Connections conferences ask when I'll be teaching specific .NET classes in 2008 and my standard reply has been "I'm not sure at this point". We have things scheduled out past June now so here's the information for those who are interested. Most of the classes listed are 5 days aside from the First Look at Visual Studio 2008 (1 day) and ASP.NET AJAX Programming (3 days).
- ASP.NET 2.0 Programming - January 14th
- First Look at Visual Studio 2008 - January 29th
- Advanced C# Programming with the .NET Framework 2.0 - February 4th
- Distributed Development with VS 2005 - February 11th
- Intro to C# Using Visual Studio 2005 - March 3rd
- Advanced C# Programming with the .NET Framework 2.0 - March 31st
- ASP.NET AJAX Programming - April 7th
- First Look at Visual Studio 2008 - June 23rd
The schedule is of course subject to change, but it's what I have at this point. If you have any questions about any of the courses feel free to contact me through my blog.
XSLT 2.0, XPath 2.0, XQuery and WSDL Support in XMLSpy 2007
I've always been a fan of Altova's XMLSpy and have used it since it was first released. Their release of XMLSpy 2007 doesn't disappoint as it adds support for several things that are of particular interest to me such as XSLT 2.0 and XPath 2.0, XQuery and enhanced WSDL editing. It of course adds many more features which you can learn about at http://www.altova.com/products/xmlspy/xml_editor.html.
The intergrated XQuery editor simplifies writing queries since it offers intellisense, access to different XQuery language keywords, a debugger, plus more. Here's an example some of the intellisense you get while working with XQuery queries:

The XSLT 2.0 editor looks and acts much like the previous one which is good for users who have already worked with XMLSpy. You get full intellisense which is especially helpful with XSLT 2.0 and XPath 2.0 since they add several new elements/attributes and functions.

If you've ever needed to debug an XSLT stylesheet before you'll find the debugging capabilities extremely helpful. I can't even tell you how many hours XSLT debuggers have saved me since debugging stylesheets by hand is like finding a needle in a haystack. Here's a screenshot of what the editor looks like while in debug mode:

The XPath Analyzer is really useful when you need to get live feedback of selected nodes based upon an XPath expression you're writing. If you've ever wasted a lot of time trying to figure out why an expression isn't returning a node-set the analyzer will definitely simplify the process:

Finally, the WSDL editor has been significantly enhanced compared to the previous version and allows messages, types, operations, portTypes, bindings, etc. to be edited inline. Here's an example of viewing the Amazon.com AWSECommerce WSDL file:

If you work a lot with XML, XSLT, XQuery or WSDL you'll find that XMLSpy can save you a lot of time. It also plugs nicely into Visual Studio .NET for an integrated experience. .NET developers can also use it to generate C# code from XSD schema files. It's certainly not free (although a free trial is available), but it's well worth the cost in my opinion if you work with various XML technologies a lot (and no....Altova didn't pay me to say that :-)).
Video: Edit XML Data with the XmlDocument Class
In this video tutorial I walk through how to use the XmlDocument class to edit XML data. Click the link below to view the video.
Video: Using XPath with the XmlDocument Class
In this video tutorial I walk through how to use XPath statements to parse an RSS feed and display results using the XmlDocument class Click the link below to view the video.
.NET Distributed Application Development
I'm teaching Microsoft's .NET Distributed Application Development course this week in Phoenix and wanted to get some sample code I put together posted for everyone that is attending (and anyone else that is interested). The code demonstrates asynchronous Web Services calls, MSMQ fundamentals, remoting through code and remoting through configuration files, using delegates with remoting (for async calls), WSE 3 features, plus more.
Las Vegas DevConnections Talks - Code and Content (Updated)
I'm going to be giving 3 talks and one pre-conference workshop at DevConnections next week in Las Vegas on behalf of Interface Technical Training. It's always a great conference and I'm looking forward to it. The topics I'll be covering are shown below:
- Migrating from Web Services to Service Oriented Architectures (SOAs)
- Minimize Code with Strongly-Typed DataSets and TableAdapters
- Generate Dynamic Maps: .NET 2.0 XML and Web Services
- Microsoft AJAX, XML and Web Services: How it all Fits Together (Updated for Beta 2)
I'll update the Microsoft AJAX talk code and slides sometime next week. If you're attending the conference stop by and say "hi" at any of my sessions.
Creating an ASP.NET RSS Blog Roller
We needed an RSS blog roller for http://www.interfacett.com so we could show various employee blogs. While there are several out there for .NET we wanted something that we could build on and customize so Spike Xavier and I put together a quick class named RssBlogRoller that would read an array of blog URLs, grab a specific number of items and then sort them based upon the <pubDate> element. It was a fun little exercise that will be useful in classes as well since it demonstrates generics, XmlReaders (and sub readers), nullable types and the ASP.NET ObjectDataSource.
The code for the RssBlogRoller is shown below. I've refactored it several times now and while it's not perfect, it gets the job done. RssBlogRoller has a method named GetRssItems that returns an array of RssItem objects (also shown below).
using System.Web.Configuration;
using System.Xml;
using System.IO;
using System.Collections.Generic;
using System.Web;
namespace InterfaceTT {
public class RSSBlogRoller {
public static RSSItem[] GetRssItems(string rssURLs,
int numberToShow)
{
//Try to grab URLs from web.config
if (rssURLs == null) rssURLs =
WebConfigurationManager.AppSettings["BlogUrls"];
if (String.IsNullOrEmpty(rssURLs))
{
HttpContext.Current.Trace.Warn("GetRssItems",
"rssURLs is empty. No blogs to parse were found.");
return null;
}
//Get each person's blog URL
string[] rssUrlsArray = rssURLs.Split(new char[] { ';' });
//Check if we have any URLs to retrieve
if (rssUrlsArray == null || rssUrlsArray.Length == 0)
{
HttpContext.Current.Trace.Warn("GetRssItems",
"rssURLs is empty. No blogs to parse were found.");
return null;
}
//Create dictionary to store each person's blog entries
//Key is blog URL, value is all the person's entries
Dictionary<string, List<RSSItem>> namesFeeds =
new Dictionary<string, List<RSSItem>>();
foreach (string url in rssUrlsArray)
{
if (url.Length > 0)
{
List<RSSItem> blogItems = new List<RSSItem>();
RSSItem currItem = null;
XmlReader reader = null;
try
{
reader = XmlReader.Create(url);
while (reader.Read())
{
//Exit read operation if we've
//found all we need
if (blogItems.Count > numberToShow) break;
if (reader.NodeType == XmlNodeType.Element
&& reader.Name.ToLower() == "item")
{
//Create a sub XmlReader
currItem = ReadRSSItem(reader.ReadSubtree());
}
//After each item end tag create HTML output
if (reader.NodeType == XmlNodeType.EndElement
&& reader.Name.ToLower() == "item")
{
if (currItem != null)
blogItems.Add(currItem);
}
}
}
catch (Exception exp)
{
HttpContext.Current.Trace.Warn("GetRssItems",
"Error in reading RSS feed: " + exp.Message);
}
finally
{
if (reader != null) reader.Close();
}
if (blogItems.Count > 0)
{
namesFeeds.Add(url, blogItems);
}
}
} //End For
RSSItem[] newItems = GetRSSItems(namesFeeds, numberToShow);
//Will sort by pubDate...implements IComparable<T>
Array.Sort(newItems);
return newItems;
}
private static RSSItem ReadRSSItem(XmlReader subReader)
{
string title = null;
string link = null;
string desc = null;
DateTime? pubDate = null; //Nullable<DateTime>
string authorName = null;
subReader.MoveToContent();
while (subReader.Read())
{
switch (subReader.Name.ToLower())
{
case "title":
title = subReader.ReadString();
break;
case "link":
link = subReader.ReadString();
break;
case "description":
desc = subReader.ReadString();
break;
case "pubdate":
string pubDateVal = subReader.ReadString();
DateTime d;
if (DateTime.TryParse(pubDateVal, out d))
{
pubDate = Convert.ToDateTime(pubDateVal);
}
break;
case "author":
authorName = subReader.ReadString();
break;
}
}
if (!String.IsNullOrEmpty(title)
&& !String.IsNullOrEmpty(link)
&& !String.IsNullOrEmpty(desc))
{
RSSItem item = new RSSItem(title, link,
desc, pubDate, authorName);
return item;
}
return null;
}
private static RSSItem[] GetRSSItems(Dictionary<string,
List<RSSItem>> namesFeeds, int numberToShow)
{
if (numberToShow < 1) numberToShow = 1;
List<RSSItem> blogItems = new List<RSSItem>();
int i = 0;
if (namesFeeds != null && namesFeeds.Count > 0)
{
foreach (string key in namesFeeds.Keys)
{
List<RSSItem> items = namesFeeds[key];
if (items != null)
{
int count = items.Count;
if (count > 0)
{
int j = 0;
while (j < numberToShow)
{
if (j == count) break;
blogItems.Add(items[j]);
j++;
i++;
}
}
else
{
namesFeeds.Remove(key);
}
}
}
}
else
{
HttpContext.Current.Trace.Warn("GetRSSItems",
"namesFeeds is null or has a 0 count.");
}
return blogItems.ToArray();
}
}
}
using System.Collections.Generic;
namespace InterfaceTT {
public class RSSItem : IComparable<RSSItem> {
private string _Title;
private string _Link;
private string _Description;
private DateTime? _PubDate;
private string _AuthorName;
public RSSItem(string title,string link,string desc,
DateTime? pubDate,string authorName) {
_Title = title;
_Link = link;
_Description = desc;
_PubDate = pubDate;
_AuthorName = authorName;
}
public string Title {
get {
return _Title;
}
set {
_Title = value;
}
}
public string Link {
get {
return _Link;
}
set {
_Link = value;
}
}
public string Description {
get {
return _Description;
}
set {
_Description = value;
}
}
public DateTime? PubDate
{
get { return _PubDate; }
set { _PubDate = value; }
}
public string AuthorName
{
get { return _AuthorName; }
set { _AuthorName = value; }
}
#region IComparable<RSSItem> Members
public int CompareTo(RSSItem other)
{
if (this.PubDate < other.PubDate) return 1;
if (this.PubDate > other.PubDate) return -1;
return 0; //The are equal
}
#endregion
}
}
The user control that displays the blog data for employees is shown next. It uses the ObjectDataSource control to bind to the RssBlogRoller class.
<%@ Control Language="C#" AutoEventWireup="true"
CodeFile="BlogRoller.ascx.cs" Inherits="UserControl_BlogRoller" %>
<%@ OutputCache Duration="900" VaryByParam="None" %>
<asp:DataList ID="DataList1" runat="server"
DataSourceID="odsRss" HorizontalAlign="Left" RepeatLayout="Flow">
<ItemTemplate>
<a href='<%# Eval("Link") %>'><%# Eval("Title") %></a>
<br />
<%# Eval("PubDate") %> By <%# Eval("AuthorName") %>
<br />
<%# Strip(Eval("Description"),Eval("Link")) %>
</li>
</ItemTemplate>
</asp:DataList>
<asp:ObjectDataSource ID="odsRss" runat="server"
SelectMethod="GetRssItems" TypeName="InterfaceTT.RSSBlogRoller">
<SelectParameters>
<asp:Parameter DefaultValue=""
Name="rssURLs" Type="String" />
<asp:Parameter DefaultValue="1"
Name="numberToShow" Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>
An example of the blog roller in action can be found at http://www.interfacett.com/ and the code can be downloaded here.
