SIOC implementation for BlogEngine.NET

Update: This is now part of the Data Portability Pack for BlogEngine.NET

A major feature of BlogEngine.NET is that it supports a lot of open standards. Keeping with this, I’ve setup an initial implementation of SIOC for BlogEngine.NET. SIOC (Semantically-Interconnected Online Communities) is an extension of RDF which goes beyond RSS in that it describes not only the content of a website, but the connections between site content, users on the site, and another websites. While RSS has one big document for recent content, SIOC splits up its data into (1) a site profile, (2) profiles for authors, (3) profiles for posts, and (4) profiles for comments. Each of these not only lists the author’s name, but also includes FOAF (Friend of a Friend) data to help identify users across the Internet via a hashed email address. If all sites were SIOC/FOAF enabled, you could theoretically search an aggregator site (like Technorati if it supported SIOC) for all posts and comments by a given user within a set of blogs, forums, or other websites. For more information on this, see my post on Data Portability standards.

Site Profile

To get a feel for the data, here’s what the site profile looks like (note: I’ve tried to match the Word Press SIOC plugin URL conventions as much as possible)
http://johndyer.name/sioc.axd?sioc_type=site

<rdf:RDF>
<!-- users -->
<sioc:Usergroup rdf:about="http://localhost/johndyer/sioc.axd?sioc_type=site#authors"> <dc:title>Authors at "John Dyer"</dc:title> <sioc:has_member> <sioc:User rdf:about="http://localhost/johndyer/author/John+Dyer.aspx" rdfs:label="John Dyer"> <sioc:see_also rdf:resource="http://localhost/johndyer/sioc.axd?sioc_type=user&amp;sioc_id=John+Dyer" /> </sioc:User> </sioc:has_member> </sioc:Usergroup>
<!-- site info -->
<sioc:Site rdf:about="http://johndyer.name/"> <dc:title>John Dyer</dc:title> <dc:description>ASP.NET, Flash, and JavaScript from FreeTextBox and Dallas Seminary</dc:description> <sioc:link>http://johndyer.name/</sioc:link> <sioc:host_of>http://johndyer.name/sioc.axd?sioc_type=site#webblog</sioc:host_of> <sioc:has_group>http://johndyer.name/sioc.axd?sioc_type=site#authors</sioc:has_group>
</sioc:Site>
<!-- blog info, posts--> <sioc:Forum rdf:about="http://johndyer.name/sioc.axd?sioc_type=site#webblog"> <sioc:name>John Dyer</sioc:name> <sioc:link rdf:resource="http://johndyer.name/sioc.axd?sioc_type=site#webblog" /> <sioc:container_of> <sioc:Post rdf:about="http://johndyer.name/post/2008/02/BlogEngineNET-Extension-Flash-Video-Player.aspx" dc:title="BlogEngine.NET Extension: Flash Video Player"> <rdfs:seeAlso rdf:resource="http://johndyer.name/sioc.axd?sioc_type=post&amp;sioc_id=06af08e0-c4eb-421c-9e18-b618358d33ca" /> </sioc:Post> </sioc:container_of> </sioc:Forum> </rdf:RDF>

This describes (1) the users on the site (sioc:Usergroup) which would be blog authors, (2) the site in general (sioc:Site), and (3) and displays the content (sioc:Forum). Each of these has links to other SIOC documents for the user and then for the posts.

Post Profile

Here’s what a post looks like:
http://johndyer.name/sioc.axd?sioc_type=post&sioc_id=612564cd-3cfa-42b5-92e9-44beb52f7cd5

<?xml version="1.0" encoding="utf-8"?>
<rdf:RDF xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:rss="http://purl.org/rss/1.0/" xmlns:admin="http://webns.net/mvcb/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content" xmlns:sioc="http://rdfs.org/sioc/ns#">
  <foaf:Document rdf:about="http://johndyer.name/">
    <dc:title>SIOC post profile for "John Dyer"</dc:title>
    <dc:description>A SIOC profile describes the structure and contents of a weblog in a machine readable form. For more information please refer to http://sioc-project.org/.</dc:description>
    <foaf:primaryTopic>http://johndyer.name/post/2008/02/Website-Break-Coke-vs-Diet-Coke-vs-Coke-Zero.aspx</foaf:primaryTopic>
    <admin:generatorAgent>BlogEngine.NET SIOC Generator (1.0) by John Dyer</admin:generatorAgent>
  </foaf:Document>
