On my last post I introduced the feeds I created to subscribe to Mix09 session videos.
In case someone is interested on how I did it, here it is:
<%@ WebHandler Language="C#" Class="mix09" %>
using System;
using System.IO;
using System.Web;
using System.Linq;
using System.Xml.Linq;
using System.Net;
using System.Xml;
public class mix09 : IHttpHandler, IHttpAsyncHandler
{
class WebClientOpenReadAsyncResult : IAsyncResult
{
private AsyncCallback callback;
public WebClientOpenReadAsyncResult()
{
this.IsCompleted = true;
this.CompletedSynchronously = true;
}
public WebClientOpenReadAsyncResult(AsyncCallback callback)
{
this.callback = callback;
this.IsCompleted = false;
this.CompletedSynchronously = false;
}
public object AsyncState
{
get { return null; }
}
public bool CompletedSynchronously { get; private set; }
public System.Threading.WaitHandle AsyncWaitHandle
{
get { throw new InvalidOperationException("ASP.NET should not use this property ."); }
}
public bool IsCompleted { get; private set; }
public Stream Stream { get; private set; }
public void Completed(object sender, OpenReadCompletedEventArgs e)
{
this.IsCompleted = true;
this.Stream = e.Result;
if (this.callback != null)
{
this.callback(this);
}
}
}
private static Uri mixSessionsUri = new Uri("http://sessions.visitmix.com/RSS");
private HttpContext context;
private string type;
#region IHttpHandler Members
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
WebClient wc = InitializeRequest(context);
if (wc == null)
{
return;
}
OutputFeed(wc.OpenRead(mixSessionsUri));
}
#endregion
#region IHttpAsyncHandler Members
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
WebClient wc = InitializeRequest(context);
if (wc == null)
{
return new WebClientOpenReadAsyncResult();
}
WebClientOpenReadAsyncResult ar = new WebClientOpenReadAsyncResult(cb);
wc.OpenReadCompleted += ar.Completed;
wc.OpenReadAsync(mixSessionsUri, extraData);
return ar;
}
public void EndProcessRequest(IAsyncResult result)
{
Stream stream = (result as WebClientOpenReadAsyncResult).Stream;
if (stream != null)
{
OutputFeed(stream);
}
}
#endregion
private WebClient InitializeRequest(HttpContext context)
{
this.context = context;
this.type = context.Request.QueryString["type"];
if (string.IsNullOrEmpty(this.type))
{
return null;
}
WebClient wc = new WebClient();
wc.Headers[HttpRequestHeader.UserAgent] = "Required User Agent";
return wc;
}
private void OutputFeed(Stream source)
{
XmlReader feedReader = XmlReader.Create(source);
XDocument feed = XDocument.Load(feedReader);
var rss = feed.Element("rss");
var channel = rss.Element("channel");
var title = channel.Element("title");
title.Value = string.Format("{0} ({1})", title.Value, this.type.ToUpper());
channel.Element("link").Value = "http://cli.gs/Mix09Sessions";
foreach (var item in channel.Elements("item"))
{
string link = item.Element("link").Value;
string session = link.Substring(link.LastIndexOf('/') + 1).ToLower();
string enclosureUrl = string.Format("http://mschannel9.vo.msecnd.net/o9/mix/09/{0}/{1}.wmv", this.type.ToLower(), session);
item.Add(
new XElement("enclosure",
new XAttribute("url", enclosureUrl)));
}
this.context.Response.Write(feed.ToString());
this.context.Response.ContentType = "application/rss+xml";
HttpCachePolicy cache = this.context.Response.Cache;
cache.SetCacheability(HttpCacheability.ServerAndPrivate);
cache.SetExpires(DateTime.Now.AddHours(1));
cache.VaryByParams["type"] = true;
cache.SetValidUntilExpires(true);
}
}