PageRenderTime 67ms CodeModel.GetById 41ms app.highlight 5ms RepoModel.GetById 15ms app.codeStats 0ms

/src/Amptools/Public/blogs/michaelherndon/archives/2008_07_13_index.aspx

https://github.com/pvencill/amptools
ASP.NET | 488 lines | 372 code | 116 blank | 0 comment | 30 complexity | b021e4de52dce8e89c9ee8c221ebe717 MD5 | raw file
  1<%@ Page Title="amptools.net: 07.13.2008" Language="C#" MasterPageFile="~/App/Views/Layouts/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="System.Web.Mvc.ViewPage" %>
  2<asp:Content ID="Content2" ContentPlaceHolderID="Head" runat="server">   
  3       	<link href='/Content/default/css/syntax-highlighter.css' rel="stylesheet" type="text/css" />
  4	<link rel="alternate" type="application/rss+xml" title="amptools.net - RSS" href="http://feeds.feedburner.com/amptoolsnet" />
  5	<link rel="service.post" type="application/atom+xml" title="amptools.net - Atom" href="http://www.blogger.com/feeds/7043853799247804655/posts/default" />
  6	<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://www.blogger.com/rsd.g?blogID=7043853799247804655" />
  7	<style type="text/css">
  8		@import url("http://www.blogger.com/css/blog_controls.css");
  9		@import url("http://www.blogger.com/dyn-css/authorization.css?targetBlogID=7043853799247804655");
 10	</style>
 11
 12	<script type="text/javascript" src="http://www.blogger.com/js/backlink.js"></script>
 13	<script type="text/javascript" src="http://www.blogger.com/js/backlink_control.js"></script>
 14	<script type="text/javascript">var BL_backlinkURL = "http://www.blogger.com/dyn-js/backlink_count.js";var BL_blogId = "7043853799247804655";</script>
 15</asp:Content>
 16
 17<asp:Content ID="Content3" ContentPlaceHolderID="Javascript" runat="server">
 18		<script type="text/javascript" src="~/javascripts/prototype.js"></script>
 19		<script type="text/javascript" src="~/javascripts/syntax-highlighter/shCore.js"></script>
 20		<script type="text/javascript" src="~/javascripts/syntax-highlighter/shBrushCSharp.js"></script>
 21		<script type="text/javascript" src="~/javascripts/syntax-highlighter/shBrushRuby.js"></script>
 22		<script type="text/javascript" src="~/javascripts/syntax-highlighter/shBrushJScript.js"></script>
 23		<script type="text/javascript" src="~/javascripts/syntax-highlighter/shBrushCss.js"></script>
 24		<script type="text/javascript" src="~/javascripts/syntax-highlighter/shBrushSql.js"></script>
 25		<script type="text/javascript" src="~/javascripts/syntax-highlighter/shBrushXml.js"></script>
 26		<script type="text/javascript">
 27			//<[CDATA[
 28			dp.SyntaxHighlighter.HighlightAll('code'); 
 29			//]]>
 30		</script>
 31</asp:Content>
 32<asp:Content ID="Content1" ContentPlaceHolderID="main" runat="server">
 33      
 34	
 35		<div class="left">
 36 			<h2 class="silver">
 37				&quot;Working on the complexity that is always indirectly implied by simpilicity.&quot;
 38			</h2>
 39		
 40
 41                  
 42			<h2 class="blog-title"><a name="8164722880411458481"></a>
 43				
 44				 Using WCF to access the Flickr JSON API
 45				
 46				<span class="blog-byline">
 47				by: michael herndon, at: 7/17/2008 06:40:00 AM
 48				</span>
 49				
 50			 </h2>
 51			 <div class="blog-content">
 52				<p>Even though there are quite a few opensource .Net libraries REST API out there, and a really impressive one for Flickr, they tend to never evolve or fork to use the newer framework technologies.&#160; I think its great that they support 1.0, 2.0, and mono, but why not fork and support WCF?&#160; I think part of the problem that .Net 3.5 use is not wide spread as it should be is not only information overload and bad naming for extension libraries, but also lack of opensource support to provide libraries and basis for current technology.&#160; </p>  <p>Flickr tends to be a little more tricky to use when calling it than some other REST APIs. WCF is a cool technology, but needs to be massaged when using it with Flickr due to a couple of gotchas and not so obvious things about WCF. In order to use Flickr, you need to register for an api_key and a shared secret code which is used to create an MD5 hash. You also need to create that MD5 each time you call a method, using the url parameters in a certain way. </p>  <p>There are also a few not so obvious factors about using the JSON part of Flickr. All of the .Net libraries I've seen so far, use XML. While C# is king of parsing&#160; XML, JSON tends to be more compact, which means less expense over the wire, though it might mean more time parsing once on the developers end point. So there are tradeoffs to using it. </p>  <p>When I created the classes needed to use WCF to call Flickr, I have the actual &quot;DataContract&quot; object (DTO, Data Transfer Object), A Hash (Dictionary&lt;string, object&gt;) for adding the parameters to create the MD5 signature, A base class for creating the WCF proxy, a custom &quot;WebContentTypeMapper&quot;, The &quot;ServiceContract&quot; interface, the actual &quot;Client class&quot;, and a mixins class for creating the MD5. </p>  <p>Here are some of the gotchas that I ran into while getting WCF to work with Flickr. </p>  <p></p>  <ol>   <li>Flickr makes you create a md5 hash to send with every call for ALL parameters in alphabetical order using your &quot;Shared Secret&quot; Code as part of the md5.&#160;&#160; </li>    <li>Flickr's Json response &quot;Content-Type&quot; header is sent not as &quot;application/json&quot; but as &quot;text/plain&quot; which equates to &quot;Raw&quot; in WCF lingo.&#160; </li>    <li>The response object is wrapped and not obvious when it comes to json how the DataContract object should be formed.&#160; </li>    <li>Flickr will wrap the json response in a javascript function unless you pass in the parameter &quot;nojsoncallback=1&quot; </li> </ol>  <p>To get around number one, I created an extension method that takes a Hash (Dictionary&lt;string, object&gt;) and adds method that converts the parameters into a MD5 string. </p>  <pre class="code csharp">namespace Amplify.Linq
 53{
 54	using System;
 55	using System.Collections.Generic;
 56	using System.Linq;
 57	using System.Text;
 58
 59#if STANDALONE
 60	public class Hash : Dictionary&lt;string, object&gt;
 61	{
 62
 63		
 64
 65
 66	}
 67#endif 
 68}
 69// different file
 70	
 71namespace Amplify.Linq
 72{
 73	using System;
 74	using System.Collections.Generic;
 75	using System.Linq;
 76	using System.Security.Cryptography;
 77	using System.Text;
 78
 79	using Amplify.Linq;
 80
 81	public static class Mixins
 82	{
 83
 84	
 85
 86		public static string ToMD5(this Hash obj, string secret)
 87		{
 88			var query = from item in obj
 89						orderby item.Key ascending
 90						select item.Key + item.Value.ToString(); 
 91
 92			StringBuilder builder = new StringBuilder(secret, 2048);
 93
 94			foreach (string item in query)
 95				builder.Append(item);
 96
 97			MD5CryptoServiceProvider crypto = new MD5CryptoServiceProvider();
 98			byte[] bytes = Encoding.UTF8.GetBytes(builder.ToString());
 99			byte[] hashedBytes = crypto.ComputeHash(bytes, 0, bytes.Length);
100			return BitConverter.ToString(hashedBytes).Replace(&quot;-&quot;, &quot;&quot;).ToLower();
101		}
102
103	}
104}</pre>
105
106<p>Well Gotcha number two, took a bit of research to figure it out. The error I got was that it was looking for Json or XML but could not do anything with &quot;Raw&quot;. So the solution is to create a custom binding with a custom WebContentTypeManager. </p>
107
108<pre class="code csharp">namespace Amplify.Flickr
109{
110	using System.ServiceModel;
111	using System.ServiceModel.Channels;
112	using System.Runtime.Serialization;
113	using System.ServiceModel.Web;
114
115	public class JsonContentMapper : WebContentTypeMapper
116	{
117		public override WebContentFormat GetMessageFormatForContentType(string contentType)
118		{
119			return WebContentFormat.Json;
120		}
121	}
122}
123
124// different file
125
126namespace Amplify.Flickr
127{
128	using System;
129	using System.Collections.Generic;
130	using System.Linq;
131	using System.Text;
132	using System.ServiceModel;
133	using System.ServiceModel.Channels;
134	using System.ServiceModel.Description;
135	using System.ServiceModel.Web;
136
137	using Amplify.Linq;
138
139	public class FlickrClient&lt;T&gt; 
140	{
141		protected string Secret { get; set; }
142
143		protected string Key { get; set; }
144
145		protected string Token { get; set; }
146
147		protected string Url { get; set; }
148
149		protected T Proxy { get; set; }
150
151
152		public FlickrClient(string key, string secret)
153		{
154			this.Key = key;
155			this.Secret = secret;
156			this.Url = &quot;http://api.flickr.com/services/rest&quot;;
157			this.Proxy = this.InitializeProxy();
158		}
159
160		public FlickrClient(string key, string secret, string token)
161			:this(key, secret)
162		{
163			this.Token = token;
164		}
165
166		protected virtual T InitializeProxy()
167		{
168			// using custom wrapper
169			CustomBinding binding = new CustomBinding(new WebHttpBinding());
170			WebMessageEncodingBindingElement property =	binding.Elements.Find&lt;WebMessageEncodingBindingElement&gt;();
171			property.ContentTypeMapper = new JsonContentMapper();
172			
173
174			ChannelFactory&lt;T&gt; channel = new ChannelFactory&lt;T&gt;(
175				binding, this.Url);
176
177			channel.Endpoint.Behaviors.Add( new WebHttpBehavior());
178			return channel.CreateChannel();
179		}
180
181	}
182}</pre>
183
184<p>The 3rd issue, to know that all objects are wrapped in a &quot;Response&quot; object. To create a DataContract for the getFrob method on flickr, it took looking at the json to see what it was returning. The object below is the basic form of the Json object that is returned, it also includes the properties in case an error object is returned. </p>
185
186<pre class="code csharp">	using System;
187	using System.Collections.Generic;
188	using System.Linq;
189	using System.Text;
190	using System.Runtime.Serialization;
191
192	[DataContract]
193	public class FrobResponse 
194	{
195		[DataMember(Name = &quot;frob&quot;)]
196		public JsonObject Frob { get; set; }
197
198		[DataContract(Name = &quot;frob&quot;)]
199		public class JsonObject
200		{
201			[DataMember(Name = &quot;_content&quot;)]
202			public string Content { get; set; }
203
204		}
205
206		[DataMember(Name = &quot;stat&quot;)]
207		public string Status { get; set; }
208
209		[DataMember(Name = &quot;code&quot;)]
210		public int Code { get; set; }
211
212		[DataMember(Name = &quot;message&quot;)]
213		public string Message { get; set; }
214	}
215
216	// different file
217
218
219	using System;
220	using System.Collections.Generic;
221	using System.Linq;
222	using System.Text;
223	using System.ServiceModel;
224	using System.ServiceModel.Web;
225
226	[ServiceContract]
227	public interface IAuthClient
228	{
229		[OperationContract,
230			WebInvoke(
231				UriTemplate = &quot;/?method=flickr.auth.getFrob&amp;format=json&amp;nojsoncallback=1&amp;api_key={key}&amp;api_sig={signature}&quot;,
232				ResponseFormat = WebMessageFormat.Json,
233				BodyStyle = WebMessageBodyStyle.Bare)]
234		FrobResponse GetFrob(string signature, string key);
235
236		[OperationContract,
237			WebInvoke(
238				UriTemplate = &quot;/?method=flickr.auth.getToken&amp;format=json&amp;nojsoncallback=1&amp;api_key={key}&amp;frob={frob}&amp;api_sig={signature}&quot;,
239				ResponseFormat = WebMessageFormat.Json,
240				BodyStyle = WebMessageBodyStyle.WrappedResponse)]
241		Auth GetToken(string signature, string key, string frob);
242	}
243
244
245	// the actual client class.  
246
247	using System;
248	using System.Collections.Generic;
249	using System.Linq;
250	using System.Text;
251
252	using Amplify.Linq;
253
254
255	public class AuthClient : FlickrClient&lt;IAuthClient&gt;
256	{
257
258		public AuthClient(string key, string secret)
259			:base(key, secret)
260		{ }
261
262		public AuthClient(string key, string secret, string token)
263			:base(key, secret, token)
264		{ }
265
266		public string GetFrob()
267		{
268			string md5 = new Hash() {
269				{&quot;api_key&quot;, this.Key},
270				{&quot;format&quot;, &quot;json&quot;},
271				{&quot;method&quot;, &quot;flickr.auth.getFrob&quot;},
272				{&quot;nojsoncallback&quot;, 1}
273			}.ToMD5(this.Secret);
274
275			FrobResponse response = this.Proxy.GetFrob(md5, this.Key);
276			if (response.Code &gt; 0)
277				throw new Exception(response.Message);
278
279			return response.Frob.Content;
280		}
281	}</pre>  <p class="blogger-labels">Labels: <a rel='tag' href="http://www.amptools.net/labels/Amplify.aspx">Amplify</a>, <a rel='tag' href="http://www.amptools.net/labels/C#.aspx">C#</a>, <a rel='tag' href="http://www.amptools.net/labels/Code.aspx">Code</a>, <a rel='tag' href="http://www.amptools.net/labels/CSharp.aspx">CSharp</a>, <a rel='tag' href="http://www.amptools.net/labels/Flickr.aspx">Flickr</a>, <a rel='tag' href="http://www.amptools.net/labels/JSON.aspx">JSON</a>, <a rel='tag' href="http://www.amptools.net/labels/REST.aspx">REST</a>, <a rel='tag' href="http://www.amptools.net/labels/WCF.aspx">WCF</a></p>
282			 </div>
283			 <div class="blog-footer">
284				<a class="comment-link" href="http://www.blogger.com/comment.g?blogID=7043853799247804655&postID=8164722880411458481"location.href=http://www.blogger.com/comment.g?blogID=7043853799247804655&postID=8164722880411458481;><span style="text-transform:lowercase">0 Comments</span></a>
285				
286				<a class="comment-link" href="http://www.amptools.net/2008/07/using-wcf-to-access-flickr-json-api.aspx#links"><span style="text-transform:lowercase">Links to this post</span></a>
287				  <span class="item-action"><a href="http://www.blogger.com/email-post.g?blogID=7043853799247804655&postID=8164722880411458481" title="Email Post"><img class="icon-action" alt="" src="http://www.blogger.com:80/img/icon18_email.gif"/></a></span>
288				
289				<script type="text/javascript" src="http://w.sharethis.com/widget/?tabs=web%2Cemail&amp;charset=utf-8&amp;services=reddit%2Cdigg%2Cfacebook%2Cmyspace%2Cdelicious%2Cstumbleupon%2Ctechnorati%2Cpropeller%2Cblinklist%2Cmixx%2Cnewsvine%2Cgoogle_bmarks%2Cyahoo_myweb%2Cwindows_live%2Cfurl&amp;style=rotate&amp;publisher=baa2824f-9291-46c0-87b4-6d5a72508a05&amp;headerbg=%23dddddd&amp;inactivebg=%231bb601&amp;inactivefg=%2370eb00%09&amp;linkfg=%231bb601"></script>
290			</div>
291			
292
293                  
294			<h2 class="blog-title"><a name="1989566401714559482"></a>
295				
296				 Sample Mixins for HttpRequestBase to use with Asp.Net MVC
297				
298				<span class="blog-byline">
299				by: michael herndon, at: 7/16/2008 12:40:00 AM
300				</span>
301				
302			 </h2>
303			 <div class="blog-content">
304				<p>Being a semi avid user of rails for my day job, you tend to miss a couple of things that rails has that is not in Asp.Net's MVC framework. It is a great start and the control over the html (minus laziness of whoever ever developed their &quot;Html.DropDownList&quot; extension method, grrr INDENT YOUR NEW LINES!!), is much greater than what webforms gives you. One of the missing things that I miss is the request.xhr?, request.post?, etc methods that end to be helpful when deciding if this is an AJAX call or an actual action call to return the correct page. </p>  <p>So how do you determine if the request is an ajax request or just a regular page request. What about enforcing that a page is SSL?&#160; What about doing different things depending if the request is a GET or POST?&#160; </p>  <p>So after some googling about headers, rails, and such: here are the first go around of extension methods for HttpRequestBase that should come in handy. </p>  <pre class="code csharp">public static class ControllerMixins
305{
306
307		public static bool IsPost(this HttpRequestBase obj)
308		{
309			return obj.Headers[&quot;REQUEST_METHOD&quot;].ToLower() == &quot;post&quot;;
310		}
311
312		public static bool IsGet(this HttpRequestBase obj)
313		{
314			return obj.Headers[&quot;REQUEST_METHOD&quot;].ToLower() == &quot;get&quot;;
315		}
316
317		public static bool IsXhr(this HttpRequestBase obj)
318		{
319			string value = obj.Headers[&quot;HTTP_X_REQUESTED_WITH&quot;];
320			return (!string.IsNullOrEmpty(value) &amp;&amp; value.ToLower() == &quot;xmlhttprequest&quot;);
321		}
322
323		public static bool IsSSL(this HttpRequestBase obj)
324		{
325			return obj.Headers[&quot;HTTPS&quot;] == &quot;on&quot; ||
326				obj.Headers[&quot;'HTTP_X_FORWARDED_PROTO'&quot;] == &quot;https&quot;;
327		}
328}</pre>  <p class="blogger-labels">Labels: <a rel='tag' href="http://www.amptools.net/labels/Asp.Net.aspx">Asp.Net</a>, <a rel='tag' href="http://www.amptools.net/labels/Asp.Net Mvc.aspx">Asp.Net Mvc</a>, <a rel='tag' href="http://www.amptools.net/labels/C#.aspx">C#</a>, <a rel='tag' href="http://www.amptools.net/labels/Code.aspx">Code</a>, <a rel='tag' href="http://www.amptools.net/labels/CSharp.aspx">CSharp</a>, <a rel='tag' href="http://www.amptools.net/labels/Mixins.aspx">Mixins</a></p>
329			 </div>
330			 <div class="blog-footer">
331				<a class="comment-link" href="http://www.blogger.com/comment.g?blogID=7043853799247804655&postID=1989566401714559482"location.href=http://www.blogger.com/comment.g?blogID=7043853799247804655&postID=1989566401714559482;><span style="text-transform:lowercase">0 Comments</span></a>
332				
333				<a class="comment-link" href="http://www.amptools.net/2008/07/sample-mixins-for-httprequestbase-to.aspx#links"><span style="text-transform:lowercase">Links to this post</span></a>
334				  <span class="item-action"><a href="http://www.blogger.com/email-post.g?blogID=7043853799247804655&postID=1989566401714559482" title="Email Post"><img class="icon-action" alt="" src="http://www.blogger.com:80/img/icon18_email.gif"/></a></span>
335				
336				<script type="text/javascript" src="http://w.sharethis.com/widget/?tabs=web%2Cemail&amp;charset=utf-8&amp;services=reddit%2Cdigg%2Cfacebook%2Cmyspace%2Cdelicious%2Cstumbleupon%2Ctechnorati%2Cpropeller%2Cblinklist%2Cmixx%2Cnewsvine%2Cgoogle_bmarks%2Cyahoo_myweb%2Cwindows_live%2Cfurl&amp;style=rotate&amp;publisher=baa2824f-9291-46c0-87b4-6d5a72508a05&amp;headerbg=%23dddddd&amp;inactivebg=%231bb601&amp;inactivefg=%2370eb00%09&amp;linkfg=%231bb601"></script>
337			</div>
338			
339
340                  
341			<h2 class="blog-title"><a name="3907268195622759157"></a>
342				
343				 Amplify&#39;s TwitterN, Yet Another C# Twitter REST API Library
344				
345				<span class="blog-byline">
346				by: michael herndon, at: 7/13/2008 03:08:00 PM
347				</span>
348				
349			 </h2>
350			 <div class="blog-content">
351				<p><a href="http://code.google.com/p/twittern">http://code.google.com/p/twittern</a></p>  <p>I put together a C# twitter library that uses WCF's <a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.aspx">DataContract</a> &amp; <a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datamemberattribute.aspx">DataMembers</a> and .Net 3.5's <a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.json.datacontractjsonserializer.aspx">DataContractJsonSerializer</a>.&#160; Its currently in alpha stage, as I need to finish writing the tests, documentation and make a simple WPF client for twitter.&#160; I needed a twitter library for a personal &quot;secret&quot; project of mine and found that most twitter libraries do not keep up with the twitter API and break when using them. Plus they tend to go to great lengths when parsing the xml.&#160; Unfortunately I do not know if this will work on mono yet. It seems that they have &quot;<a href="http://www.mono-project.com/WCF">Olive</a>&quot;, which is mono's version of WCF and I've seen where they have a path for the &quot;DataContractJsonSerializer&quot;.&#160; If there are any one familiar enough with mono, please by all means use the code, join the project.&#160; </p>  <p>One design decision that I made was to use Json rather than xml as its more compact and less data to transfer.&#160; I used WCF because with DataContract &amp; DataMembers you can parse Json and you can name your properties the property way with Pascal Case properties and then tell wcf what attributes of json they represent. This way you don't have properties that look like ruby like &quot;screen_name&quot; or&#160; &quot;profile_sidebar_border_color&quot; in your <a href="http://martinfowler.com/eaaCatalog/dataTransferObject.html">Data Transfer Object</a> in order to deserialize the Json response from twitter. </p>  <p>&#160;</p>  <p>A basic sample of how to use the library is below. </p>  <pre class="code csharp">
352
353using Amplify.Twitter;
354using System.Security;
355
356// ... stuff
357
358public void Test() 
359{
360	SecureString password = new SecureString();
361	string temp = "password";
362	for (var i = 0; i &lt; temp.Length; i++)
363		password.AppendChar(temp[i]);
364	
365	password.MakeReadOnly();
366	Twitter.SetCredentials("Username", password);
367
368	StatusService service = Twitter.CreateStatusService();
369 	// or StatusService service = new StatusService("Username", password);
370
371        List&lt;Status&gt; tweets = service.GetUserTimeline("MichaelHerndon");
372}
373
374</pre>  <p class="blogger-labels">Labels: <a rel='tag' href="http://www.amptools.net/labels/Amplify.aspx">Amplify</a>, <a rel='tag' href="http://www.amptools.net/labels/C#.aspx">C#</a>, <a rel='tag' href="http://www.amptools.net/labels/CSharp.aspx">CSharp</a>, <a rel='tag' href="http://www.amptools.net/labels/DataContractJsonSerializer.aspx">DataContractJsonSerializer</a>, <a rel='tag' href="http://www.amptools.net/labels/JSON.aspx">JSON</a>, <a rel='tag' href="http://www.amptools.net/labels/REST.aspx">REST</a>, <a rel='tag' href="http://www.amptools.net/labels/Twitter.aspx">Twitter</a>, <a rel='tag' href="http://www.amptools.net/labels/WCF.aspx">WCF</a></p>
375			 </div>
376			 <div class="blog-footer">
377				<a class="comment-link" href="http://www.blogger.com/comment.g?blogID=7043853799247804655&postID=3907268195622759157"location.href=http://www.blogger.com/comment.g?blogID=7043853799247804655&postID=3907268195622759157;><span style="text-transform:lowercase">3 Comments</span></a>
378				
379				<a class="comment-link" href="http://www.amptools.net/2008/07/amplify-twittern-yet-another-c-twitter.aspx#links"><span style="text-transform:lowercase">Links to this post</span></a>
380				  <span class="item-action"><a href="http://www.blogger.com/email-post.g?blogID=7043853799247804655&postID=3907268195622759157" title="Email Post"><img class="icon-action" alt="" src="http://www.blogger.com:80/img/icon18_email.gif"/></a></span>
381				
382				<script type="text/javascript" src="http://w.sharethis.com/widget/?tabs=web%2Cemail&amp;charset=utf-8&amp;services=reddit%2Cdigg%2Cfacebook%2Cmyspace%2Cdelicious%2Cstumbleupon%2Ctechnorati%2Cpropeller%2Cblinklist%2Cmixx%2Cnewsvine%2Cgoogle_bmarks%2Cyahoo_myweb%2Cwindows_live%2Cfurl&amp;style=rotate&amp;publisher=baa2824f-9291-46c0-87b4-6d5a72508a05&amp;headerbg=%23dddddd&amp;inactivebg=%231bb601&amp;inactivefg=%2370eb00%09&amp;linkfg=%231bb601"></script>
383			</div>
384			
385		</div>
386		<div class="right">
387			<h3>
388				Connect
389			</h3>
390			<ul>
391				<li>
392					<a href="http://www.twitter.com/michaelherndon">
393						<img src="/content/images/twitter-badge.png" alt="Twitter badge" /> 
394					</a>
395				</li>
396				<li>
397					<a href="http://www.facebook.com/profile.php?id=824905532">
398						<img src="/content/images/facebook-badge.png" alt="Facebook badge" /> 
399					</a>
400				</li>
401				<li>
402					<a href="skype:michaelherndon?add">
403						<img src="http://download.skype.com/share/skypebuttons/buttons/add_green_transparent_118x23.png" alt="Add me to Skype" />
404					</a>
405				</li>
406			</ul>
407			
408			<h3>
409				<a href="http://feeds.feedburner.com/amptoolsnet" rel="alternate" type="application/rss+xml">
410					Subscribe in a reader <img src="http://www.feedburner.com/fb/images/pub/feed-icon32x32.png" style="vertical-align:middle" alt="" />
411				</a>
412			</h3>
413			<ul>
414				<li>
415				
416				</li>
417				<li>
418					<a href="http://feeds.feedburner.com/amptoolsnet">
419						<img src="http://feeds.feedburner.com/~fc/amptoolsnet?bg=990066&amp;fg=CCCCCC&amp;anim=0"  alt="" />
420					</a>
421				</li>
422				<li>
423					<a href="http://add.my.yahoo.com/rss?url=http://feeds.feedburner.com/amptoolsnet" title="amptools.net">
424						<img src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif" alt="" />
425					</a>
426				</li>
427				<li>
428					<a href="http://fusion.google.com/add?feedurl=http://feeds.feedburner.com/amptoolsnet">
429						<img src="http://buttons.googlesyndication.com/fusion/add.gif"   alt="Add to Google Reader or Homepage"/>
430					</a>
431				</li>
432				<li>
433					<a href="http://www.pageflakes.com/subscribe.aspx?url=http://feeds.feedburner.com/amptoolsnet" title="Add to Pageflakes">
434						<img src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif" alt="Add to Pageflakes"/>
435					</a>
436				</li>
437				<li>
438					<a href="http://www.bloglines.com/sub/http://feeds.feedburner.com/amptoolsnet" title="amptools.net" type="application/rss+xml">
439						<img src="http://www.bloglines.com/images/sub_modern11.gif" alt="Subscribe in Bloglines" />
440					</a>
441				</li>
442				<li>
443					<a href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http://feeds.feedburner.com/amptoolsnet" title="amptools.net">
444						<img src="http://www.newsgator.com/images/ngsub1.gif" alt="Subscribe in NewsGator Online" />
445					</a>
446				</li>
447			</ul>
448			<h3 class="sidebar-title">
449				Previous Posts
450			</h3>
451			<ul id="recently">
452				
453					<li><a href="http://www.amptools.net/2008/07/using-wcf-to-access-flickr-json-api.aspx">Using WCF to access the Flickr JSON API</a></li>
454				
455					<li><a href="http://www.amptools.net/2008/07/sample-mixins-for-httprequestbase-to.aspx">Sample Mixins for HttpRequestBase to use with Asp....</a></li>
456				
457					<li><a href="http://www.amptools.net/2008/07/amplify-twittern-yet-another-c-twitter.aspx">Amplify&#39;s TwitterN, Yet Another C# Twitter REST AP...</a></li>
458				
459					<li><a href="http://www.amptools.net/2008/07/determining-developmenttesting-mode-in.aspx">Determining Development/Testing Mode in .Net</a></li>
460				
461					<li><a href="http://www.amptools.net/2008/06/pursuit-of-rails-like-active-record-for.aspx">Pursuit of Rails like Active Record for C#</a></li>
462				
463					<li><a href="http://www.amptools.net/2008/04/thoughts-on-developing-linq-to-sql.aspx">Thoughts on Developing a Linq To SQL Layer</a></li>
464				
465					<li><a href="http://www.amptools.net/2008/04/gallio-mb-unit-3-with-bdd-style-tests-i_05.aspx">Gallio &amp; Mb-Unit 3 With BDD style tests, I mean sp...</a></li>
466				
467					<li><a href="http://www.amptools.net/2008/04/test-posting.aspx">Simplicity</a></li>
468				
469			</ul>
470			<h3 class="sidebar-title">
471				Archives
472			</h3>
473			<ul class="archive-list">
474   				
475    				<li><a href="http://www.amptools.net/blogs/michaelherndon/archives/2008_03_30_index.aspx">03.30.2008</a></li>
476				
477    				<li><a href="http://www.amptools.net/blogs/michaelherndon/archives/2008_04_06_index.aspx">04.06.2008</a></li>
478				
479    				<li><a href="http://www.amptools.net/blogs/michaelherndon/archives/2008_06_08_index.aspx">06.08.2008</a></li>
480				
481    				<li><a href="http://www.amptools.net/blogs/michaelherndon/archives/2008_07_06_index.aspx">07.06.2008</a></li>
482				
483    				<li><a href="http://www.amptools.net/blogs/michaelherndon/archives/2008_07_13_index.aspx">07.13.2008</a></li>
484				
485			</ul>
486		</div>
487	
488</asp:Content>