<?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>source code bean &#187; Web</title>
	<atom:link href="http://sourcecodebean.com/archives/category/web/feed" rel="self" type="application/rss+xml" />
	<link>http://sourcecodebean.com</link>
	<description>giving you tricks and tips of good coding</description>
	<lastBuildDate>Sun, 06 Jun 2010 16:40:09 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>First steps toward EPiServer and ASP.NET MVC</title>
		<link>http://sourcecodebean.com/archives/first-steps-toward-episerver-and-asp-net-mvc/595</link>
		<comments>http://sourcecodebean.com/archives/first-steps-toward-episerver-and-asp-net-mvc/595#comments</comments>
		<pubDate>Mon, 19 Apr 2010 20:33:38 +0000</pubDate>
		<dc:creator>Peter</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://sourcecodebean.com/?p=595</guid>
		<description><![CDATA[Recently I started a new assignment at a customer where we are going to build their new public web site and their intranet, both of them based on EPiServer CMS 6. The person leading the project is very found of ASP.NET MVC, so my first task was to experiment with EPiServer and ASP.NET MVC,  [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I started a new assignment at a customer where we are going to build their new public web site and their intranet, both of them based on EPiServer CMS 6. The person leading the project is very found of ASP.NET MVC, so my first task was to experiment with EPiServer and ASP.NET MVC,  to try to get a running prototype up. </p>
<p>I did some research online to see what others had done. I found two great posts by <a href="http://joelabrahamsson.com/entry/episerver-and-mvc-retrieving-current-page-using-a-custom-model-binder">Joel Abrahamsson</a> and one from <a href="http://fbrz.wordpress.com/2009/10/10/episerver-and-mvc/">Fabio Fabrizio</a>, who based his solution on Joels experiments. </p>
<p>Joels first attempt was to create a base class from which all Controllers inherited. However, this made the controller do more than it should and made it very hard to test. His second attempt was to create a custom model binder and make every action receive currentPage as a parameter. This approach makes it much easier to create unit tests for the code, since it is now possible to moc the currentPage parameter. </p>
<p>Fabio took a different approach and decided to implement a custom MVC handler and a controller factory. This approach fits very well with MVC and felt like the right way to go, so I decided to create a prototype based on Fabios code. Fabios code was based on EPiServer CMS 5 and ASP.NET MVC 1.0, but I wanted to use EPiServer 6 and ASP.NET MVC 2.0, so I started porting the solution.</p>
<p>Porting the solution to EPiServer 6 and ASP.NET MVC 2.0 required some changes to both code and configuration, which not all of them was trivial. At the moment I have a prototype up running, and it works remarkably well! I will continue my experiments and post my results.</p>
]]></content:encoded>
			<wfw:commentRss>http://sourcecodebean.com/archives/first-steps-toward-episerver-and-asp-net-mvc/595/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>EPiServer friendly URLs for paginated pages (and why the asp:LinkButton must die)</title>
		<link>http://sourcecodebean.com/archives/episerver-friendly-urls-for-paginated-pages-and-why-the-asplinkbutton-must-die/510</link>
		<comments>http://sourcecodebean.com/archives/episerver-friendly-urls-for-paginated-pages-and-why-the-asplinkbutton-must-die/510#comments</comments>
		<pubDate>Mon, 15 Mar 2010 06:05:37 +0000</pubDate>
		<dc:creator>Peter</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://sourcecodebean.com/?p=510</guid>
		<description><![CDATA[Recently I got a request from a customer to perform some search engine optimizing for an old EPiServer site we are maintaining. One of the optimizations was to fix the paging on their product page. The products are fetched from an external data source and are not stored as pages in EPiServer, thus normal EPiServer [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I got a request from a customer to perform some search engine optimizing for an old EPiServer site we are maintaining. One of the optimizations was to fix the paging on their product page. The products are fetched from an external data source and are not stored as pages in EPiServer, thus normal EPiServer paging controls can not be used. Image a normal paging control like this:</p>
<p>Prev 1, 2 , 3, &#8230;, 99 Next</p>
<p>A fairly normal approach to this would have been to use a query parameter for handling the paging. Like this:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&lt;a href=&quot;/products/?page=4&quot;&gt;4&lt;/a&gt;</div>
</li>
</ol>
</div>
<p>By using this approach each page would have a unique entry point, using query strings is however not optimal for SEO, but even worse is using asp:LinkButtons. Whoever created the site had decided to use asp:LinkButtons. LinkButtons are very convenient to work with in ASP.NET, but the HTML code they generate is not very SEO friendly. This is the HTML that was generated:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&lt;div id=&quot;ctl00_MainContent_pnlPaging&quot;&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &lt;a id=&quot;ctl00_MainContent_rptPages_ctl00_lbPage&quot;
</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp;href=&quot;javascript:__doPostBack(&#8216;ctl00$MainContent$rptPages$ctl00$lbPage&#8217;,&#8221;)&quot;&gt;1&lt;/a&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &lt;a id=&quot;ctl00_MainContent_rptPages_ctl01_lbPage&quot;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp;href=&quot;javascript:__doPostBack(&#8216;ctl00$MainContent$rptPages$ctl01$lbPage&#8217;,&#8221;)&quot;&gt;2&lt;/a&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &lt;a id=&quot;ctl00_MainContent_rptPages_ctl02_lbPage&quot;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp;href=&quot;javascript:__doPostBack(&#8216;ctl00$MainContent$rptPages$ctl02$lbPage&#8217;,&#8221;)&quot;&gt;3&lt;/a&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &lt;a id=&quot;ctl00_MainContent_lbNext&quot;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp;href=&quot;javascript:__doPostBack(&#8216;ctl00$MainContent$lbNext&#8217;,&#8221;)&quot;&gt;Next&lt;/a&gt;
</div>
</li>
<li class="li2">
<div class="de2">&lt;/div&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
</ol>
</div>
<p>We can see that:</p>
<ul>
<li>LinkButtons generates a javascript that is run when the link is clicked, instead of using a normal link</li>
<li>Paging is handled using a postback, the pages will no longer have unique entry points.</li>
</ul>
<p>This is <strong>disastrous </strong>from a SEO perspective.</p>
<p>So lets fix it. First step is to replace the LinkButtons with normal links (asp:Hyperlink) &#8211; and then we are going to do some URL rewrite magic to create SEO-friendly URLs. The code behind was changed to assign links like <code>/products/?page=4</code>.</p>
<p>Now, to get URLs like <code>/products/page/4</code>, we can create a custom url rewrite module in EPiServer. First we create a new class, Rewrite,  that inherits from <code>EPiServer.Web.FriendlyUrlRewriteProvider</code>. In this class we override three methods (don&#8217;t ask we why they have such confusing names, someone at EPiServer must have been under the influsene of something when nameing them):</p>
<ul>
<li><code>ConvertToInternalInternal </code>- Used to convert from <code>/product/page/4/</code> to an internal EPiServer page with the page id as a query parameter</li>
<li><code>ConvertToExternalInternal </code>- Used to convert from an internal EPiServer URL (<code>/PageType.aspx?lotsofqueryparameters=values</code>) to an external (<code>/products/page/4/</code>)</li>
<li><code>ConvertToInternal </code>- Needed to work around URL rewrite caching behaviour in EPiServer, will get into more detail on this later.</li>
</ul>
<p>This is the class:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">namespace Utils</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">public class Rewrite : FriendlyUrlRewriteProvider <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1">// The regexp to match a paged url</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; <span class="kw4">string</span> _regexpPaging = @<span class="st0">&quot;(.+)/page/([0-9]+)/$&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; protected override bool ConvertToInternalInternal<span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; UrlBuilder url, ref object internalObject<span class="br0">&#41;</span><span class="br0">&#123;</span>&#8230;<span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; protected override bool ConvertToExternalInternal<span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; UrlBuilder url, object internalObject, Encoding toEncoding<span class="br0">&#41;</span><span class="br0">&#123;</span>&#8230;<span class="br0">&#125;</span> </div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; public override bool ConvertToInternal<span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; UrlBuilder url, out object internalObject<span class="br0">&#41;</span> <span class="br0">&#123;</span>&#8230;<span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p><br/></p>
<p>The first method we implement is the ConvertToInternalInternal which will convert the URL to an internal EPiServer URL.</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">protected override bool ConvertToInternalInternal<span class="br0">&#40;</span>UrlBuilder url, ref object internalObject<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>url == <span class="kw2">null</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1">// Regexp to match if the URL ends with /page/{Id}/</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; Match match = Regex.<span class="me1">Match</span><span class="br0">&#40;</span>url.<span class="me1">Path</span>, _regexpPaging<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; <span class="co1">// If we have a match, remove the /page/{Id}/ from the end of the URL</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1">// and add a querystring to the internal URL that is dqcPagingId </span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1">// (should have a unique name to not clash with some other querystring)</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>match.<span class="me1">Length</span> &gt; <span class="nu0">0</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; url.<span class="me1">Path</span> = match.<span class="me1">Groups</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>.<span class="me1">Value</span> + <span class="st0">&quot;/&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; url.<span class="me1">QueryCollection</span><span class="br0">&#91;</span><span class="st0">&quot;dqcPagingId&quot;</span><span class="br0">&#93;</span> = match.<span class="me1">Groups</span><span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span>.<span class="me1">Value</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; base.<span class="me1">ConvertToInternalInternal</span><span class="br0">&#40;</span>url, ref internalObject<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1">// Now when the /page/{Id}/ is removed from the URL, and the querystring is added, we can let EPiServer do its normal URL-rewriting.</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">return</span> base.<span class="me1">ConvertToInternalInternal</span><span class="br0">&#40;</span>url, ref internalObject<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p><br/></p>
<p>While not nessesary, we should override the <code>ConvertToExternalInternal </code>as well. This will let EPiServer automatically convert internal urls containing the <code>dqcPagingId </code>querystring to a external url ending with /page/{Id}/.</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">protected override bool ConvertToExternalInternal<span class="br0">&#40;</span>UrlBuilder url, object internalObject, Encoding toEncoding<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="co1">// First let EPiServer convert the internal URL to an external. This will give us a URL like:</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="co1">// /Products/?dqcPagingId=5 (if it is a paged page)</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp;bool isRewritten = base.<span class="me1">ConvertToExternalInternal</span><span class="br0">&#40;</span>url, internalObject, toEncoding<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// Check if the URLs query string contains dqcPagingId</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// If it does we add /page/{Id} to the URL and removes the query string</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>url.<span class="me1">Query</span>.<span class="me1">Contains</span><span class="br0">&#40;</span><span class="st0">&quot;dqcPagingId&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; url.<span class="me1">Path</span> = <span class="kw4">string</span>.<span class="me1">Concat</span><span class="br0">&#40;</span>url.<span class="me1">Path</span>, <span class="st0">&quot;page/&quot;</span>, url.<span class="me1">QueryCollection</span><span class="br0">&#91;</span><span class="st0">&quot;dqcPagingId&quot;</span><span class="br0">&#93;</span>, <span class="st0">&quot;/&quot;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; url.<span class="me1">QueryCollection</span>.<span class="me1">Remove</span><span class="br0">&#40;</span><span class="st0">&quot;dqcPagingId&quot;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="kw1">return</span> isRewritten;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p><br/></p>
<p>Now one can think we would be done, but there is one more method we need to implement. EPiServer uses a cache to cache URL rewrites from external URLs to internal URLs, but it will only cache the querystrings used by EPiServer, not the <code>dqcPagingId </code>we added. This gives a rather unexpected result. The first time the page is loaded everything loads fine, from code behind we can access the <code>dqcPagingId </code>and show the requested page. If you wait 10 senconds (default cache time) or more and reloads the page, it works fine. But if you reload the page sooner, the dqcPagingId will not be set when the page loads. This is because the querystring <code>dqcPagingId </code>is not cached by EPiServer. This took me quite some time to figure out.</p>
<p>The solution to the problem is to override ConvertToInternal to bypass the default caching:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">public override bool ConvertToInternal<span class="br0">&#40;</span>UrlBuilder url, out object internalObject<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1">// If the URL end on /page/{id}/, bypass cache by calling ConvertToInternalInternal</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; <span class="co1">// A more optimal solution would be to perform some kind of caching here</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>Regex.<span class="me1">IsMatch</span><span class="br0">&#40;</span>url.<span class="me1">Path</span>, _regexpPaging<span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; internalObject = <span class="kw2">null</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; ConvertToInternalInternal<span class="br0">&#40;</span>url, ref internalObject<span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1">// Else, it is ok to use the cached result</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">return</span> base.<span class="me1">ConvertToInternal</span><span class="br0">&#40;</span>url, out internalObject<span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
</ol>
</div>
<p><br/></p>
<p>The last step is to add our Rewrite module to the web.config:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &lt;providers&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &lt;add
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp;name=&quot;MyUrlRewriter&quot;
</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp;enableSimpleAddress=&quot;true&quot;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp;friendlyUrlCacheAbsoluteExpiration=&quot;0:0:10&quot;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp;type=&quot;Utils.Rewrite, Utils&quot;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp;description=&quot;URL rewriter for paging&quot; /&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &lt;/providers&gt;
</div>
</li>
<li class="li2">
<div class="de2">&lt;/urlRewrite&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
</ol>
</div>
<p><br/></p>
<p>Now we should be all done! Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://sourcecodebean.com/archives/episerver-friendly-urls-for-paginated-pages-and-why-the-asplinkbutton-must-die/510/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Creating a JSON-RPC service using Zend Json Server</title>
		<link>http://sourcecodebean.com/archives/creating-a-json-rpc-service-using-zend-json-server/422</link>
		<comments>http://sourcecodebean.com/archives/creating-a-json-rpc-service-using-zend-json-server/422#comments</comments>
		<pubDate>Thu, 07 Jan 2010 08:11:15 +0000</pubDate>
		<dc:creator>Peter</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://sourcecodebean.com/?p=422</guid>
		<description><![CDATA[In this post I am going to show how easy it is to create a JSON-RPC web service using the built in support in Zend Framework.
First we need to create the php-file that will handle the incoming RPC calls. It is not advised to put this inside the MVC structure of a Zend web application, [...]]]></description>
			<content:encoded><![CDATA[<p>In this post I am going to show how easy it is to create a JSON-RPC web service using the built in support in Zend Framework.</p>
<p>First we need to create the php-file that will handle the incoming RPC calls. It is not advised to put this inside the MVC structure of a Zend web application, since that will lead to unessesary complexity and overhead. The Zend people recommend that we create the JSON-RPC under <code>/public/api/vX/</code>, so lets create the file <code>/public/api/v1/jsonrpc.php</code> (if you haven&#8217;t setup your Zend MVC structure, read my blog post  <a href="http://sourcecodebean.com/archives/getting-started-with-the-zend-framework/374">Getting started with the zend framework</a> to get started).</p>
<p>We will have to do the regular bootstrapping to get our application up and running:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Define path to application directory</span></div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.php.net/defined"><span class="kw3">defined</span></a><span class="br0">&#40;</span><span class="st0">&#8216;APPLICATION_PATH&#8217;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; || <a href="http://www.php.net/define"><span class="kw3">define</span></a><span class="br0">&#40;</span><span class="st0">&#8216;APPLICATION_PATH&#8217;</span>, <a href="http://www.php.net/realpath"><span class="kw3">realpath</span></a><span class="br0">&#40;</span><a href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">&#40;</span><span class="kw2">__FILE__</span><span class="br0">&#41;</span> . <span class="st0">&#8216;/../../../application&#8217;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Define application environment</span></div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.php.net/defined"><span class="kw3">defined</span></a><span class="br0">&#40;</span><span class="st0">&#8216;APPLICATION_ENV&#8217;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; || <a href="http://www.php.net/define"><span class="kw3">define</span></a><span class="br0">&#40;</span><span class="st0">&#8216;APPLICATION_ENV&#8217;</span>, <span class="br0">&#40;</span><a href="http://www.php.net/getenv"><span class="kw3">getenv</span></a><span class="br0">&#40;</span><span class="st0">&#8216;APPLICATION_ENV&#8217;</span><span class="br0">&#41;</span> ? <a href="http://www.php.net/getenv"><span class="kw3">getenv</span></a><span class="br0">&#40;</span><span class="st0">&#8216;APPLICATION_ENV&#8217;</span><span class="br0">&#41;</span> : <span class="st0">&#8216;production&#8217;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="co1">// Ensure library/ is on include_path</span></div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.php.net/set_include_path"><span class="kw3">set_include_path</span></a><span class="br0">&#40;</span><a href="http://www.php.net/implode"><span class="kw3">implode</span></a><span class="br0">&#40;</span>PATH_SEPARATOR, <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <a href="http://www.php.net/realpath"><span class="kw3">realpath</span></a><span class="br0">&#40;</span><span class="st0">&#8216;../../../library&#8217;</span><span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <a href="http://www.php.net/get_include_path"><span class="kw3">get_include_path</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">/** Zend_Application */</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">require_once</span> <span class="st0">&#8216;Zend/Application.php&#8217;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Create application, bootstrap, and run</span></div>
</li>
<li class="li2">
<div class="de2"><span class="re0">$application</span> = <span class="kw2">new</span> Zend_Application<span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; APPLICATION_ENV,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; APPLICATION_PATH . <span class="st0">&#8216;/configs/application.ini&#8217;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="re0">$application</span>-&gt;<span class="me1">bootstrap</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
</ol>
</div>
<p>The next step is to create the class that will be exposed through the service. I will create a very simple class that will simply perform an addition of two ints. It is very important to describe the input parameters using the @param directive in the comment. This information is used by the Json Server when creating the SMD (Service Mapping Description).</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">/**</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* Simple &#8211; sample class to expose via JSON-RPC</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;*/</span></div>
</li>
<li class="li2">
<div class="de2"><span class="kw2">class</span> Simple</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="coMULTI">/**</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp; &nbsp; &nbsp;* Return sum of two variables</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp; &nbsp; &nbsp;*</span></div>
</li>
<li class="li2">
<div class="de2"><span class="coMULTI">&nbsp; &nbsp; &nbsp;* @param &nbsp;int $x</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp; &nbsp; &nbsp;* @param &nbsp;int $y</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp; &nbsp; &nbsp;* @return array</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp; &nbsp; &nbsp;*/</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> add<span class="br0">&#40;</span><span class="re0">$x</span>, <span class="re0">$y</span><span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&#8216;result&#8217;</span> =&gt; <span class="re0">$x</span> + <span class="re0">$y</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
</ol>
</div>
<p>The last step to get the JSON-RPC server running:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Instantiate server, etc.</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$server</span> = <span class="kw2">new</span> Zend_Json_Server<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$server</span>-&gt;<span class="me1">setClass</span><span class="br0">&#40;</span><span class="st0">&#8216;Simple&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">if</span> <span class="br0">&#40;</span><span class="st0">&#8216;GET&#8217;</span> == <span class="re0">$_SERVER</span><span class="br0">&#91;</span><span class="st0">&#8216;REQUEST_METHOD&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// Indicate the URL endpoint, and the JSON-RPC version used:</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$server</span>-&gt;<span class="me1">setTarget</span><span class="br0">&#40;</span><span class="st0">&#8216;/api/v1/jsonrpc.php&#8217;</span><span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-&gt;<span class="me1">setEnvelope</span><span class="br0">&#40;</span>Zend_Json_Server_Smd::<span class="me2">ENV_JSONRPC_2</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// Grab the SMD</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$smd</span> = <span class="re0">$server</span>-&gt;<span class="me1">getServiceMap</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="co1">// Return the SMD to the client</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <a href="http://www.php.net/header"><span class="kw3">header</span></a><span class="br0">&#40;</span><span class="st0">&#8216;Content-Type: application/json&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$smd</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">return</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$server</span>-&gt;<span class="me1">handle</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
</ol>
</div>
<p>Now your JSON-RPC Server should be up running. Browsing <code>http://{your web server}/api/v1/jsonrpc.php</code> should result in the following SMD:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="st0">&quot;transport&quot;</span>:<span class="st0">&quot;POST&quot;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="st0">&quot;envelope&quot;</span>:<span class="st0">&quot;JSON-RPC-2.0&quot;</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; <span class="st0">&quot;contentType&quot;</span>:<span class="st0">&quot;application<span class="es0">\/</span>json&quot;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="st0">&quot;SMDVersion&quot;</span>:<span class="st0">&quot;2.0&quot;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="st0">&quot;target&quot;</span>:<span class="st0">&quot;<span class="es0">\/</span>api<span class="es0">\/</span>v1<span class="es0">\/</span>jsonrpc.php&quot;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="st0">&quot;services&quot;</span>: <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="st0">&quot;add&quot;</span>:<span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;envelope&quot;</span>:<span class="st0">&quot;JSON-RPC-2.0&quot;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;transport&quot;</span>:<span class="st0">&quot;POST&quot;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;parameters&quot;</span>:<span class="br0">&#91;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><span class="st0">&quot;type&quot;</span>:<span class="st0">&quot;integer&quot;</span>,<span class="st0">&quot;name&quot;</span>:<span class="st0">&quot;x&quot;</span>,<span class="st0">&quot;optional&quot;</span>:<span class="kw2">false</span><span class="br0">&#125;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><span class="st0">&quot;type&quot;</span>:<span class="st0">&quot;integer&quot;</span>,<span class="st0">&quot;name&quot;</span>:<span class="st0">&quot;y&quot;</span>,<span class="st0">&quot;optional&quot;</span>:<span class="kw2">false</span><span class="br0">&#125;</span><span class="br0">&#93;</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;returns&quot;</span>:<span class="st0">&quot;array&quot;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="st0">&quot;methods&quot;</span>:<span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;add&quot;</span>:<span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;envelope&quot;</span>:<span class="st0">&quot;JSON-RPC-2.0&quot;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;transport&quot;</span>:<span class="st0">&quot;POST&quot;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;parameters&quot;</span>:<span class="br0">&#91;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#123;</span><span class="st0">&quot;type&quot;</span>:<span class="st0">&quot;integer&quot;</span>,<span class="st0">&quot;name&quot;</span>:<span class="st0">&quot;x&quot;</span>,<span class="st0">&quot;optional&quot;</span>:<span class="kw2">false</span><span class="br0">&#125;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#123;</span><span class="st0">&quot;type&quot;</span>:<span class="st0">&quot;integer&quot;</span>,<span class="st0">&quot;name&quot;</span>:<span class="st0">&quot;y&quot;</span>,<span class="st0">&quot;optional&quot;</span>:<span class="kw2">false</span><span class="br0">&#125;</span><span class="br0">&#93;</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;returns&quot;</span>:<span class="st0">&quot;array&quot;</span><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
</ol>
</div>
<p>jQuery does not support calling JSON-RPC services out of the box, but fourtenly there is plenty of plugins for jquery that fixes this. One is the JSON-RPC client found <a href="http://www.tanabi.com/projects/jsonrpc ">here</a>. Download the client and put the javascript files into your <code>/js</code> folder. Then create a new file <code>test.html</code> and add the following html:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&lt;html&gt;
</div>
</li>
<li class="li1">
<div class="de1">&lt;head&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &lt;script LANGUAGE=&quot;javascript&quot; SRC=&quot;js/jquery-1.3.min.js&quot;&gt;&lt;/script&gt;
</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &lt;script LANGUAGE=&quot;javascript&quot; SRC=&quot;js/json2.js&quot;&gt;&lt;/script&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &lt;script LANGUAGE=&quot;javascript&quot; SRC=&quot;js/jquery.zend.jsonrpc.js&quot;&gt;&lt;/script&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &lt;script&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $(document).ready(function(){
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; test = jQuery.Zend.jsonrpc({url: &#8216;/api/v1/jsonrpc.php&#8217;});
</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; alert(test.add(1,1)['result']);
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &lt;/script&gt;
</div>
</li>
<li class="li1">
<div class="de1">&lt;/head&gt;
</div>
</li>
<li class="li1">
<div class="de1">&lt;body&gt;
</div>
</li>
<li class="li2">
<div class="de2">&lt;/body&gt;
</div>
</li>
<li class="li1">
<div class="de1">&lt;/html&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
</ol>
</div>
<p>We are all done! Browsing test.html should result in an alert box containg the result.<br />
<a href="http://sourcecodebean.com/wp-content/uploads/2010/01/result.png"><img src="http://sourcecodebean.com/wp-content/uploads/2010/01/result.png" alt="result" title="result" width="420" height="153" class="aligncenter size-full wp-image-442" /></a></p>
<p>Congratulations! You have created a JSON-RPC service!</p>
<p> <br/><br />
Read more about the Zend Framework:</p>
<ul>
<li><a href="http://sourcecodebean.com/archives/creating-a-custom-view-helper-in-the-zend-framework/6">Creating a custom View Helper in the Zend Framework</a></li>
<li><a href="http://sourcecodebean.com/archives/friendly-urls-and-the-zend-router/31">Friendly URLs and the Zend</a></li>
<li><a href="http://sourcecodebean.com/archives/upgrading-from-zend-framework-1-7-to-1-9-the-autoloader/414">Upgrading from Zend Framework 1.7 to 1.9 – The autoloader</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://sourcecodebean.com/archives/creating-a-json-rpc-service-using-zend-json-server/422/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Upgrading from Zend Framework 1.7 to 1.9 &#8211; The autoloader</title>
		<link>http://sourcecodebean.com/archives/upgrading-from-zend-framework-1-7-to-1-9-the-autoloader/414</link>
		<comments>http://sourcecodebean.com/archives/upgrading-from-zend-framework-1-7-to-1-9-the-autoloader/414#comments</comments>
		<pubDate>Wed, 30 Dec 2009 16:54:56 +0000</pubDate>
		<dc:creator>Peter</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://sourcecodebean.com/?p=414</guid>
		<description><![CDATA[Today I upgraded a project we started working on last year from Zend Framework 1.7 to Zend Framework 1.9. I excepted to run into several API incompatibilities, but the only problem I got was the autoloader.
In Zend 1.7, and earlier versions, the autoloader was registered like this:



&#160;


require_once &#34;Zend/Loader.php&#34;;


Zend_Loader::registerAutoload&#40;&#41;;


&#160;



In Zend Framwork 1.9 this has changed slightly, [...]]]></description>
			<content:encoded><![CDATA[<p>Today I upgraded a project we started working on last year from Zend Framework 1.7 to Zend Framework 1.9. I excepted to run into several API incompatibilities, but the only problem I got was the autoloader.</p>
<p>In Zend 1.7, and earlier versions, the autoloader was registered like this:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">require_once</span> <span class="st0">&quot;Zend/Loader.php&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">Zend_Loader::<span class="me2">registerAutoload</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
</ol>
</div>
<p>In Zend Framwork 1.9 this has changed slightly, you now have to register the namespaces you want to autoload:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">require_once</span> <span class="st0">&#8216;Zend/Loader/Autoloader.php&#8217;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$loader</span> = Zend_Loader_Autoloader::<span class="me2">getInstance</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$loader</span>-&gt;<span class="me1">registerNamespace</span><span class="br0">&#40;</span><span class="st0">&#8216;Dqc_&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
</ol>
</div>
<p>This was the only change we needed to do to upgrade from 1.7 to 1.9, quite impressive! </p>
]]></content:encoded>
			<wfw:commentRss>http://sourcecodebean.com/archives/upgrading-from-zend-framework-1-7-to-1-9-the-autoloader/414/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting started with the Zend Framework</title>
		<link>http://sourcecodebean.com/archives/getting-started-with-the-zend-framework/374</link>
		<comments>http://sourcecodebean.com/archives/getting-started-with-the-zend-framework/374#comments</comments>
		<pubDate>Sun, 13 Dec 2009 21:53:00 +0000</pubDate>
		<dc:creator>Peter</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://sourcecodebean.com/?p=374</guid>
		<description><![CDATA[It used to be a bit tricky to get started with the Zend Framework. The Zend Framework is very flexible and allows you to set it up in almost any way that fits your needs. This means for example that the directory structure and location of files is up to you, however &#8211; there is [...]]]></description>
			<content:encoded><![CDATA[<p>It used to be a bit tricky to get started with the Zend Framework. The Zend Framework is very flexible and allows you to set it up in almost any way that fits your needs. This means for example that the directory structure and location of files is up to you, however &#8211; there is a recommended layout. When I first started using Zend I had to figure out this by looking at examples and reading the (at that time) rather poor documentation available. In Zend Framework 1.9 a tool, <code>zf.sh</code>, was introduced. It simplifies creating a new site a lot. In this blogpost I will guide you though the process of setting up a Zend development environment in OS X. The only part that is OS X specific is MAMP. Zend Framework runs just fine under Windows and Linux as well.  </p>
<p><strong>Step 1 &#8211; Getting a *AMP setup (LAMP, MAMP, WAMP)</strong><br />
The AMP (Apache, Mysql, PHP) stack is available for almost all modern operating systems. I am writing this on my Macbook, so in this tutorial I will use <a href="http://www.mamp.info">MAMP</a>. When I develop PHP in Windows I usually use WAMPServer and in Linux you can install the LAMP-stack using the packaging system in most distributions.  </p>
<p>Setting up MAMP is pretty straightforward, download the <a href="http://www.mamp.info/en/downloads/index.html">MAMP .dmg-file</a> and drag the MAMP folder to your Applications folder.<br />
<a href="http://sourcecodebean.com/wp-content/uploads/2009/12/mamp.png"><img src="http://sourcecodebean.com/wp-content/uploads/2009/12/mamp.png" alt="mamp" title="mamp" width="423" height="344" class="aligncenter size-full wp-image-384" /></a></p>
<p>Start the application and press the &#8220;Open start page&#8221; button to make sure everything works. On the start page you will find information about your site, phpInfo, phpMyAdmin and SqLiteManager. We will get back to configuring the http root directory later.</p>
<p><strong>Step 2 &#8211; Download and install Zend Framework</strong><br />
Go to the <a href="http://framework.zend.com/download/current/">framwork download page</a> and download the minimal distribution. In this tutorial I am using 1.9.6, but the instructions will probably apply to all 1.9 versions. </p>
<p>Extract the downloaded file and move the folder to a shared location, for example /usr/local/. Next step is to create an alias for the zf.sh tool. Edit your ~/.bash_profile and add the following line (change the path to where you moved the extracted files):</p>
<blockquote><p><code>zf=/usr/local/ZendFramework1.9/bin/zf.sh</code></p></blockquote>
<p>This will allow you execute the zf tool without using the full path. Try it out by executing <code>zf show version</code>, it should return the version number of the file you downloaded.</p>
<blockquote><p><code><br />
$ zf show version<br />
Zend Framework Version: 1.9.6<br />
</code></p></blockquote>
<p><strong>Step 3 &#8211; Create your project</strong><br />
Go to the folder where you want to create your new project, in my case ~/Development/. Run <code>zf create project zf-tutorial</code>. This will setup the default directory structure and create the necessary files. </p>
<p><a href="http://sourcecodebean.com/wp-content/uploads/2009/12/zendstructure.png"><img src="http://sourcecodebean.com/wp-content/uploads/2009/12/zendstructure.png" alt="Zend Framework directory structure" title="Zend Framework directory structure" width="252" height="397" class="aligncenter size-full wp-image-386" /></a></p>
<p>The application/ folder is where the source code for your website lives. It contains separate folder for models, views and controllers. The public/ folder is the folder that is going to be your document root. </p>
<p>Now you need to copy the Zend library (in my case /usr/local/ZendFramework1.9/library/Zend) or create a symlink for it so your site can find the Zend files. I prefer using a symlink: </p>
<blockquote><p><code><br />
$ cd ~/Development/zf-tutorial/library<br />
$ ln -s /usr/local/ZendFramework1.9/library/Zend/ Zend<br />
</code></p></blockquote>
<p><strong>Step 4 &#8211; Run the project</strong><br />
The last step before we will have running site up is to configure the step that we skipped in Step 1, configuring the Apache document root.<br />
<a href="http://sourcecodebean.com/wp-content/uploads/2009/12/sitesettings.png"><img src="http://sourcecodebean.com/wp-content/uploads/2009/12/sitesettings.png" alt="sitesettings" title="sitesettings" width="359" height="238" class="aligncenter size-full wp-image-388" /></a></p>
<p>Open up MAMP and click the preferences button, under the apache tab you will find the document root. Click select and navigate to the &#8220;public&#8221; folder in your zend project. Apply the settings and restart the server. </p>
<p>Now open your browser and direct it to <a href="http://localhost">http://localhost</a> and you should see the default welcomescreen:<br />
<a href="http://sourcecodebean.com/wp-content/uploads/2009/12/zenddefault.png"><img src="http://sourcecodebean.com/wp-content/uploads/2009/12/zenddefault.png" alt="zenddefault" title="zenddefault" width="610" height="408" class="aligncenter size-full wp-image-390" /></a></p>
<p>Now open your <code>application/controllers/IndexController.php</code> and start hacking your code!</p>
<p> <br/><br />
If you want to learn more about the Zend Framework i have some posts on some more advanced topics:</p>
<ul>
<li><a href="http://sourcecodebean.com/archives/creating-a-custom-view-helper-in-the-zend-framework/6">Creating a custom View Helper in the Zend Framework</a></li>
<li><a href="http://sourcecodebean.com/archives/friendly-urls-and-the-zend-router/31">Friendly URLs and the Zend</a></li>
<li><a href="http://sourcecodebean.com/archives/upgrading-from-zend-framework-1-7-to-1-9-the-autoloader/414">Upgrading from Zend Framework 1.7 to 1.9 – The autoloader</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://sourcecodebean.com/archives/getting-started-with-the-zend-framework/374/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Book review: ASP.NET MVC 1.0 &#8211; Test Driven Development</title>
		<link>http://sourcecodebean.com/archives/book-review-asp-net-mvc-1-0-test-driven-development/354</link>
		<comments>http://sourcecodebean.com/archives/book-review-asp-net-mvc-1-0-test-driven-development/354#comments</comments>
		<pubDate>Wed, 09 Dec 2009 09:28:25 +0000</pubDate>
		<dc:creator>Peter</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://sourcecodebean.com/?p=354</guid>
		<description><![CDATA[About a month ago I finished reading the book ASP.NET MVC 1.0 &#8211; Test Driven Development by Emad Ibrahim. The book weighs in only at about 300 pages, making it easily something you can read in a couple of nights. The book is written in tutorial fashion and is is probably best read with a [...]]]></description>
			<content:encoded><![CDATA[<p>About a month ago I finished reading the book ASP.NET MVC 1.0 &#8211; Test Driven Development by Emad Ibrahim. The book weighs in only at about 300 pages, making it easily something you can read in a couple of nights. The book is written in tutorial fashion and is is probably best read with a laptop running Visual Studio on your lap, so you can follow the examples in the book. The paradigm of the book is Problem, Design, Solution. Emand gudies the reader though the full process of creating a web application in a Test Driven manner. </p>
<p>Besides from only presenting MVC and TTD Emand presents several very useful libraries for Test Driven Development:</p>
<ul>
<li>Moq &#8211; A mocking library for .NET that uses the power of LINQ to create mocks.</li>
<li>Ninject &#8211; Dependency injection library for .NET</li>
<li>MBunit &#8211; An alternative to VSTest</li>
</ul>
<p>I think the book gives a good kickstart in ASP.NET MVC and TTD. My favorite part of the book was actually not reading about MVC itself, it was reading about testing it &#8211; Emad shows the strengths of MVC by showing how it makes testing easier. </p>
]]></content:encoded>
			<wfw:commentRss>http://sourcecodebean.com/archives/book-review-asp-net-mvc-1-0-test-driven-development/354/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Microsoft Web Platform Installer</title>
		<link>http://sourcecodebean.com/archives/microsoft-web-platform-installer/296</link>
		<comments>http://sourcecodebean.com/archives/microsoft-web-platform-installer/296#comments</comments>
		<pubDate>Sat, 03 Oct 2009 09:51:40 +0000</pubDate>
		<dc:creator>Peter</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://sourcecodebean.com/?p=296</guid>
		<description><![CDATA[I recently needed to setup a new ASP.NET development environment and deiced to give Microsofts Web Platform Installer 2.0 a chance. I had actually never heard about this product before, but what it does is installing .NET, the needed development libraries, and the express versions of Visual Studio and SQL Server. It required three reboots, [...]]]></description>
			<content:encoded><![CDATA[<p>I recently needed to setup a new ASP.NET development environment and deiced to give Microsofts Web Platform Installer 2.0 a chance. I had actually never heard about this product before, but what it does is installing .NET, the needed development libraries, and the express versions of Visual Studio and SQL Server. It required three reboots, but in total it saved me a lot of time! </p>
]]></content:encoded>
			<wfw:commentRss>http://sourcecodebean.com/archives/microsoft-web-platform-installer/296/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Playing with WSGI in Python (part 1)</title>
		<link>http://sourcecodebean.com/archives/playing-with-wsgi-in-python-part-1/280</link>
		<comments>http://sourcecodebean.com/archives/playing-with-wsgi-in-python-part-1/280#comments</comments>
		<pubDate>Mon, 10 Aug 2009 09:00:13 +0000</pubDate>
		<dc:creator>Peter</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://sourcecodebean.com/?p=280</guid>
		<description><![CDATA[For the last month I have been playing around with WSGI in Python. WSGI is an interface between the web server and the web application, it is meant to simplify writing your own web framework in Python. My intention is not to write an fully fledged web framework, but rather just play around with some [...]]]></description>
			<content:encoded><![CDATA[<p>For the last month I have been playing around with WSGI in Python. WSGI is an interface between the web server and the web application, it is meant to simplify writing your own web framework in Python. My intention is not to write an fully fledged web framework, but rather just play around with some ideas I have and try it out.</p>
<p>In WSGI an application is just a callable object (remember that in Python functions are objects too!) that takes two parameters, environ and start_response. A very simple application could look like this:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">def</span> application<span class="br0">&#40;</span>environ, start_response<span class="br0">&#41;</span>:</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;start_response<span class="br0">&#40;</span><span class="st0">&#8216;200 OK&#8217;</span>, <span class="br0">&#91;</span><span class="br0">&#40;</span><span class="st0">&#8216;content-type&#8217;</span>, <span class="st0">&#8216;text/html&#8217;</span><span class="br0">&#41;</span><span class="br0">&#93;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="kw1">return</span> <span class="br0">&#91;</span><span class="st0">&#8216;Hello world!&#8217;</span><span class="br0">&#93;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
</ol>
</div>
<p>Not very exiting but it shows us the very basics of WSGI. The function start_response is a function that, as the name implies, starts sending out the response. This is where you give status and headers. Lastly the application returns an iterator with the body response (usually a list of strings or a list containing one string that is the entire body). As you can see WSGI lets code pass around web request in a fairly formal way.</p>
<p>To run this application you can either install Apache and configure it with modwsgi, this might however be slightly overkill just in order to test the application. Instead I recommend installing Python Paste (pythonpaste.com), which is kind of a framework for web frameworks. It includes a lot of functionality that can be reused, but more importantly right now, it includes a simple web server that can serve WSGI applications. In Ubuntu 9.04 (the operating system I am currently running) Paste can be installed using apt:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">apt-get install python-paste</div>
</li>
</ol>
</div>
<p>To run the application, add the folowing lines to the end of your source file:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">if</span> __name__ == <span class="st0">&#8216;__main__&#8217;</span>:</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">from</span> paste <span class="kw1">import</span> httpserver</div>
</li>
<li class="li1">
<div class="de1">&nbsp; httpserver.<span class="me1">serve</span><span class="br0">&#40;</span>application, host=<span class="st0">&#8216;127.0.0.1&#8242;</span>, port=<span class="st0">&#8216;8000&#8242;</span><span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
</ol>
</div>
<p>
Now it should be possible to run the application:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">$ python appserver.py
</div>
</li>
<li class="li1">
<div class="de1">serving on http://127.0.0.1:8000
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
</ol>
</div>
<p>Your web application is now up running! In the next part i will introduce you to a slightly more exiting application.</p>
]]></content:encoded>
			<wfw:commentRss>http://sourcecodebean.com/archives/playing-with-wsgi-in-python-part-1/280/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Friendly URLs in ASP.NET using URLRewriter.NET</title>
		<link>http://sourcecodebean.com/archives/friendly-urls-in-aspnet-using-urlrewriternet/243</link>
		<comments>http://sourcecodebean.com/archives/friendly-urls-in-aspnet-using-urlrewriternet/243#comments</comments>
		<pubDate>Mon, 22 Jun 2009 11:28:23 +0000</pubDate>
		<dc:creator>Peter</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://sourcecodebean.com/?p=243</guid>
		<description><![CDATA[I was having a chat the other day with Danish Peter (yes, another one) about URL rewrites in ASP.NET. In a previous post I wrote about how to use friendly URLs in the Zend framework, in this post, which is based on our discussion, I will discuss how to do this in ASP.NET.
Friendly URLs are [...]]]></description>
			<content:encoded><![CDATA[<p>I was having a chat the other day with Danish Peter (yes, another one) about URL rewrites in ASP.NET. In a previous post I wrote about how to use friendly URLs in the Zend framework, in this post, which is based on our discussion, I will discuss how to do this in ASP.NET.</p>
<p>Friendly URLs are achieved by a technique called URL-rewrite. A friendly URL is a  URL that is easy to read and understand. Let me give you an example (from a site my girlfriend loves) of what is NOT a friendly URL:</p>
<blockquote><p>http://www.bebe.com/bebe-Jersey-Knit-Apron-Dress/dp/B001UX1NBQ?ie=UTF8&amp;asinSearchPageIndex=13&amp;pf_rd_r=1C6TS27BZZ1CAD6WY81S&amp;navAsinList=B001UNM3XS%2CB001OPYKKQ%2CB001UNNQ52%2CB001RPD88I%<br />
2CB001R4NHHQ%2CB0026BM39W%2CB001QOU6TY%2CB001UX1NNY%2CB001UAA4WI<br />
%2CB0024QP6KM%2CB0026RRN4G%2CB0027DCI6W%2CB001UX3QL6%2CB001UX1NBQ<br />
%2CB001VROPT8%2CB00265NBKS%2CB001RPM80C%2CB001UBWNTO%2CB001RPIC1G<br />
%2CB001PA2NMW&amp;node=675941011&amp;pf_rd_s=search-results&amp;field_browse=675941011&amp;searchSize=20&amp;navAsinListIndex=0&amp;pf_rd_t=101&amp;field_availability=0&amp;id=bebe%20Jersey%20Knit%20Apron%20Dress&amp;searchBinNameList=null&amp;store=core&amp;pf_rd_p=476815091&amp;ref=search_results_14&amp;searchNodeID=675941011&amp;pf_rd_i=675941011&amp;field_launch-date=-1y&amp;searchRank=-custom-rank&amp;searchPage=1&amp;pf_rd_m=A2FMOXN01TSNYY</p></blockquote>
<p>This might be an extreme example, but there are plenty of sites which are as bad. If the above URL was transformed into a friendly URL it might look something like:</p>
<blockquote><p>http://www.bebe.com/Apparel/Dresses/Jersey-Knit-Apron-Dress.html</p></blockquote>
<p>The second address is easier to read. URL rewrite techniques have been around for a long time and the first time I used it was back in the early Apache 1.3 days. Today good sites use friendly URLs and if you have not adopted it yet, you need to start using it.</p>
<p>There are several benefits from using a friendly url scheme, the most prominent are:</p>
<ol>
<li> 1. The clear structure makes it easier for humans to read and understand the addres</li>
<li> 2. It is easier for search engines to understand what the address is and crawler the site.  URL structure that goes more than three directories deep is not always read by a spider.</li>
<li> 3. If search engines understand the URL, it is also easier for them to help people finding what they want, giving better search results. Hence using keywords and proper titles makes life easier.</li>
</ol>
<p><strong>What options are there for ASP.NET?</strong><br />
There is no built in support for having friendly URLs in ASP.NET, but you could spend your time writing your own URL-rewrite module. Writing your own module is basically spending time reinventing the wheel. If you have the time, go ahead, but if not there are already several good ones out there (free and open source). One that I have found very useful is the URLRewriter.NET (http://urlrewriter.net/). URLRewriter.NET provides similar rewrite capabilities as the mod_rewrite does for Apache.</p>
<p><strong>Using URLRewriter.NET</strong><br />
It is possible to use the URLRewriter.NET module without making any changes to the IIS configuration, this will however limit the functionallity the URLRewriter.NET rewriting capabilities. To use its full power, IIS should be configured to map all requests to the ASP.NET runtime (how to do this is covered in the manual). We will only be touching the surface of URLRewriter.NET so we will not have to do any modifications to the IIS configuration.</p>
<p>To add URLRewriter.NET to your project start out by opening Visual Studio or Visual Web Developer. Open your project and then right click the project in the solution explorer and click on Add Reference, go browse and find the folder you downloaded and unzipped.  You will find the binary (.dll) file in <code>“Loation”\urlrewriternet20rc1b6\UrlRewriterV2\bin\Release</code>.</p>
<p>Before we can use the module we need to make some changes to the web.config. Add the following in the configSections:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;configSections<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="sc3"><span class="re1">&lt;section</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">name</span>=<span class="st0">&quot;rewriter&quot;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">requirePermission</span>=<span class="st0">&quot;false&quot;</span> </div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="re0">type</span>=<span class="st0">&quot;Intelligencia.UrlRewriter.Configuration.RewriterConfigurationSectionHandler, Intelligencia.UrlRewriter&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;/configSections<span class="re2">&gt;</span></span></span></div>
</li>
</ol>
</div>
<p>This will allow the URL writer to read the rewrite rules we will define later. Now we need to add this module to the httpModules section:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;system</span>.web<span class="re2">&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="sc3"><span class="re1">&lt;httpModules<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;add</span> </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="re0">type</span>=<span class="st0">&quot;Intelligencia.UrlRewriter.RewriterHttpModule, Intelligencia.UrlRewriter&quot;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; <span class="re0">name</span>=<span class="st0">&quot;UrlRewriter&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/httpModules<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;<span class="sc3"><span class="re1">&lt;/system</span>.web<span class="re2">&gt;</span></span></div>
</li>
</ol>
</div>
<p>By adding the rewriter as a httpModule we allow it to intercept web requests and route the requests to the actual aspx file serving the page. Now we need to define the rewrite rules:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;rewriter<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="sc3"><span class="re1">&lt;rewrite</span> <span class="re0">url</span>=<span class="st0">&quot;~/(.+)/(.+)/(.+)/(.+).shtml&quot;</span> <span class="re0">to</span>=<span class="st0">&quot;~/Default.aspx?Year=$1&amp;amp;Month=$2&amp;amp;Date=$3&amp;amp;Title=$4&quot;</span><span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="sc3"><span class="re1">&lt;rewrite</span> <span class="re0">url</span>=<span class="st0">&quot;~/Article/(.+).shtml&quot;</span> <span class="re0">to</span>=<span class="st0">&quot;~/Articles.aspx?ID=$1&quot;</span><span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;/rewriter<span class="re2">&gt;</span></span></span></div>
</li>
</ol>
</div>
<p>The rewrite rules are defined using regular expressions. Regular expressions are very powerful and is something every programmer should know. The syntax might be hard to remember but there are several great tools to help build advanced regular expressions, for example the RegexDesigner.NET (http://www.sellsbrothers.com/tools/#regexd) that Chris Sells has created.</p>
<p>The above rewrite rules are simple. The first rewrite rule will rewrite URLs like<br />
<blockquote>sourcecodebean.com/2009/04/01/1.shtml</p></blockquote>
<p> to </p>
<blockquote><p>sourcecodebean.com/Default.aspx?Year=2009&#038;Month=04&#038;Date=01&#038;Id=1</p></blockquote>
<p><br/><br />
And the second rewrite rule will match requests starting with ~/Article/ so it will rewrite URLs like<br />
<blockquote>sourcecodebean.com/Article/1.shtml</p></blockquote>
<p> to<br />
<blockquote>sourcecodebean.com/Articles.aspx?ID=1</p></blockquote>
<p><strong>Finishing up</strong><br />
By now you hopefully have a functioning site that uses friendly URLs. One of the common problems you might run into is broken links. To avoid this you should make sure that you reference all your pages from the root level (~) and that all your links has the runat=server tag.</p>
<p>Thanks for your input Peter!  You can check out his Danish Peter blog over at <a href="http://www.magic-mouse.dk">Magic Mouse</a>. </p>
]]></content:encoded>
			<wfw:commentRss>http://sourcecodebean.com/archives/friendly-urls-in-aspnet-using-urlrewriternet/243/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>The importance of web standards (and why you should not design for browsers)</title>
		<link>http://sourcecodebean.com/archives/the-importance-of-web-standards-and-why-you-should-not-design-for-browsers/227</link>
		<comments>http://sourcecodebean.com/archives/the-importance-of-web-standards-and-why-you-should-not-design-for-browsers/227#comments</comments>
		<pubDate>Mon, 15 Jun 2009 12:05:08 +0000</pubDate>
		<dc:creator>Peter</dc:creator>
				<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://sourcecodebean.com/?p=227</guid>
		<description><![CDATA[For the last three months I have been working with one of Sweden&#8217;s largest companies. When I arrived the first day I noticed that it was not possible to log in to the intranet using Firefox. The explanation I received:
&#8220;our sites are built for Internet Explorer, you have to use it&#8221;
In my head a warning [...]]]></description>
			<content:encoded><![CDATA[<p>For the last three months I have been working with one of Sweden&#8217;s largest companies. When I arrived the first day I noticed that it was not possible to log in to the intranet using Firefox. The explanation I received:</p>
<blockquote><p>&#8220;our sites are built for Internet Explorer, you have to use it&#8221;</p></blockquote>
<p>In my head a warning bell rang. I fired up Internet Explorer to find that the whole site was a horrible mix of broken HTML, badly written Javascript, lot of frames and almost no use of CSS. It surly could not work in anything else other than Internet Explorer 6 and 7.</p>
<p>My job was not the development of the intranet (which I am glad for), so I just told the customer what I thought and that they should do a better job of following web standards so the users could use the browser of their choice. The kind of stupid response I got was something in style with:</p>
<blockquote><p>&#8220;we concentrate on Microsoft technologies, so the only requirement we have is that it should work in Internet Explorer&#8221;</p></blockquote>
<p>The fun started during my last week at the company, when Microsoft started to push out Internet Explorer 8 to all Windows Update users. IE8 is actually very strict when it comes to following web standards. Lo and behold, none of the users who had their systems upgraded could use the intranet. IE8, now strict on standards, vomited back the bad intranet and the company basically came to standstill. Chaos!</p>
<p>I observed the chaos (smiling) for an hour before I decided to save the day by telling them about &#8220;EmulateIE7&#8243;. By default, IE8 uses the new IE8 rendering engine. The big difference from before is that if a site is broken IE8 will NOT default to an older rendering engine. This is different from how older IE browsers behaved and is clearly a step in the right direction for Microsoft to support web standards. However they have not scraped backwards compatibility entirely. In order to allow for broken sites to be viewed in IE8, it is possible for the developer to add the following meta-tag to the page:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;meta</span> <span class="re0">http-equiv</span>=<span class="st0">&quot;X-UA-Compatible&quot;</span> <span class="re0">content</span>=<span class="st0">&quot;IE=EmulateIE7&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
</ol>
</div>
<p>This tag will tell IE8 to use the IE7 rendering engine.</p>
<p>And if you are stubborn enough to believe that building websites for browsers is acceptable, there are reasons why we need web standards:</p>
<ol>
<li><strong>1. Accessibility is the law</strong>:  FCC regulations in the United States require that web sites are accessible to people with disabilities. If a website cannot be viewed by someone with an impairment, it is not only illegal but highly unfair to visitors.  With proper web standards, these visitors can change font and modify a website layout to make it easier to read.</li>
<li><strong>2. Better search engine rankings</strong>: While people may be gung ho for &#8220;SEO&#8221; and those techniques, some of the most basic and most important ways of reading a website can improve the reading by a search engine spider. Combined with semantic markup, the separation of content and presentation generally improves search engine rankings.</li>
<li><strong>3. Easier development and maintenance</strong>: Using semantic and structured HTML makes it easier and quicker to understand code created by somebody else. Since every programmer leaves a footprint in their style of code, those that write web standards will make it easy for others to understand code.  It will also help avoid the hackneyed job that many sites exist in today.</li>
<li><strong>4. CSS = Faster downloading and rendering of pages</strong>: Using CSS for presentation style leads to leaner HTML documents.  It also makes it easier to globally change attributes.  Leaner files means quicker downloads for visitors.</li>
<li><strong>5. Semantic HTML is friendly to adaptation</strong>:  Semantically marked up documents can beadapted to print and alternative browsing devices (PDAs, iPhones, netbooks) by linking to a different CSS file.</li>
</ol>
<p>After the incident was resolved we had a long discussing about web standards, and the company now understands that you can not design a site for a certain browser, it should be designed to follow accepted web standards.</pre>
]]></content:encoded>
			<wfw:commentRss>http://sourcecodebean.com/archives/the-importance-of-web-standards-and-why-you-should-not-design-for-browsers/227/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
