Ahmad Masykur

Share your knowledge although one function!

About the author

Ahmad Masykur is a Software Architecture Engineer at PT. Freeport Indonesia Jakarta Indonesia.
In this blog, I share things of interest to me. Most topics are likely to be related to software development, but don't hold me to it.

Certificates



Awards


Powered by

Widget Prayer Time not found.

There is an error in XML document (4, 16278).X

Page List

Validators


Ahmad Masykur

Create WebSlices for BlogEngine.NET 1.5

Web Slices are snippets of the entire page that a user can subscribe to. Web Slices will be kept updated by the browser automatically, and can be viewed directly from the Favorites bar, complete with graphics and visuals. BlogEngine.NET is most popular blog software developed in ASP.NET technology. WebSlices is not yet supported by latest version of BlogEngine.NET (version 1.5.0). I will show you step by step creating WebSlices for BlogEngine.NET.

Prepare service for WebSlices

WebSlices can use XML RSS service to display the data. WebSlices will display first item of RSS information. To display n of latest blog posts, we should modify RSS service to show all information in latest item. BlogEngine use syndication handler for RSS which served by SyndicationHandler.cs file in BlogEngine.Core assembly. Please modify following files to extend syndication handler to be support WebSlices.

SyndicationFormat.cs

Add new enum named WebSlices

/****************************************************************************
Modification History:
*****************************************************************************
Date		Author		  Description
*****************************************************************************
04/11/2007  brian.kuhn    Created SyndicationFormat Enumeration
08/30/2007  brian.kuhn    Moved SyndicationFormat enum to root of library
06/13/2009  Ahmad Masykur Add WebSlices enumeration
****************************************************************************/
using System;
namespace BlogEngine.Core
{
    /// <summary>
    /// Represents common types of syndication formats.
    /// </summary>
    public enum SyndicationFormat
    {
        /// <summary>
        /// No syndication format specified.
        /// </summary>
        None    = 0,
        /// <summary>
        ///  Indicates that a feed conforms to the Atom syndication format.
        /// </summary>
        Atom    = 1,
        /// <summary>
        /// Indicates that a feed conforms to the RSS syndication format.
        /// </summary>
        Rss     = 2,
        /// <summary>
        /// Indicates that a feed conforms to the IE8 WebSlices syndication format.
        /// </summary>
        WebSlices = 3
    };
}

SyndicationHandler.cs

In SetHeaderInformation method, add highlighted lines below.

/// <summary>
/// Sets the response header information.
/// </summary>
/// <param name="context">An <see cref="HttpContext"/> object that provides references to the intrinsic server objects (for example, <b>Request</b>, <b>Response</b>, <b>Session</b>, and <b>Server</b>) used to service HTTP requests.</param>
/// <param name="items">The collection of <see cref="IPublishable"/> instances used when setting the response header details.</param>
/// <param name="format">The format of the syndication feed being generated.</param>
/// <exception cref="ArgumentNullException">The <paramref name="context"/> is a null reference (Nothing in Visual Basic) -or- the <paramref name="posts"/> is a null reference (Nothing in Visual Basic).</exception>
private static void SetHeaderInformation(HttpContext context, List<IPublishable> items, SyndicationFormat format)
{
	DateTime lastModified = DateTime.MinValue;
	foreach (IPublishable item in items)
	{
		if (item.DateModified.AddHours(-BlogSettings.Instance.Timezone) > lastModified)
			lastModified = item.DateModified.AddHours(-BlogSettings.Instance.Timezone);
	}
	switch (format)
	{
		case SyndicationFormat.Atom:
			context.Response.ContentType = "application/atom+xml";
			context.Response.AppendHeader("Content-Disposition", "inline; filename=atom.xml");
			break;
		case SyndicationFormat.Rss:
			context.Response.ContentType = "application/rss+xml";
			context.Response.AppendHeader("Content-Disposition", "inline; filename=rss.xml");
			break;
		case SyndicationFormat.WebSlices:
			context.Response.ContentType = "application/rss+xml";
			context.Response.AppendHeader("Content-Disposition", "inline; filename=webslices.xml");
		break;
	}
	if (Utils.SetConditionalGetHeaders(lastModified))
		context.Response.End();
}

SyndicationGenerator.cs

Add new WriteWebSlicesFeed method below