<!-- post data -->
<sioc:Post rdf:about="http://johndyer.name/post/2008/02/Website-Break-Coke-vs-Diet-Coke-vs-Coke-Zero.aspx"> <sioc:link rdf:resource="http://johndyer.name/post/2008/02/Website-Break-Coke-vs-Diet-Coke-vs-Coke-Zero.aspx" /> <sioc:has_container rdf:resource="http://johndyer.name/sioc.axd?sioc_type=site#webblog" /> <dc:title>Website Break: Coke vs. Diet Coke vs. Coke Zero</dc:title> <!-- post author -->
<sioc:has_creator> <sioc:User rdf:about="http://johndyer.name/author/John+Dyer.aspx"> <rdfs:seeAlso rdf:resource="http://johndyer.name/sioc.axd?sioc_type=user&amp;sioc_id=John+Dyer" /> </sioc:User>
</sioc:has_creator> <foaf:maker> <foaf:Person rdf:about="http://johndyer.name/author/John+Dyer.aspx" foaf:name="John Dyer"> <foaf:mbox_sha1sum>3eb435778fafc3efde35fba2ca731c6d3234178f</foaf:mbox_sha1sum> <foaf:homepage rdf:resource="http://johndyer.name/" /> <rdfs:seeAlso rdf:resource="http://johndyer.name/sioc.axd?sioc_type=user&amp;sioc_id=John+Dyer" /> </foaf:Person> </foaf:maker>
<dcterms:created>2/1/2008 4:40:53 PM</dcterms:created> <sioc:content> Today, we decided to take a break from web development and do something truly important: a taste test. Tim, Adam, Brian, and I wanted to see if we could identify Coke, Diet Coke, and Coke Zero in a blind test. We each had three cups that another team member had setup. We tasted each drink and tried to match the drink with the cup and also mark our favorite. Tim is the narrator and then the participants from left to right are: John (me), Adam, Tim, and Brian. </sioc:content> <content:encoded>&lt;p&gt;Today, we decided to take a break from web development and do something truly important: a taste test. Tim, Adam, Brian, and I wanted to see if we could identify Coke, Diet Coke, and Coke Zero in a blind test. We each had three cups that another team member had setup. We tasted each drink and tried to match the drink with the cup and also mark our favorite. Tim is the narrator and then the participants from left to right are: John (me), Adam, Tim, and Brian.&lt;/p&gt;</content:encoded> <!-- categories and tags -->
<sioc:topic rdfs:label="Off Topic" rdf:resource="http://johndyer.name//category/Off Topic.aspx" /> <sioc:topic rdfs:label="challenge" rdf:resource="http://johndyer.name//?tag=/challenge" /> <sioc:topic rdfs:label="soda" rdf:resource="http://johndyer.name//?tag=/soda" />
<!-- comments --> <sioc:has_reply> <sioc:Post rdf:about="http://johndyer.name/post/2008/02/Website-Break-Coke-vs-Diet-Coke-vs-Coke-Zero.aspx#id_a82699f9-77e2-460d-b3b1-d1d470180df9"> <rdfs:seeAlso rdf:resource="http://johndyer.name/sioc.axd?sioc_type=comment&amp;sioc_id=a82699f9-77e2-460d-b3b1-d1d470180df9" /> </sioc:Post> </sioc:has_reply>
<!-- outbound links --> <sioc:links_to rdf:resource="http://www.cokezero.com/" rdfs:label="Coke Zero" /> </sioc:Post> </rdf:RDF>

This one also has a “document” description (which I left out on the site profile) and then has information about the post including its author (both sioc:has_creator and foaf:maker which has my email as a SHA1 hash), content (sioc:content and content:encoded), categories (sioc:topic), outbound links (sioc:links_to), and then links to the comments for the post (sioc:has_reply)

Download and Installation

  1. Download BlogEngine.NET SIOC extension
  2. Copy the three files into the \App_Code\Sioc\ directory
  3. Add the following line to your web.config
    <add verb="*" path="sioc.axd" type="SIOC.SiocHandler, App_Code" validate="false"/>

Update: This is now part of the Data Portability Pack

What’s Next?

  1. This extension will add a <link> tag to your header, but you view it directly at: http://yoursite.com/sioc.axd
  2. Explore the SIOC file at:  http://sparql.captsolo.net/browser/browser.py?url=http%3A%2F%2Fjohndyer.name%2Fsioc.axd
  3. An SIOC explorer is also available here which allows you to search and sort the data from among several sites: http://www.activerdf.org/sioc/

20 thoughts on “SIOC implementation for BlogEngine.NET

  1. Thanks Chris. It’s fixed now.
    The SiocExtension class is using Post.Serving event to add the SIOC <link> to the header. This is not terribly efficient, but I don’t think there’s another event that can be used for doing this.

  2. hi john
    i’ve been looking into your rdf output.
    when exporting comments, why don’t you connect them to the post they comment with sioc:reply_of (with the post rdf url as the object)?
    your only connection is via the sioc:link to the comment html, but that is not enough.
    if one wants to know that s comment is a comment just by looking a the rdf, one must know it is a reply_of another post!
    it’s is a major problem, i think.
    another major problem is your implementation of foaf:primaryTopic.
    i think you should use a rdf:resource as the object and not a literal.
    take a look here for examples to correct implementations (to my understanding) of the spec:
    http://www.johnbreslin.com/blog/index.php?sioc_type=comment&sioc_id=554475
    (besides the fact that they use a reply_to instead of a reply_of!!)
    besides all that – good job and thanks for sharing!
    yoav

  3. I came lately to your website and have been reading along. I thought I would leave my initial comment. Keep writing, cause your posts are impressive! Doesn’t it take up a lot of time to keep your blog so fascinating

  4. Fantastic site you have here but I was wanting
    to know if you knew of any message boards that cover the same topics talked about
    here? I’d really love to be a part of group where
    I can get opinions from other experienced individuals that share the same interest.
    If you have any recommendations, please let me know. Thank you!

  5. Consejo: Si ciertos tratamientos para saber como se quita la caspa soluciona su inconveniente, recuerde mantener todos y cada uno de los utensilios de cabello limpios para prevenir siguientes apariciones
    de caspa.

Comments are closed.