<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Phil Derksen &#187; PBworks</title>
	<atom:link href="http://philderksen.com/category/pbworks/feed/" rel="self" type="application/rss+xml" />
	<link>http://philderksen.com</link>
	<description>Web Development, WordPress and SEO</description>
	<lastBuildDate>Thu, 02 Feb 2012 06:33:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Using the PBworks API with ASP.NET MVC and jQuery</title>
		<link>http://philderksen.com/2009/pbworks-api-with-aspnet-mvc-and-jquery/</link>
		<comments>http://philderksen.com/2009/pbworks-api-with-aspnet-mvc-and-jquery/#comments</comments>
		<pubDate>Thu, 14 May 2009 00:25:23 +0000</pubDate>
		<dc:creator>Phil Derksen</dc:creator>
				<category><![CDATA[ASP.NET MVC]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[PBworks]]></category>

		<guid isPermaLink="false">http://philderksen.nfshost.com/?p=22</guid>
		<description><![CDATA[Recently my company went with PBworks (formerly PBwiki) to use for internal collaboration. One of my projects is building a “dashboard” web app to bring in data from different sources, and the first thing users want to see in it is the recent activity log from the wiki. Here’s how I tapped into the PBworks API and brought it into the web app, which is being built using ASP.NET MVC and jQuery.]]></description>
			<content:encoded><![CDATA[<p>Recently my company went with <a href="http://pbworks.com/">PBworks</a> (formerly PBwiki) to use for internal collaboration. One of my projects is building a &#8220;dashboard&#8221; web app to bring in data from different sources, and the first thing users want to see in it is the recent activity log from the wiki. Here&#8217;s how I tapped into the PBworks API and brought it into the web app, which is being built using <a href="http://www.asp.net/mvc/">ASP.NET MVC</a> and <a href="http://jquery.com/">jQuery</a>.</p>
<p>Since I can’t display my company data, I created a demo project using the <a href="http://jqueryui.pbworks.com/">jQuery UI design &amp; planning wiki</a> (a great resource in itself), since it&#8217;s a public wiki. The jQuery UI wiki is already enabled for API use. If you want to enable your own wiki, go to Settings &gt; Developer Interface. Also note your three API keys as they’ll need to be passed along depending on your security settings.</p>
<p>Looking through the <a href="http://pbworks.com/api_v2/">PBworks API documentation</a> you’ll notice that they return all data in <a href="http://en.wikipedia.org/wiki/JSON">JSON</a>. Naturally I thought the quickest route to retrieving that data would be call it’s URLs directly using jQuery’s <a href="http://docs.jquery.com/Ajax/jQuery.getJSON">getJSON</a> call.</p>
<p>In my ASP.NET MVC project, for now I just wanted to see the PBworks data on the default view. So I simply went to /Views/Home/Index.aspx, cleared out the default content and added a custom div tag. The plan was to populate the div tag via AJAX using jQuery. Later this might make sense to move to a PartialView.</p>
<p>Directly after the div tag I added javascript to fill the div with the data returned from the PBworks API call. In this case I’ll use the <a href="http://pbworks.com/api_v2/#GetChanges">GetChanges</a> call to start and do a test to see if the getJSON call even executes. Here’s the code for the MainContent section of the view:</p>
<pre class="brush: csharp;">&lt;div id="pbWorksData"&gt;
&lt;/div&gt;

&lt;script type="text/javascript"&gt;

    $(document).ready(function() {
        $.getJSON("http://jqueryui.pbworks.com/api_v2/op/GetChanges/_type/jsontext", function(data)
        {
            $("#pbWorksData").append("data goes here");
        });
    });

&lt;/script&gt;</pre>
<p>Since we’re using jQuery we need to add a reference to it in the main head tag. I added mine to the master page at /Views/Shared/Site.master.</p>
<pre class="brush: csharp;">&lt;script src="../../Scripts/jquery-1.3.2.min.js" type="text/javascript"&gt;&lt;/script&gt;</pre>
<p>Unfortunately this first attempt didn’t work, which confused me for a while. The same type of call works with the Flickr API using the sample code in the jQuery <a href="http://docs.jquery.com/Ajax/jQuery.getJSON#urldatacallback">getJSON</a> docs. The URL also works if you <a href="http://jqueryui.pbworks.com/api_v2/op/GetChanges/_type/jsontext">navigate to it straight</a>. And for this public wikis you don’t need to pass any API keys in the URL.</p>
<p>Further inspection with the excellent <a href="http://getfirebug.com/">Firebug</a> add-on reveals a security error.</p>
<p><a href="http://philderksen.com/wp-content/uploads/20090512-jsonsecurityerror.png" rel="lightbox[22]"><img class="size-full wp-image-59 alignnone" title="20090512-jsonsecurityerror.png" src="http://philderksen.com/wp-content/uploads/20090512-jsonsecurityerror.png" alt="20090512 jsonsecurityerror" width="521" height="232" /></a></p>
<p>Turns out the PBworks folks aren’t allowing cross-domain javascript calls, even using <a href="http://bob.pythonmac.org/archives/2005/12/05/remote-json-jsonp/">JSONP</a> which is supported in jQuery as of version 1.2. This was confirmed in an email to them, reasons being for security. Notice also we’re not passing in a</p>
<p>To get around the cross-domain issue, we’ll just access the API via server-side code in a model class using the WebRequest and WebResponse classes. In fact we’ll just pass the JSON straight to the controller with little modification.</p>
<p>Here’s the complete PBworks model class. Notice at the end we had to strip out some surrounding text <strong>(/* -secure- */</strong>). If you don’t do this it won’t be recognized as JSON. PBworks informed me that it was in there to prevent the hijacking of credentials over browsers, and that they’re working on an alternative method to remove the need for this extra text.</p>
<pre class="brush: csharp;">using System.IO;
using System.Net;

namespace PbApiDemo.Models
{
    public class PBworks
    {
        public string GetChanges()
        {
            string url = "http://jqueryui.pbworks.com/api_v2/op/GetChanges/_type/jsontext";

            WebRequest request = HttpWebRequest.Create(url);
            WebResponse response = request.GetResponse();
            string jsonResponse = "";

            using (StreamReader sr = new StreamReader(response.GetResponseStream()))
            {
                jsonResponse = sr.ReadToEnd();
            }

            //Strip out surrounding /* -secure- */ text to keep it recognized as JSON
            jsonResponse = jsonResponse.Replace("/*-secure-", "");
            jsonResponse = jsonResponse.Replace("*/", "");

            return jsonResponse;
        }
    }
}</pre>
<p>In the controller class (PBworksController), I just created an instance of the PBworks model and passed the JSON through as text, setting the browser’s page type to application/json.</p>
<pre class="brush: csharp;">using System.Web.Mvc;
using PbApiDemo.Models;

namespace PbApiDemo.Controllers
{
    public class PBworksController : Controller
    {
        private PBworks pbw = new PBworks();

        public ActionResult GetChanges()
        {
            return Content(pbw.GetChanges(), "application/json");
        }
    }
}</pre>
<p>Now that the correct JSON is returned from a controller in the project, back in our default view we just change the URL in the javascript code.</p>
<pre class="brush: csharp;">$(document).ready(function() {
    $.getJSON("/PBworks/GetChanges", function(data)
    {
        $("#pbWorksData").append("data goes here");
    });
});</pre>
<p>Ran the project now and sure enough the test text inside the getJSON call shows up. Now we’re in business.</p>
<p>Now that I had the complete JSON object, I needed to iterate over each item returned and render them appropriately on the page. To quickly see what’s available I pasted the JSON into this cool <a href="http://json.bloople.net/">JSON 2 HTML</a> tool.</p>
<p>For use in jQuery, the parent object we’re concerned with is actually contained in the <strong>changes</strong> collection. From each item within <strong>changes</strong>, I wanted to display and link the page, author, action taken on that page, and show the lasted edited date/time. I appended all this html via jQuery doing some formatting and manipulation to get the links and date/times right. Later on we might want to move the javascript to another file and optimize it a bit, but it works for now. Here’s the final javascript contained in the default view:</p>
<pre class="brush: csharp;">&lt;script type="text/javascript"&gt;

    $(document).ready(function() {
        $.getJSON("/PBworks/GetChanges", function(data)
        {
            //Create an unordered list to hold all the entries
            $("#pbWorksData").append($("&lt;ul/&gt;"));

            $.each(data.changes, function(i, item)
            {
                if (item.page != null)
                {
                    //Get date/time from "epoch" number
                    var editDate = new Date(item.time * 1000);

                    $("#pbWorksData ul")
                        .append($("&lt;li/&gt;")
                            .append($("&lt;a/&gt;")
                                //Page name and link
                                //Replace spaces with dashes in url
                                .attr("href", "http://jqueryui.pbworks.com/" + item.page.replace(/ /g,"-"))
                                .append(item.page))
                            .append(" - ")
                            //Page "action"
                            .append(item.op_word)
                            .append(" by ")
                            .append($("&lt;a/&gt;")
                                //Page author and link
                                .attr("href", "http://jqueryui.pbworks.com/user/" + item.user_id)
                                .append(item.user_name))
                            .append(" on ")
                            //Last edited date
                            .append(editDate.toLocaleString())
                        );
                }
            });
        });
    });

&lt;/script&gt;</pre>
<p>The final rendering looks like this:</p>
<p><a href="http://philderksen.com/wp-content/uploads/20090513-blog-pbworks-api-1.png" rel="lightbox[22]"><img class="alignnone size-full wp-image-61" title="20090513-blog-pbworks-api-1.png" src="http://philderksen.com/wp-content/uploads/20090513-blog-pbworks-api-1.png" alt="20090513 blog pbworks api 1" width="585" height="268" /></a></p>
<p>Hopefully this helps anyone else out there working with the PBworks API.</p>
<div class="woo-sc-box download   "><a href="http://philderksen.com/wp-content/uploads/2009/05/2009-05-13_pbapidemo.zip">Download the demo project</a> (requires Visual Studio 2008 and ASP.NET MVC)</div>
]]></content:encoded>
			<wfw:commentRss>http://philderksen.com/2009/pbworks-api-with-aspnet-mvc-and-jquery/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