private void WriteWebSlicesFeed(Stream stream, List<IPublishable> publishables, string title)
{
    XmlWriterSettings writerSettings = new XmlWriterSettings();
    writerSettings.Encoding = System.Text.Encoding.UTF8;
    writerSettings.Indent = true;
    using (XmlWriter writer = XmlWriter.Create(stream, writerSettings))
    {
        writer.WriteStartElement("rss");
        writer.WriteAttributeString("version", "2.0");
        writer.WriteStartElement("channel");
        writer.WriteElementString("title", "Latest Posts");
        writer.WriteElementString("ttl", "15");
        writer.WriteStartElement("item");
        writer.WriteElementString("title", title);
        StringBuilder description = new StringBuilder();
        description.Append("<div style=\"font-family: arial, helvetica, sans-serif;\">");
        description.Append("<div style=\"background-color: #f0f0f0;\"><h1 style=\"margin:0px; padding:0px; font-size: x-large;\">" + title + "</h1><h2 style=\"margin:0px; padding:0px; font-size: small; font-weight: normal; font-style: italic;\">" + blogSettings.Description + "</h2></div>");
        description.Append("<ul style=\"list-style-type: none;margin: 0;padding: 0px;\">");
        for (int i = 0; (i < 10) && (i < BlogSettings.Instance.NumberOfRecentPosts); i++)
        {
            description.Append("<li style=\"margin-left: 0px;\"><div style=\"display:block; border-top: 1px solid #efefef; border-bottom: 1px solid #efefef;\"><a href=\"" + publishables[i].AbsoluteLink + "\" target=\"_blank\" title=\"" + publishables[i].Title + "\" style=\"text-decoration: none; font-size: small; color: #000090; width:500px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; \">" + publishables[i].Title + "</a></li>");
        }
        description.Append("</ul>");
        description.Append("</div>");
        writer.WriteElementString("description", System.Web.HttpUtility.HtmlDecode(description.ToString()));
        writer.WriteEndElement();
        writer.WriteFullEndElement();
    }
}

Add highlighted lens below in WriteFeed method.

/// <summary>
/// Writes a generated syndication feed that conforms to the supplied <see cref="SyndicationFormat"/> using the supplied <see cref="Stream"/> and collection.
/// </summary>
/// <param name="format">A <see cref="SyndicationFormat"/> enumeration value indicating the syndication format to generate.</param>
/// <param name="stream">The <see cref="Stream"/> to which you want to write the syndication feed.</param>
/// <param name="publishables">The collection of <see cref="IPublishable"/> objects used to generate the syndication feed content.</param>
/// <param name="title">The title of the RSS channel</param>
public void WriteFeed(SyndicationFormat format, Stream stream, List<IPublishable> publishables, string title)
{
	if (stream == null)
	{
		throw new ArgumentNullException("stream");
	}
	if (publishables == null)
	{
		throw new ArgumentNullException("publishables");
	}
	if (!stream.CanWrite)
	{
		throw new ArgumentException(String.Format(null, "Unable to generate {0} syndication feed. The provided stream does not support writing.", format), "stream");
	}
	//------------------------------------------------------------
	//	Write syndication feed based on specified format
	//------------------------------------------------------------
	switch (format)
	{
		case SyndicationFormat.Atom:
			this.WriteAtomFeed(stream, publishables, title);
			break;
		case SyndicationFormat.Rss:
			this.WriteRssFeed(stream, publishables, title);
			break;
		case SyndicationFormat.WebSlices:
			this.WriteWebSlicesFeed(stream, publishables, title);
			break;
	}
}

Master page file of selected theme.

Find <asp:contentplaceholder /> element and add hslice class to parent element of placeholder. Add some information to provide WebSlice title and service source. Your modification of master page may look like following lines.

<div id="main" class="hslice">
    <div style="display:none">
        <p class="entry-title">
            <%=BlogSettings.Instance.Name %>
        </p>
        <a rel="feedurl" href="<%=Utils.AbsoluteWebRoot + "syndication.axd?format=webslices" %>"></a>
    </div>
    <asp:contentplaceholder id="cphBody" runat="server">
    </asp:contentplaceholder>
</div>

Build BlogEngine solution. Your BlogEngine is now support WebSlices feed. You only redeploy BlogEngine.Core.dll and selected theme to make WebSlices support of your blog.

Happy nice blogging with IE8.


Tags: ,
Categories: BlogEngine
Permalink | Comments (0) | Post RSSRSS comment feed

Comments

Add comment




  Country flag

biuquote
  • Comment
  • Preview
Loading