<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>geek#</title>
	
	<link>http://geeksharp.com</link>
	<description>techno-babble for the masses</description>
	<lastBuildDate>Wed, 02 Nov 2011 14:37:42 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/geeksharp" /><feedburner:info uri="geeksharp" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Power Up Your Enumerations</title>
		<link>http://feedproxy.google.com/~r/geeksharp/~3/viNWG0ohf-s/</link>
		<comments>http://geeksharp.com/2011/11/02/power-up-your-enumerations/#comments</comments>
		<pubDate>Wed, 02 Nov 2011 14:29:10 +0000</pubDate>
		<dc:creator>Scott Anderson</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Useful Tricks]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://geeksharp.com/2011/11/02/power-up-your-enumerations/</guid>
		<description><![CDATA[<p>One of the patterns I follow a lot is creating enumerations in my code for certain reference data.&#160; I usually have tables in my SQL database to back up this data, essentially just to give myself the benefit of referential integrity.&#160; But it’s a pain to refer to data based on an arbitrary ID in the database, so enumerations are a way to ensure my code isn’t littered with “magic numbers.”</p>
<p><a href="http://geeksharp.com/2011/11/02/power-up-your-enumerations/" class="more-link">Read more on Power Up Your Enumerations&#8230;</a></p>
]]></description>
			<content:encoded><![CDATA[<p>One of the patterns I follow a lot is creating enumerations in my code for certain reference data.&#160; I usually have tables in my SQL database to back up this data, essentially just to give myself the benefit of referential integrity.&#160; But it’s a pain to refer to data based on an arbitrary ID in the database, so enumerations are a way to ensure my code isn’t littered with “magic numbers.”</p>
<p>Enumerations by themselves are powerful, but pretty plain.&#160; Since 95% of my development work is in ASP.NET MVC these days, I wanted an easy way to render the options an enumeration provides as a drop-down or radio button list.&#160; I could do this manually, and it’s not a lot of code, but I felt like there needed to be an easier, more generic way to handle things.</p>
<p><span id="more-135"></span>
<p>So let’s assume you have input model that looks like this:</p>
<pre class="brush: csharp;">public class VehicleInputModel {
    public int Year { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }
    public VehicleType VehicleType { get; set; }

    public enum VehicleType {
        Car = 1,
        Truck = 2,
        SUV = 3
    }
}</pre>
<p>This is pretty standard stuff.&#160; You’ll have to forgive the contrived example, but it basically works.&#160; I may have two database tables.&#160; One called “Vehicle” and the other called “VehicleType,” and they have a foreign-key relationship between them.&#160; All I’ve done here is make an enumeration that matches my VehicleType table so I can refer to them in code without having to sprinkle ID numbers all over the place.&#160; But what happens when I want to make a form in ASP.NET MVC to create or edit a vehicle?&#160; Some people might reach for the database and grab the data from the reference table to create our drop-down.&#160; I offer an alternative: let’s beef up the enumeration:</p>
<pre class="brush: csharp;">using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

public enum VehicleType {
    [Display(Name=&quot;Car&quot;)]
    Car = 1,

    [Display(Name=&quot;Truck&quot;)]
    Truck = 2,

    [Display(Name=&quot;Sport Utility Vehicle (SUV)&quot;)]
    SUV = 3
}</pre>
<p>Data annotations to the rescue!&#160; You’re already using them all over the place in ASP.NET MVC because of the validation system (at least I hope you are).&#160; Why not put them to work for our enumerations, too?&#160; In this case, I’ve attached some arbitrary metadata to my enumeration that will make displaying data a bit easier.</p>
<p>First, let’s create a generic helper method that will read data from these attributes.&#160; I like to use an extension method for this, and I extend the <strong>System.Enum</strong> class:</p>
<pre class="brush: csharp;">public static string GetAttributeValue&lt;T&gt;(this Enum e,
    Func&lt;T, object&gt; selector) where T : Attribute {

    var output = e.ToString();
    var member = e.GetType().GetMember(output).First();
    var attributes = member.GetCustomAttributes(typeof (T), false);

    if (attributes.Length &gt; 0) {
        var firstAttr = (T)attributes[0];
        var str = selector(firstAttr).ToString();
        output = string.IsNullOrWhiteSpace(str) ? output : str;
    }

    return output;
}</pre>
<p>This helper is fairly straightforward.&#160; All I’m doing is finding the custom attributes on the enumeration and then using a simple function to grab any value I want.&#160; If there are no attributes defined, then I just return the default <strong>ToString()</strong> value.</p>
<p>Because the <strong>Html.DropDownListFor()</strong> method takes an <strong>IEnumerable&lt;SelectListItem&gt;</strong>, I’ve written another handy method that converts an enumeration into that type:</p>
<pre class="brush: csharp;">public static IEnumerable&lt;SelectListItem&gt; ConvertToSelectList&lt;T&gt;(int? selectedItem = null) {
    return Enum.GetValues(typeof (T)).Cast&lt;T&gt;().Select(x =&gt; new SelectListItem {
        Text = (x as Enum).GetAttributeValue&lt;DisplayAttribute&gt;(y =&gt; y.Name),
        Value = Convert.ToInt32(x).ToString(),
        Selected = selectedItem.HasValue ? selectedItem == Convert.ToInt32(x) : false
    });
}</pre>
<p>This method grabs all the values in an enumeration, then uses the extension method above to read the <strong>Name</strong> property from the <strong>DisplayAttribute</strong> on each value.&#160; If there is no <strong>DisplayAttribute</strong> present, then a simple <strong>ToString()</strong> is called on each value.&#160; It also takes an optional <strong>selectedItem</strong> argument that can be used to determine which item in the list should be selected.&#160; This leaves me with a collection of <strong>SelectListItem</strong> objects where the <strong>Text</strong> property on each object is determined by the <strong>DisplayAttribute</strong>.&#160; Pretty sweet, huh?&#160; Now I can extend my <strong>VehicleInputModel</strong> like so:</p>
<pre class="brush: csharp;">public class VehicleInputModel {
    public int Year { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }
    public VehicleType VehicleType { get; set; }
    public IEnumerable&lt;SelectListItem&gt; VehicleTypeSelection { get; set; }

    public VehicleInputModel() {
        VehicleTypeSelection = EnumExtensions.ConvertToSelectList&lt;VehicleType&gt;();
    }

    public enum VehicleType {
        Car = 1,
        Truck = 2,
        SUV = 3
    }
}</pre>
<p>And finally, I can render this drop-down list in my view like so:</p>
<pre class="brush: csharp;">@Html.DropDownListFor(m =&gt; m.VehicleType, Model.VehicleTypeSelection)</pre>
<p>I hope you can see how a couple easy, generic methods and the built-in data annotations can make your enumerations a lot beefier.&#160; This can save you some time and database hits in the long run.&#160; I’m not suggesting that you use enumerations for every single reference table in your project, and I know this example is a bit contrived.&#160; My goal is simply to illustrate the power of a few well-placed attributes and a handy method in certain situations that can clean up your controllers and views a bit.&#160; Cheers!</p>
<img src="http://feeds.feedburner.com/~r/geeksharp/~4/viNWG0ohf-s" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://geeksharp.com/2011/11/02/power-up-your-enumerations/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://geeksharp.com/2011/11/02/power-up-your-enumerations/</feedburner:origLink></item>
		<item>
		<title>St. Louis Day of .NET, aka SPAM Central</title>
		<link>http://feedproxy.google.com/~r/geeksharp/~3/lxDS5f2UEo8/</link>
		<comments>http://geeksharp.com/2011/08/30/st-louis-day-of-net-aka-spam-central/#comments</comments>
		<pubDate>Tue, 30 Aug 2011 14:19:13 +0000</pubDate>
		<dc:creator>Scott Anderson</dc:creator>
				<category><![CDATA[Geek Rage]]></category>
		<category><![CDATA[.NET]]></category>

		<guid isPermaLink="false">http://geeksharp.com/2011/08/30/st-louis-day-of-net-aka-spam-central/</guid>
		<description><![CDATA[<p>So this year was the second year, now, that I’ve attended the St. Louis Day of .NET conference.&#160; Last year was fairly decent.&#160; There were a few good talks, but you can’t expect perfection from a small, regional conference that doesn’t have the draw or influence of something larger (like MIX or PDC).&#160; Fair enough.&#160; This year, however, will be the last time I attend this conference, and it all boils down to this:</p>
<p><a href="http://geeksharp.com/2011/08/30/st-louis-day-of-net-aka-spam-central/" class="more-link">Read more on St. Louis Day of .NET, aka SPAM Central&#8230;</a></p>
]]></description>
			<content:encoded><![CDATA[<p>So this year was the second year, now, that I’ve attended the St. Louis Day of .NET conference.&#160; Last year was fairly decent.&#160; There were a few good talks, but you can’t expect perfection from a small, regional conference that doesn’t have the draw or influence of something larger (like MIX or PDC).&#160; Fair enough.&#160; This year, however, will be the last time I attend this conference, and it all boils down to this:</p>
<h2>SPAM Sucks</h2>
<p><a href="http://geeksharp.com/wp-content/uploads/2011/08/image.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://geeksharp.com/wp-content/uploads/2011/08/image_thumb.png" width="608" height="460" /></a></p>
<p>Apparently it’s my fault.&#160; Apparently I didn’t read some fine print somewhere that says that the STLDODN organizers were going to give my email address to every vendor that sponsored this event so they could flood my inbox with sales pitches and bullshit.&#160; Never mind the fact that this year’s conference was even more mediocre than last year’s.&#160; Never mind the fact that the keynote was on Visual Studio LightSwitch – a product that Microsoft is pushing on business users to somehow make my job obsolete.&#160; Never mind the fact that some of my co-workers are junior level and/or interns, and they couldn’t get into the jumpstart classes because they decided to put them in undersized rooms.&#160; Never mind the fact that advanced content is glaringly absent.</p>
<p>There is a lot wrong with this conference, but the biggest problem of all is that now my <strong>work email address</strong> is being spammed by the conference vendors and sponsors.&#160; What the hell?&#160; I thought you guys had more integrity.&#160; I thought—of all people—my fellow programmers would hate spam <strong>at least</strong> as much as I do.&#160; I guess I assumed too much.&#160; Goodbye St. Louis Day of .NET, and good riddance.&#160; I will <strong>not</strong> be back next year.</p>
<img src="http://feeds.feedburner.com/~r/geeksharp/~4/lxDS5f2UEo8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://geeksharp.com/2011/08/30/st-louis-day-of-net-aka-spam-central/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://geeksharp.com/2011/08/30/st-louis-day-of-net-aka-spam-central/</feedburner:origLink></item>
		<item>
		<title>ActionMailer 0.6 Released</title>
		<link>http://feedproxy.google.com/~r/geeksharp/~3/99hQ_Aslsnk/</link>
		<comments>http://geeksharp.com/2011/07/06/actionmailer-0-6-released/#comments</comments>
		<pubDate>Wed, 06 Jul 2011 14:41:10 +0000</pubDate>
		<dc:creator>Scott Anderson</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[ActionMailer.Net]]></category>
		<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://geeksharp.com/2011/07/06/actionmailer-0-6-released/</guid>
		<description><![CDATA[<p>Well it’s been a few months since the last release, and I decided it was time to get cracking.&#160; I’m sorry for the delay, but I hope you’ll agree that it was worth the wait.&#160; So without further adieu, let’s&#160; go over the new stuff!</p>
<p><a href="http://geeksharp.com/2011/07/06/actionmailer-0-6-released/" class="more-link">Read more on ActionMailer 0.6 Released&#8230;</a></p>
]]></description>
			<content:encoded><![CDATA[<p>Well it’s been a few months since the last release, and I decided it was time to get cracking.&#160; I’m sorry for the delay, but I hope you’ll agree that it was worth the wait.&#160; So without further adieu, let’s&#160; go over the new stuff!</p>
<h2>Separating Components</h2>
<p>So one of the things a lot of people have been asking for is a version of ActionMailer.Net that works without a dependency on ASP.NET MVC.&#160; It took me a while to come up with a strategy for doing this, but I think I’ve covered all the bases.&#160; That said, I had to move things around.&#160; So here’s how the project is laid out now:</p>
<ul>
<li><strong>ActionMailer.Net</strong> – This project contains generic code that can be applied to either the MVC or Standalone versions of ActionMailer.Net.&#160; This DLL is referenced by the other two projects as sort of a “Core” set of functionality. </li>
<li><strong>ActionMailer.Net.Mvc</strong> (Nuget:&#160; <a href="http://nuget.org/List/Packages/ActionMailer">ActionMailer</a>)<strong> </strong>– All the MVC-specific stuff has been moved into this project.&#160; This means that MailerBase, EmailResult, and all the Html/Url helpers live in this project.&#160; In most cases, all you’ll have to do is change your “using” statement to this new namespace, and your existing code should work just like it has been. </li>
<li><strong>ActionMailer.Net.Standalone</strong> (Nuget:&#160; <a href="http://nuget.org/List/Packages/ActionMailer.Standalone">ActionMailer.Standalone</a>) – This project contains a standalone version of the ActionMailer.Net email rendering engine.&#160; Right now we only support Razor views through two new classes:&#160; RazorMailerBase and RazorEmailResult.&#160; I’ve decided to use the <a href="http://razorengine.codeplex.com/">RazorEngine</a> project to power this system.&#160; This engine supports models in the same way MVC does, but some other features (i.e.: layouts) have not been implemented, yet.&#160; This support is still pretty basic, but it should be enough to do most things fairly well. </li>
</ul>
<p><span id="more-129"></span><br />
<h2>Installation</h2>
<p>As I’ve linked above, there are now two <a href="http://nuget.org/">Nuget</a> packages for ActionMailer.Net.&#160; There are also <a href="https://bitbucket.org/swaj/actionmailer.net/downloads">two downloadable ZIP files</a> on the <a href="https://bitbucket.org/swaj/actionmailer.net/wiki/Home">Bitbucket project page</a>.&#160; I recommend the Nuget packages because it’s just so easy, and it will take care of any dependencies for you.&#160; However, I do keep the ZIP files updated, so feel free to use them as well.</p>
<h2>Standalone:&#160; How Does it Work?</h2>
<p>The good news is that I’ve tried to keep the standalone usage very similar to the MVC version.&#160; All you really need to do is inherit from RazorMailerBase and return RazorEmailResults, just like you do with MVC.&#160; I’m sure code is more helpful, so step 1 is to create your mailer:</p>
<pre class="brush: csharp;">public class Mailer : RazorMailerBase {
    public override string ViewPath {
        get { return &quot;Templates&quot;; }
    }

    public RazorEmailResult Verification(User model) {
        To.Add(model.EmailAddress);
        From = &quot;foo@bar.com&quot;;
        Subject = &quot;Account Verification&quot;;
        return Email(&quot;Verification&quot;, model);
    }
}</pre>
<p>You should notice that RazorMailerBase is an abstract class with only one property that you must implement, and that’s the ViewPath.&#160; This tells ActionMailer.Net where you have stored your views.&#160; In this case, I’ve chosen a folder called “Templates.”&#160; You can see my first email configured in the Verification method.&#160; Now I need to create a view in the folder configured as the ViewPath:</p>
<pre class="brush: plain;">Hello @Model.Name,

This is a sample email.</pre>
<p>You&#8217;ll notice that I did not specify a <strong>@model</strong> line in the Razor view.&#160; This is because the Razor engine does not need it.&#160; The Model object will exist, however, if you pass it to the Email method just as we did above.&#160; This is all you need to make a view.&#160; There’s one other important thing to note, however:&#160; When you make a view, it needs to end in <strong>.txt.cshtml</strong> or <strong>.html.cshtml</strong> depending on the format.&#160; The standalone version of ActionMailer.Net supports multipart messaging just like the MVC version, so we have to specify the format we wish to use.&#160; In the example above, the view should have been named:&#160; <strong>Verification.txt.cshtml</strong>.</p>
<p>The final step is to call your new Mailer class anywhere in your application like so:</p>
<pre class="brush: csharp;">var user = FindUserByID(123);
new Mailer().Verification(user).DeliverAsync();</pre>
<p>As you can see, the RazorEmailResult has delivery methods defined.&#160; Here I’m using <strong>DeliverAsync</strong> to send the email, but there is also a <strong>Deliver</strong> method if you’d like the call to happen synchronously.</p>
<h2></h2>
<h2>Wrapping it Up</h2>
<p>I hope you can see that using the standalone version of ActionMailer.Net is just as easy as the MVC version.&#160; I’ve tried to keep things as simple as possible.&#160; Keep in mind that RazorEngine is not as full-featured as the MVC razor engine, so more advanced features like partials, HTML helpers, and layouts just don’t work.&#160; However, I still believe that the basic support that is enough for most use cases.&#160; I have plans to expand the default standalone template in the future to give some email-friendly HTML helpers, just like we have in the MVC version.&#160; Please test this out and let me know what you think.&#160; It needs more features, for sure, but this is a good start, I think.&#160; Cheers!</p>
<img src="http://feeds.feedburner.com/~r/geeksharp/~4/99hQ_Aslsnk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://geeksharp.com/2011/07/06/actionmailer-0-6-released/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		<feedburner:origLink>http://geeksharp.com/2011/07/06/actionmailer-0-6-released/</feedburner:origLink></item>
		<item>
		<title>Intro to ActionMailer.Net (Screencast)</title>
		<link>http://feedproxy.google.com/~r/geeksharp/~3/9hegByVCIt4/</link>
		<comments>http://geeksharp.com/2011/02/11/intro-to-actionmailer-net-screencast/#comments</comments>
		<pubDate>Fri, 11 Feb 2011 18:02:08 +0000</pubDate>
		<dc:creator>Scott Anderson</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[ActionMailer.Net]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[MVC]]></category>

		<guid isPermaLink="false">http://geeksharp.com/2011/02/11/intro-to-actionmailer-net-screencast/</guid>
		<description><![CDATA[<p>One of the ways I like to learn is by watching screencasts.&#160; I find that it’s easier for me to retain information.&#160; I suppose I’m just a more “visual” learner.&#160; In light of this, I’ve decided to record a short screencast introducing some of the basic features of ActionMailer.Net.</p>
<p><a href="http://geeksharp.com/2011/02/11/intro-to-actionmailer-net-screencast/" class="more-link">Read more on Intro to ActionMailer.Net (Screencast)&#8230;</a></p>
]]></description>
			<content:encoded><![CDATA[<p>One of the ways I like to learn is by watching screencasts.&#160; I find that it’s easier for me to retain information.&#160; I suppose I’m just a more “visual” learner.&#160; In light of this, I’ve decided to record a short screencast introducing some of the basic features of ActionMailer.Net.</p>
<p>I’ve recently released a new version (0.4.1) of this library which adds support for true multi-part messaging and a whole bunch of URL and HTML helpers that you can use in your views.&#160; ActionMailer.Net also has a pretty thorough set of unit tests, so feel free to hack around and let me know what you think!&#160; </p>
<h1>The Video</h1>
<p><iframe title="YouTube video player" height="510" src="http://www.youtube.com/embed/QQRzYo7k9Vs?hd=1" frameborder="0" width="640" allowfullscreen="allowfullscreen"></iframe></p>
<p>I’d love to make some more of these covering some of the more advanced features in ActionMailer.Net.&#160; Any feedback is welcome and appreciated!</p>
<p>Cheers!</p>
<p><strong>P.S.</strong> – For those of you that would rather watch the uncompressed video or can’t access YouTube at work, feel free to <a href="http://geeksharp.com/media/actionmailer-intro.7z">grab the video here</a> (you’ll need <a href="http://www.7-zip.org/">7-zip</a> to decompress it).</p>
<img src="http://feeds.feedburner.com/~r/geeksharp/~4/9hegByVCIt4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://geeksharp.com/2011/02/11/intro-to-actionmailer-net-screencast/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://geeksharp.com/2011/02/11/intro-to-actionmailer-net-screencast/</feedburner:origLink></item>
		<item>
		<title>ActionMailer.Net: Email Templates for the MVC Crowd</title>
		<link>http://feedproxy.google.com/~r/geeksharp/~3/yZeTu8jzq6U/</link>
		<comments>http://geeksharp.com/2011/01/26/actionmailer-net-email-templates-for-the-mvc-crowd/#comments</comments>
		<pubDate>Wed, 26 Jan 2011 20:10:05 +0000</pubDate>
		<dc:creator>Scott Anderson</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[ActionMailer.Net]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[MVC]]></category>

		<guid isPermaLink="false">http://geeksharp.com/2011/01/26/actionmailer-net-email-templates-for-the-mvc-crowd/</guid>
		<description><![CDATA[<p>Over the past few days I’ve been working on an application here at work that will be sending emails pretty heavily.  Up until now, my usual plan was to just write a couple of helper methods that I could call.  These helper methods would undoubtedly use <em>StringBuilder</em> to do most of the grunt work, happily formatting my emails.  The problem with this approach, however, should be obvious.  There are tons of templates hard coded in C# with string literals all over the place… YUCK!</p>
<p><a href="http://geeksharp.com/2011/01/26/actionmailer-net-email-templates-for-the-mvc-crowd/" class="more-link">Read more on ActionMailer.Net: Email Templates for the MVC Crowd&#8230;</a></p>
]]></description>
			<content:encoded><![CDATA[<p>Over the past few days I’ve been working on an application here at work that will be sending emails pretty heavily.  Up until now, my usual plan was to just write a couple of helper methods that I could call.  These helper methods would undoubtedly use <em>StringBuilder</em> to do most of the grunt work, happily formatting my emails.  The problem with this approach, however, should be obvious.  There are tons of templates hard coded in C# with string literals all over the place… YUCK!</p>
<p>So I took a step back.  I realized that the Rails framework really has this nailed.  Through the awesome <em>ActionMailer</em> library within Rails, you can use the built-in template engines to generate emails almost exactly like you would generate a view.  This leads to very small helper methods, and it’s just so darn clean.  I think the MVC community could use a cool library like this, so I decided to write one.</p>
<p><span id="more-60"></span></p>
<h2>Introducing ActionMailer.Net for MVC 3</h2>
<p>First off, the code is completely open source.  My boss was cool enough to let me share this with the community, so I’ve chosen the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a> as it seems most fitting.  The code is <a href="https://bitbucket.org/swaj/actionmailer.net">up on bitbucket</a> right now, so feel free to download it and tinker with it to your heart’s content.  This is still very alpha, so I’ll warn you that it might have a few bugs.  I’ve tried to be diligent with my unit tests, but I’m sure I’ve missed a few things.</p>
<p>The error handling could use some work, and I also need to add support for multi-part messages and attachments.  I also want to throw this thing up on NuGet soon to make it easier to download. These features are in the works, but patches and pull requests are most certainly welcome!</p>
<h2>Cool, Now Show Me the Code!</h2>
<p>So once you’ve downloaded and referenced the <em>ActionMailer.Net.dll</em> within your project, using it is pretty easy.  First, you need to add a new controller.  For this example, mine will be called <em>MailController</em>.  This new controller should inherit from <em>ActionMailer.Net.MailerBase</em>:</p>
<pre class="brush: csharp;">public class MailController : MailerBase
{
    public EmailResult VerificationEmail(User model)
    {
        To.Add(model.EmailAddress);
        From = "no-reply@mycoolsite.com";
        Subject = "MyCoolSite Account Verification";
        return Email(model);
    }
}</pre>
<p>Notice that we’re returning a special type from the action defined above.  This type <em>EmailResult</em> is provided by ActionMailer.Net.  We’re also using a special helper method called <em>Email()</em> instead of the normal <em>View()</em> method you’re probably used to.</p>
<p>The next step is to create a view that matches this action.  I’ve only tested the Razor view engine, but the library should be view engine agnostic, meaning that you could just as easily use the Web Forms view engine, or even Spark, or NHaml as long as they are registered as proper view engines within your application.  To correspond with the sample method above, the view for this action should live in <em>~/Views/Mail/VerificationEmail.cshtml</em>:</p>
<pre class="brush: plain;">@model User

@{
    Layout = null;
}

Welcome to My Cool Site, @User.FirstName

We need you to verify your email.  Click this nifty link to get verified!

@Url.Action("Verify", "Account", new { code = @User.EmailActivationToken.ToString() })

Thanks!</pre>
<p>Right now the links are generated with a relative URL.  I’m working on a couple of helpers to fix that for you, but just be aware of it at the moment.  The final step is to actually call this action from somewhere else, and that’s the easiest part.  Let’s say you’ve got a registration action and you want to send out email verification.  All it takes is one line of code:</p>
<p>&nbsp;</p>
<pre class="brush: csharp;">new MailController().VerificationEmail(newUser).Deliver();</pre>
<p>That’s it!  I’ve tried to make the library as fluid as possible to save you some headaches, but I could definitely use some input from you guys.</p>
<h2>Configuration</h2>
<p>There is a little bit of configuration that needs to be done, but it’s pretty easy.  Under the hood, ActionMailer.Net is using the default <em>System.Net.Mail.SmtpClient</em> to send all your messages.  This means that you need to add some configuration options in your project’s <em>Web.config</em> file.  While I’m in development, I like to send all emails to a local folder on my hard drive:</p>
<pre class="brush: xml;">&lt;system.net&gt;
  &lt;mailSettings&gt;
    &lt;smtp deliveryMethod="SpecifiedPickupDirectory"&gt;
      &lt;specifiedPickupDirectory pickupDirectoryLocation="C:\temp\"/&gt;
    &lt;/smtp&gt;
  &lt;/mailSettings&gt;
&lt;/system.net&gt;</pre>
<p>But later, when you move to production, you’ll need some more appropriate settings:</p>
<pre class="brush: xml;">&lt;system.net&gt;
  &lt;mailSettings&gt;
    &lt;smtp deliveryMethod="Network"&gt;
      &lt;network host="smtp.mysite.com" userName="myuser" password="mypassword" /&gt;
    &lt;/smtp&gt;
  &lt;/mailSettings&gt;
&lt;/system.net&gt;</pre>
<h2>What Else Does it Do?</h2>
<p>I’ve tried to make this library as extensible as possible through interfaces.  If you would rather using something like Amazon SES to send your messages, all you need to do is implement the <em>IMailSender</em> interface, and then override the default MailSender with your own like this:</p>
<pre class="brush: csharp;">public MailController() {
    MailSender = new MyCustomSender();
}</pre>
<p>Another feature is the ability to override a couple of methods on the <em>MailerBase</em> class within your controller to inspect mail messages before and after they are sent.  You can even cancel certain messages from going out:</p>
<p>&nbsp;</p>
<pre class="brush: csharp;">protected override void OnMailSending(MailSendingContext context) {
    // here I could set context.Cancel to stop the message
    // or I could see the message as context.Mail
}

protected override void OnMailSent(MailMessage mail) {
    // the mail message that was sent is passed in for you
}</pre>
<h2>Wrapping Up</h2>
<p>So that’s it for now.  I’ve got a lot of plans for this library.  I’d like to make it just as full-featured as its Rails counterpart.  I could also use some testing and even contributions from the community.  Sending email sucks, so let’s make it easier on each other, right?  Cheers!</p>
<img src="http://feeds.feedburner.com/~r/geeksharp/~4/yZeTu8jzq6U" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://geeksharp.com/2011/01/26/actionmailer-net-email-templates-for-the-mvc-crowd/feed/</wfw:commentRss>
		<slash:comments>36</slash:comments>
		<feedburner:origLink>http://geeksharp.com/2011/01/26/actionmailer-net-email-templates-for-the-mvc-crowd/</feedburner:origLink></item>
		<item>
		<title>Oh Noes! There Goes My Blog!</title>
		<link>http://feedproxy.google.com/~r/geeksharp/~3/b-eH7br8nBw/</link>
		<comments>http://geeksharp.com/2011/01/14/oh-noes-there-goes-my-blog/#comments</comments>
		<pubDate>Fri, 14 Jan 2011 22:23:15 +0000</pubDate>
		<dc:creator>Scott Anderson</dc:creator>
				<category><![CDATA[Sad Pandas]]></category>

		<guid isPermaLink="false">http://geeksharp.com/?p=51</guid>
		<description><![CDATA[<p>So in case you are wondering&#8230; recently I was moving my database around, and in the midst of things I managed to completely blow up my WordPress database.  I thought to myself: &#8220;No matter!  I have backups!&#8221;  Little did I know that I had actually forgotten to set up the cron job to copy the backups to AWS S3 (my backup solution du &#8216;jour).</p>
<p><a href="http://geeksharp.com/2011/01/14/oh-noes-there-goes-my-blog/" class="more-link">Read more on Oh Noes! There Goes My Blog!&#8230;</a></p>
]]></description>
			<content:encoded><![CDATA[<p>So in case you are wondering&#8230; recently I was moving my database around, and in the midst of things I managed to completely blow up my WordPress database.  I thought to myself: &#8220;No matter!  I have backups!&#8221;  Little did I know that I had actually forgotten to set up the cron job to copy the backups to AWS S3 (my backup solution du &#8216;jour).</p>
<p>Long story short, I had to scrape my content out of Google cache to get this blog back in action.  One lovely side effect, however, is that all my post comments were blasted to smithereens.  I do apologize for those of you that were thoughtful enough to lend me your words.  I&#8217;ve learned the hard way to always confirm your backup strategy.  I hereby join the ranks of <a href="http://haacked.com/archive/2009/12/14/back-in-business-again.aspx">Phil Haack</a> and <a href="http://www.codinghorror.com/blog/2009/12/international-backup-awareness-day.html">Jeff Atwood</a> (*facepalm*).</p>
<img src="http://feeds.feedburner.com/~r/geeksharp/~4/b-eH7br8nBw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://geeksharp.com/2011/01/14/oh-noes-there-goes-my-blog/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://geeksharp.com/2011/01/14/oh-noes-there-goes-my-blog/</feedburner:origLink></item>
		<item>
		<title>The Great Host Swap</title>
		<link>http://feedproxy.google.com/~r/geeksharp/~3/qthnkoNKeGI/</link>
		<comments>http://geeksharp.com/2010/12/17/the-great-host-swap/#comments</comments>
		<pubDate>Fri, 17 Dec 2010 18:32:11 +0000</pubDate>
		<dc:creator>Scott Anderson</dc:creator>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Geek Rage]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://geeksharp.com/?p=42</guid>
		<description><![CDATA[<p>It’s funny how things work out.&#160; If you’re reading this, you’re on my new server.&#160; The great host swap of 2010 is complete.&#160; God it was a pain, but, sadly, it was necessary.&#160; Things have been solid for a long time here, but I guess everyone has their bad days.&#160; My old host just had a few too many for me to deal with.</p>
<p><a href="http://geeksharp.com/2010/12/17/the-great-host-swap/" class="more-link">Read more on The Great Host Swap&#8230;</a></p>
]]></description>
			<content:encoded><![CDATA[<p>It’s funny how things work out.&#160; If you’re reading this, you’re on my new server.&#160; The great host swap of 2010 is complete.&#160; God it was a pain, but, sadly, it was necessary.&#160; Things have been solid for a long time here, but I guess everyone has their bad days.&#160; My old host just had a few too many for me to deal with.</p>
<p>My former host was <a href="http://www.linode.com">Linode</a>.&#160; For the most part, things were incredibly stable.&#160; Barring recent events, I never had any major issues that weren’t somehow my fault.&#160; I signed up with them in June of 2009 because I noticed their packages offered more bang for the buck than <a href="http://www.slicehost.com">Slicehost</a> (my first host for this blog).&#160; They had a lot of positive reviews, and their control panel software was pretty sweet.&#160; My geek side fell in love with Linode, and I was a happy customer for a long time.&#160; Recently, though… things haven’t been so great.</p>
<p><span id="more-42"></span></p>
<h2>Hurricane Electric?&#160; Woohoo!</h2>
<p>One of the great benefits of Linode is that they have multiple data centers.&#160; You can pick between five of them at the time of this writing.&#160; One of my key concerns was IPv6 connectivity (which Linode does not yet provide natively), and I knew that Hurricane Electric’s Tunnel Broker service had a POP in Fremont.&#160; I was pleasantly surprised to find out that Linode actually co-located within Hurricane Electric’s Fremont facility, so the latency over my IPv6 tunnel was extremely low.&#160; I mean the times were sub-millisecond.&#160; Color me happy.</p>
<h2>Hurricane Electric’s Lack of Redundancy</h2>
<p>At first I was amazingly happy with my service.&#160; Again, it was a year and a half of pretty solid performance.&#160; I’d have a couple blips here and there in my network connectivity, but Linode was always on top of things and had issues resolved usually within a few minutes.&#160; The problems started, however, toward the end of last month.&#160; The Fremont facility suffered some major issues.&#160; You can see more about them on <a href="http://status.linode.com/2010/11/fremont-power-issues-rfo.html">Linode’s status page</a>, but suffice it to say that I was a bit upset after these <strong>two</strong> incidents within days of each other.</p>
<p>What Hurricane Electric decided to leave out of the RFO was the fact that customer equipment was damaged due to their faulty systems.&#160; What they describe as a 3-second power issue (the first outage) actually destroyed customer equipment.&#160; Thank god Linode was prepared for this.&#160; My VPS was down for hours, but Linode had hot standby systems in place.&#160; I hate to think how long I’d have been down if Linode wasn’t as prepared.&#160; I really don’t understand how a top-tier ISP like Hurricane Electric can suffer so much damage and downtime because of a simple lightning storm.&#160; To me, this is complete and total failure on their part.&#160; I didn’t blame Linode at all.</p>
<p>Next comes downtime number two within 3 days of the previous one.&#160; They had another “incident” which caused a 1-second power failure due to the fact that they were still running on their N + 1 redundant UPS which failed.&#160; Again, Linode was quick to respond.&#160; Tell me something Hurricane Electric… if the power was only interrupted for 1 second, why did you not enhance the degraded UPS?&#160; I understand you were waiting for parts, but you should have been better prepared in the meantime.&#160; Again, I can’t fathom how a company of your position and stature could be in this situation.</p>
<h2>Sticking It Out</h2>
<p>So to be completely fair, the first two downtimes weren’t Linode’s fault.&#160; I realize that.&#160; I completely blame the incompetence of Hurricane Electric for those issues.&#160; After those two incidents, I decided to stick it out with Linode.&#160; Let’s face it:&#160; migrating servers is a pain in the ass, and I really didn’t want to do it.&#160; Not only that, but I felt like it wasn’t fair to blame Linode for something that was completely out of their control.</p>
<p>So stick it out, I did.&#160; I was obviously very angry at this point, but I convinced myself that 1.5 years of solid service was enough to offset a few hours of downtime that wasn’t their fault.&#160; But then the third issue happened, and this time, it was Linode’s fault.&#160; This was the straw that broke the camel’s back.</p>
<p>Linode <a href="http://status.linode.com/2010/12/scheduled-network-maintenance-in-fremont-december-12-2010.html">posted</a> about some network maintenance they needed to perform on December 12.&#160; I figured this wouldn’t be a big deal.&#160; Any decent ISP has redundancy built in at every point possible, so even if they were replacing several core switches, there shouldn’t have been any need for downtime.&#160; There was, however, substantial downtime.&#160; I couldn’t take it anymore.&#160; Between Hurricane Electric and Linode, it seemed like my server was doomed.&#160; I decided to make a move.</p>
<h2>Rackspace Cloud</h2>
<p>So here we are, rolling on the <a href="http://www.rackspacecloud.com/">Rackspace Cloud</a>.&#160; I must say that I’ve been very impressed so far.&#160; It hasn’t all been candy and roses, though.&#160; I did have an issue with the webserver that is hosting this site right now.&#160; It was very unresponsive and slow.&#160; Here’s the difference though:&#160; Rackspace support is amazing.&#160; I clicked the little “Live Chat” button in my dashboard, and instantly I was connected with a fellow named Ethan.&#160; Ethan stuck with me while we tried a few things, and then eventually he decided that it would be a good idea to move my server to another host.&#160; Once my server was moved, the problems went away, and everything just worked.&#160; Rackspace support is stellar, and I can’t recommend them highly enough.</p>
<h2>Wrapping It Up (TLDR)</h2>
<p>I couldn’t take the downtime with Linode.&#160; I know Rackspace Cloud is just rebranded Slicehost, but that’s fine with me.&#160; Rackspace support is stellar, and I don’t mind paying just a few extra dollars per month to have a company like Rackspace behind me.&#160; I’m looking at launching my small startup venture soon, and I need reliability from my host.&#160; Thanks for all the fish, Linode.&#160; It was good while it lasted, but I’m a happy Rackspace customer now.&#160; Woot!</p>
<img src="http://feeds.feedburner.com/~r/geeksharp/~4/qthnkoNKeGI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://geeksharp.com/2010/12/17/the-great-host-swap/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://geeksharp.com/2010/12/17/the-great-host-swap/</feedburner:origLink></item>
		<item>
		<title>Implementing ISession in EF4</title>
		<link>http://feedproxy.google.com/~r/geeksharp/~3/IPrr0K182J8/</link>
		<comments>http://geeksharp.com/2010/11/16/implementing-isession-in-ef4/#comments</comments>
		<pubDate>Tue, 16 Nov 2010 18:20:18 +0000</pubDate>
		<dc:creator>Scott Anderson</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[EF4]]></category>

		<guid isPermaLink="false">http://geeksharp.com/?p=19</guid>
		<description><![CDATA[<p>In a previous post regarding the ISession from Rob Conery, a commenter asked about our implementation of ISession with regards to EF4.&#160; Rather than send him the specific code, I figured I’d make another blog post to outline exactly how we use it here at work.</p>
<p><a href="http://geeksharp.com/2010/11/16/implementing-isession-in-ef4/" class="more-link">Read more on Implementing ISession in EF4&#8230;</a></p>
]]></description>
			<content:encoded><![CDATA[<p>In a previous post regarding the ISession from Rob Conery, a commenter asked about our implementation of ISession with regards to EF4.&#160; Rather than send him the specific code, I figured I’d make another blog post to outline exactly how we use it here at work.</p>
<p>Basically, each of our projects has a “Data” layer where we store everything needed to communicate with the database.&#160; This is also where the ISession interface lives, so it’s easy to provide the implementation.&#160; There is one caveat, however, because we need to provide a generic EF4 implementation that can work with any data context.&#160; In our projects, sometimes we need to speak with multiple databases, and then it becomes just a matter of plugging the right entity collection into our implementation.&#160; Here’s what the code looks like:</p>
<p><span id="more-19"></span></p>
<pre class="brush: csharp;">public class EntityFrameworkSession&lt;O&gt; : ISession where O : ObjectContext, new() {
    protected readonly ObjectContext _db;

    public EntityFrameworkSession() {
        _db = new O();
    }

    public virtual void CommitChanges() {
        _db.SaveChanges();
    }

    public virtual void Refresh&lt;T&gt;(T item) where T : class {
        _db.Refresh(RefreshMode.StoreWins, item);
    }

    public virtual void Delete&lt;T&gt;(Expression&lt;Func&lt;T, bool&gt;&gt; expression) where T : class {
        IQueryable&lt;T&gt; query = _db.CreateObjectSet&lt;T&gt;().Where(expression);

        foreach (T item in query) {
            _db.DeleteObject(item);
        }
    }

    public virtual void Delete&lt;T&gt;(T item) where T : class {
        if (item == null)
            throw new ArgumentNullException(&quot;item&quot;);

        _db.DeleteObject(item);
    }

    public virtual void DeleteAll&lt;T&gt;() where T : class {
        ObjectSet&lt;T&gt; query = _db.CreateObjectSet&lt;T&gt;();

        foreach (T item in query) {
            _db.DeleteObject(item);
        }
    }

    public virtual T Single&lt;T&gt;(Expression&lt;Func&lt;T, bool&gt;&gt; expression) where T : class {
        return All&lt;T&gt;().SingleOrDefault(expression);
    }

    public virtual IQueryable&lt;T&gt; All&lt;T&gt;() where T : class {
        return _db.CreateObjectSet&lt;T&gt;().AsQueryable();
    }

    public virtual void Add&lt;T&gt;(T item) where T : class {
        _db.CreateObjectSet&lt;T&gt;().AddObject(item);
    }

    public virtual void Add&lt;T&gt;(IEnumerable&lt;T&gt; items) where T : class {
        foreach (T item in items) {
            _db.CreateObjectSet&lt;T&gt;().AddObject(item);
        }
    }

    public virtual void Update&lt;T&gt;(T item) where T : class {
        // EF4 tracks updates on its own, so nothing is needed here
        return;
    }

    public virtual void Dispose() {
        _db.Dispose();
    }
}</pre>
<p>As you can see, it&#8217;s actually pretty small.&#160; The beauty comes from the fact that it’s completely generic.&#160; When we create an EF4 Entity Data Model (*.EDMX file), we name the data context, and then we can pass it into this implementation, like so:</p>
<pre class="brush: csharp;">// First, we need to build the session
var session = new EntityFrameworkSession&lt;NorthwindEntities&gt;();

// Now I can get any table I want from the session.
var products = session.All&lt;Product&gt;();

// Maybe I want and individual item.
var product = session.Single&lt;Product&gt;(x =&gt; x.ProductID = 1);

// We can use the more verbose LINQ syntax, too.
var products = from p in session.All&lt;Product&gt;()
               where p.Price &gt; 2.50m
               select p;</pre>
<p>As you can see, working with ISession is pretty easy from this implementation.&#160; One thing I haven’t covered in this post is support for logical deletes.&#160; We have another subclass for that which uses this EF4 implementation as its base.&#160; This is why all the methods in our implementation are virtual.&#160; I’ll save that implementation for another post!</p>
<img src="http://feeds.feedburner.com/~r/geeksharp/~4/IPrr0K182J8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://geeksharp.com/2010/11/16/implementing-isession-in-ef4/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://geeksharp.com/2010/11/16/implementing-isession-in-ef4/</feedburner:origLink></item>
		<item>
		<title>Nginx, Rails and PHP: Round 2!</title>
		<link>http://feedproxy.google.com/~r/geeksharp/~3/frsVNFHAD4I/</link>
		<comments>http://geeksharp.com/2010/09/14/nginx-rails-and-php-round-2/#comments</comments>
		<pubDate>Tue, 14 Sep 2010 18:30:37 +0000</pubDate>
		<dc:creator>Scott Anderson</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://geeksharp.com/?p=38</guid>
		<description><![CDATA[<p>It’s been a while since I posted about my current webserver setup, and a few things have changed around here!&#160; I like to stay current, and the latest version of PHP has changed the way I build from source.&#160; I’ve also changed the way I install stuff, this way it’s much easier to update things like PHP which tend to litter files all over the place.&#160; Anyway, you came here for the goods, so here we go:</p>
<p><a href="http://geeksharp.com/2010/09/14/nginx-rails-and-php-round-2/" class="more-link">Read more on Nginx, Rails and PHP: Round 2!&#8230;</a></p>
]]></description>
			<content:encoded><![CDATA[<p>It’s been a while since I posted about my current webserver setup, and a few things have changed around here!&#160; I like to stay current, and the latest version of PHP has changed the way I build from source.&#160; I’ve also changed the way I install stuff, this way it’s much easier to update things like PHP which tend to litter files all over the place.&#160; Anyway, you came here for the goods, so here we go:</p>
<h4>Step 1:&#160; Environment and Pre-Requisites</h4>
<p>This section probably looks familiar.&#160; The only difference now is that I’m running Ubuntu 10.04 LTS on my main server now.&#160; The packages are pretty much the same.&#160; First we make sure the universe repository is enabled by editing /etc/apt/sources.list and removing the hash marks in front of universe lines:</p>
<p><span id="more-38"></span></p>
<pre class="brush: plain;">deb http://us.archive.ubuntu.com/ubuntu/ lucid universe multiverse
deb-src http://us.archive.ubuntu.com/ubuntu/ lucid universe multiverse
deb http://us.archive.ubuntu.com/ubuntu/ lucid-updates universe restricted main multiverse
deb-src http://us.archive.ubuntu.com/ubuntu/ lucid-updates universe multiverse
deb http://security.ubuntu.com/ubuntu lucid-security universe multiverse
deb-src http://security.ubuntu.com/ubuntu lucid-security universe multiverse</pre>
<p>Next we need to snag a lot of packages that are requried to build the various packages.&#160; Run the following commands to get what we need:</p>
<pre class="brush: plain;">sudo apt-get update
sudo apt-get install build-essential libxml2-dev libssl-dev libbz2-dev curl libcurl4-openssl-dev libpng12-dev libmcrypt-dev mysql-server libmysqlclient-dev libxslt1-dev autoconf2.13 libltdl-dev libreadline5-dev libsqlite3-ruby postgresql-server-dev-8.4 libpcre3-dev</pre>
<p>Finally, libevent still hasn’t been updated to a suitable version for PHP-FPM, so we need to install that manually:</p>
<pre class="brush: plain;">wget http://monkey.org/~provos/libevent-1.4.14b-stable.tar.gz
cd libevent-1.4.14b-stable
./configure
make &amp;&amp; sudo checkinstall</pre>
<p>You&#8217;ll notice above that I use the &quot;checkinstall&quot; command to install this package.&#160; The main reason I use this is that it makes upgrading a lot easier in the future.&#160; It’s especially nice when you want to update something like PHP.&#160; This handy command will generate a nice *.deb file for you, and then you can remove the package using “dpkg –r packagename” when you’re ready to upgrade down the road.&#160; Neat, huh?&#160; <strong>Note</strong>:&#160; if you get an error during building the package with checkinstall, it’s probably because you need to change the version of your package to say “1.4.14b-stable” instead of just “stable.”&#160; For reference, here are the checkinstall values I use:</p>
<pre class="brush: plain;">This package will be built according to these values:

0 -  Maintainer: [ Scott Anderson &lt;scott@geeksharp.com&gt; ]
1 -  Summary: [ My custom version of libevent-1.4.14b-stable ]
2 -  Name:    [ libevent ]
3 -  Version: [ 1.4.14b-stable ]
4 -  Release: [ 1 ]
5 -  License: [ GPL ]
6 -  Group:   [ checkinstall ]
7 -  Architecture: [ i386 ]
8 -  Source location: [ libevent-1.4.14b-stable ]
9 -  Alternate source location: [  ]
10 - Requires: [  ]
11 - Provides: [ libevent ]</pre>
<h4>Step 2:&#160; Compiling PHP From Source with the Suhosin Patch</h4>
<p>Since the FPM module is now included in PHP as of version 5.3.3, we don’t have to download it separately.&#160; All we need to snag is the latest Suhosin patch and apply to to the 5.3.3 source.&#160; </p>
<pre class="brush: plain;">wget http://us2.php.net/get/php-5.3.3.tar.bz2/from/this/mirror
bzip2 -dc php-5.3.3.tar.bz2 | tar xf -
wget http://download.suhosin.org/suhosin-patch-5.3.3-0.9.10.patch.gz
gunzip suhosin-patch-5.3.3-0.9.10.patch.gz
cd php-5.3.3
patch -p 1 -i ../suhosin-patch-5.3.3-0.9.10.patch</pre>
<p>Now all we have to do is configure and build PHP itself.&#160; Thankfully this process is a lot simpler now that PHP-FPM has been integrated into the core PHP source.</p>
<pre class="brush: plain;">./configure --enable-bcmath --with-bz2 --enable-calendar --enable-fpm --with-fpm-user=www-data --with-fpm-group=www-data --with-curl --enable-dba --enable-exif --enable-ftp --with-gd --with-gettext --enable-mbstring --with-mysql --with-mysqli --with-pdo-mysql --with-openssl --with-pcre-regex --enable-shmop --enable-soap --enable-sockets --enable-sysvmsg --enable-wddx --enable-zip --with-zlib --enable-sysvsem --enable-sysvshm --with-mcrypt --enable-pcntl --enable-mbregex --with-mhash --with-xsl
make &amp;&amp; sudo checkinstall</pre>
<p>Now we need to copy the init.d script and the new php-fpm.conf into place.&#160; Even if you already had PHP-FPM installed, these steps are essential because the configuration format has changed, and we need to modify a couple of settings.&#160; You can move the new files into place like so:</p>
<pre class="brush: plain;">sudo cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
sudo chmod +x /etc/init.d/php-fpm
sudo cp sapi/fpm/php-fpm.conf /usr/local/etc/php-fpm.conf
sudo cp php.ini-production /usr/local/lib/php.ini</pre>
<p>There are a few things you’ll need to change in the config file before we can actually start PHP.&#160; Make sure you open /usr/local/etc/php-fpm.conf in your favorite text editor and change the following values.&#160; Please note that the “pm” settings are what I use on my VPS, but you might want to adjust them to better suit your environment.</p>
<pre class="brush: plain;">pid = /usr/local/var/run/php-fpm.pid
pm.max_children = 10
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 5</pre>
<p>Now you can stop and start PHP-FPM like so:</p>
<pre class="brush: plain;">sudo /etc/init.d/php-fpm restart</pre>
<h4>Step 3:&#160; Ruby Enterprise Edition, Nginx, and Phusion Passenger</h4>
<p>By far the best way to run a Rails site in production is by using Phusion Passenger and Ruby Enterprise Edition.&#160; The performance benefits are huge, and this setup is very friendly to limited resource environments (like VPS’s).&#160; During the installation of Ruby Enterprise Edition, we will have the opportunity to customize our Nginx install, so we need to snag its source too.&#160; Here’s how:</p>
<pre class="brush: plain;">wget http://nginx.org/download/nginx-0.7.67.tar.gz
wget http://rubyforge.org/frs/download.php/71096/ruby-enterprise-1.8.7-2010.02.tar.gz
tar -zxf nginx-0.7.67.tar.gz
tar -zxf ruby-enterprise-1.8.7-2010.02.tar.gz
./ruby-enterprise-1.8.7-2010.02/installer</pre>
<p>This install process is pretty seamless.&#160; Once you’re done, you need to run one more command to enable Phusion Passenger support in Nginx:</p>
<pre class="brush: plain;">sudo /opt/ruby-enterprise-1.8.7-2010.02/bin/passenger-install-nginx-module</pre>
<p>This install script will ask you a series of questions.&#160; I prefer to customize my Nginx install, so here are my answers.&#160; Obviously, you’ll need to adjust any paths to places appropriate for your system and where you extracted the nginx source tarball.</p>
<pre class="brush: plain;">Enter your choice (1 or 2) or press Ctrl-C to abort: 2
Please specify the directory: &lt;enter your directory, in my case it was /home/scott/nginx-0.7.67&gt;
Please specify a prefix directory [/opt/nginx]: /usr/local/nginx
Extra arguments to pass to configure script: --sbin-path=/usr/local/sbin --with-http_ssl_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module --with-http_stub_status_module --with-http_gzip_static_module</pre>
<h4>Step 4:&#160; Nginx Configuration</h4>
<p>We took care of PHP above, so all we need to do now is configure Nginx.&#160; My default configuration file is below.&#160; You can tweak it however you like, but these settings work really well in my environment.&#160; If you used the same options as I did above, you can find this file at /usr/local/nginx/conf/nginx.conf:</p>
<pre class="brush: plain;">user  www-data;
worker_processes  4;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  10 10;

    passenger_root /opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/gems/1.8/gems/passenger-2.2.15;
    passenger_ruby /opt/ruby-enterprise-1.8.7-2010.02/bin/ruby;
    passenger_pool_idle_time 1000;

    gzip  on;
    gzip_comp_level 1;
    gzip_proxied any;
    gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    log_format main '$remote_addr - $remote_user [$time_local] '
        '&quot;$request&quot; $status  $body_bytes_sent &quot;$http_referer&quot; '
        '&quot;$http_user_agent&quot; &quot;$http_x_forwarded_for&quot;';

    access_log  /var/log/nginx_access.log main;

    error_log  /var/log/nginx_error.log crit;

    include /usr/local/nginx/sites-enabled/*;
}</pre>
<p>Now we need to set some default fastcgi options in /usr/local/nginx/conf/fastgci_params.&#160; I just appended these to the end of the file.</p>
<pre class="brush: plain;">fastcgi_connect_timeout 60;
fastcgi_send_timeout 180;
fastcgi_read_timeout 180;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
fastcgi_intercept_errors on;</pre>
<p>Next, I like to create a &quot;/usr/local/nginx/sites-enabled&quot; directory that houses each website&#8217;s configuration details.&#160; First I&#8217;ll show the configuration I used to handle URL rewrites for WordPress (this blog).&#160; I called the file /usr/local/nginx/sites-enabled/geeksharp.com.</p>
<pre class="brush: plain;">server {
 listen 80;
 server_name *.geeksharp.com *.geeksharp.info *.geeksharp.org geeksharp.info geeksharp.org;
 rewrite ^(.*) http://geeksharp.com$1 permanent;
}

server {
 listen 80;
 server_name geeksharp.com;
 location / {
 root&#160;&#160; /var/www;&#160; # absolute path to your WordPress installation
 index&#160; index.php index.html index.htm;

 # this serves static files that exist without running other rewrite tests
 if (-f $request_filename) {
 expires 30d;
 break;
 }

 # this sends all non-existing file or directory requests to index.php
 if (!-e $request_filename) {
 rewrite ^(.+)$ /index.php?q=$1 last;
 }
 }

 location ~ \.php$ {
 fastcgi_pass 127.0.0.1:9000;
 fastcgi_index index.php;
 fastcgi_param SCRIPT_FILENAME /var/www$fastcgi_script_name;
 include fastcgi_params;
 }
}</pre>
<p>Here&#8217;s how I&#8217;d set up a rails site.&#160; In this example, the file is called /usr/local/nginx/sites-enabled/geeksharp.net.</p>
<pre class="brush: plain;">server {
 listen 80;
 server_name *.geeksharp.net;
 rewrite ^(.*) http://geeksharp.net$1 permanent;
}

server {
 listen 80;
 server_name geeksharp.net;
 root /home/scott/geeksharp.net/public;
 passenger_enabled on;
 access_log /home/scott/geeksharp.net-access.log;
 error_log /home/scott/geeksharp.net-error.log;
}</pre>
<h4>Step 5:&#160; Startup Scripts</h4>
<p>We already copied the PHP startup script into place earlier, however we need to create one for Nginx, too.&#160; Place this file at /etc/init.d/nginx and use the following contents:</p>
<pre class="brush: plain;">#! /bin/sh

### BEGIN INIT INFO
# Provides:&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; nginx
# Required-Start:&#160;&#160;&#160; $all
# Required-Stop:&#160;&#160;&#160;&#160; $all
# Default-Start:&#160;&#160;&#160;&#160; 2 3 4 5
# Default-Stop:&#160;&#160;&#160;&#160;&#160; 0 1 6
# Short-Description: starts the nginx web server
# Description:&#160;&#160;&#160;&#160;&#160;&#160; starts nginx using start-stop-daemon
### END INIT INFO

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/local/sbin/nginx
NAME=nginx
DESC=nginx 

test -x $DAEMON || exit 0

# Include nginx defaults if available
if [ -f /etc/default/nginx ] ; then
 . /etc/default/nginx
fi

set -e

case &quot;$1&quot; in
 start)
 echo -n &quot;Starting $DESC: &quot;
 start-stop-daemon --start --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \
 --exec $DAEMON -- $DAEMON_OPTS
 echo &quot;$NAME.&quot;
 ;;
 stop)
 echo -n &quot;Stopping $DESC: &quot;
 start-stop-daemon --stop --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \
 --exec $DAEMON
 echo &quot;$NAME.&quot;
 ;;
 restart|force-reload)
 echo -n &quot;Restarting $DESC: &quot;
 start-stop-daemon --stop --quiet --pidfile \
 /usr/local/nginx/logs/$NAME.pid --exec $DAEMON
 sleep 1
 start-stop-daemon --start --quiet --pidfile \
 /usr/local/nginx/logs/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
 echo &quot;$NAME.&quot;
 ;;
 reload)
 echo -n &quot;Reloading $DESC configuration: &quot;
 start-stop-daemon --stop --signal HUP --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \
 --exec $DAEMON
 echo &quot;$NAME.&quot;
 ;;
 *)
 N=/etc/init.d/$NAME
 echo &quot;Usage: $N {start|stop|restart|force-reload}&quot; &gt;&amp;2
 exit 1
 ;;
esac

exit 0</pre>
<p>Finally, make sure you update your rc.d</p>
<pre class="brush: plain;">sudo update-rc.d nginx defaults
sudo update-rc.d php-fpm defaults</pre>
<p>Please note that if for some reason nginx won&#8217;t start, chances are you have a config issue.&#160; When you issue a restart command, the config errors usually will not be displayed.&#160; The best way to track them down is to is to simply issue a stop command followed by a start command, and your errors will be displayed.&#160; If you ever need to restart your services manually, you can use these commands (I find that restart can be buggy, which is why I explicity stop and start each one):</p>
<pre class="brush: plain;">sudo /etc/init.d/php-fpm stop &amp;&amp; sudo /etc/init.d/php-fpm start
sudo /etc/init.d/nginx stop &amp;&amp; sudo /etc/init.d/nginx start</pre>
<p>So that&#8217;s it! I know this is an epic post, but I hope it helps someone. Leave comments if you have specific questions or if I left out something particularly useful. Again, I understand that there&#8217;s probably a better way to do something, so feel free to share your thoughts!&#160; As a final thought, I would like to thank <a href="http://interfacelab.com/nginx-php-fpm-apc-awesome/" target="_blank">Joshua Dorkin</a> for providing a great article on which I based a lot of this material!</p>
<img src="http://feeds.feedburner.com/~r/geeksharp/~4/frsVNFHAD4I" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://geeksharp.com/2010/09/14/nginx-rails-and-php-round-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://geeksharp.com/2010/09/14/nginx-rails-and-php-round-2/</feedburner:origLink></item>
		<item>
		<title>Mocking Rob Conery’s ISession</title>
		<link>http://feedproxy.google.com/~r/geeksharp/~3/HMD_6J1C5OA/</link>
		<comments>http://geeksharp.com/2010/08/26/mocking-rob-conery%e2%80%99s-isession/#comments</comments>
		<pubDate>Thu, 26 Aug 2010 18:25:12 +0000</pubDate>
		<dc:creator>Scott Anderson</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Useful Tricks]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[Unit Testing]]></category>

		<guid isPermaLink="false">http://geeksharp.com/?p=29</guid>
		<description><![CDATA[<p>Recently at work, we’ve really started to embrace TDD (and BDD).&#160; As a team, it helps us write much cleaner, more efficient code.&#160; I’m not going to preach forever about the benefits of TDD.&#160; There are thousands of other blog posts out there beating this topic to death.&#160; One of the ways that we communicate with our databases at work is by using <a href="http://blog.wekeroad.com/2010/04/19/tekpub-starter" target="_blank">Rob Conery’s ISession</a> interface.&#160; We have an implementation of this interface for Entity Framework 4, and it works beautifully.&#160; However, given that this interface is super generic, it’s less than obvious how you would mock such a thing.&#160; Here’s the ISession interface in all its glory:</p>
<p><a href="http://geeksharp.com/2010/08/26/mocking-rob-conery%e2%80%99s-isession/" class="more-link">Read more on Mocking Rob Conery’s ISession&#8230;</a></p>
]]></description>
			<content:encoded><![CDATA[<p>Recently at work, we’ve really started to embrace TDD (and BDD).&#160; As a team, it helps us write much cleaner, more efficient code.&#160; I’m not going to preach forever about the benefits of TDD.&#160; There are thousands of other blog posts out there beating this topic to death.&#160; One of the ways that we communicate with our databases at work is by using <a href="http://blog.wekeroad.com/2010/04/19/tekpub-starter" target="_blank">Rob Conery’s ISession</a> interface.&#160; We have an implementation of this interface for Entity Framework 4, and it works beautifully.&#160; However, given that this interface is super generic, it’s less than obvious how you would mock such a thing.&#160; Here’s the ISession interface in all its glory:</p>
<p><span id="more-29"></span></p>
<pre class="brush: csharp;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace MyApplication.Models {
    public interface ISession : IDisposable {
        void CommitChanges();
        void Delete&lt;T&gt;(Expression&lt;Func&lt;T, bool&gt;&gt; expression) where T : class;
        void Delete&lt;T&gt;(T item) where T : class;
        void DeleteAll&lt;T&gt;() where T : class;
        T Single&lt;T&gt;(Expression&lt;Func&lt;T, bool&gt;&gt; expression) where T : class;
        IQueryable&lt;T&gt; All&lt;T&gt;() where T : class;
        void Add&lt;T&gt;(T item) where T : class;
        void Add&lt;T&gt;(IEnumerable&lt;T&gt; items) where T : class;
        void Update&lt;T&gt;(T item) where T : class;
    }
}</pre>
<p>This simple interface is pretty powerful. Using Ninject (our DI/IoC library of choice), it’s simple to inject our concrete EF4 implementation of this interface into the service layer of our MVC projects.&#160; Since our service layer sits in between our MVC application and the database, it’s critical that we put tests around them.&#160; It’s important to realize, though, that <strong>we only want to test the service itself, not the EF4 integration</strong>.&#160; We can test the EF4 integration separately using integration tests.&#160; Since our services all take ISession objects in their constructors, we are left with no other options but to mock ISession.</p>
<h3>Enter Moq</h3>
<p><a href="http://code.google.com/p/moq/" target="_blank">Moq</a> is a sweet mocking library for the .NET framework.&#160; We use it extensively in our tests to help focus our tests on specific concerns.&#160; As stated above, our services rely on an ISession implementation to work properly, but that doesn’t mean we have to feed it a real ISession.&#160; Moq allows us to create a <strong>fake</strong> ISession that our services can call.&#160; This, in turn, allows us to focus our tests on just the service itself.</p>
<p>If you’ve ever used Moq before, and you look at the very generic ISession interface above, you quickly realize that mocking this behavior is a little challenging.&#160; Luckily, it’s definitely not impossible… we just have to flex our lambda muscles.&#160; I’ve written a class called “FakeSessionBuilder” for my applications so we can build up a mocked ISession object for use in tests.&#160; Here’s the class:</p>
<pre class="brush: csharp;">// This code is released under the Creative Commons CC0 License
// Find the license here:  http://creativecommons.org/publicdomain/zero/1.0/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Moq;
using MyApplication.Models;

namespace MyApplication.Tests.Mocks {
    public class FakeSessionBuilder {
        public readonly Mock&lt;ISession&gt; Mock;

        public FakeSessionBuilder() {
            Mock = new Mock&lt;ISession&gt;();
        }

        public void LoadFakeCollection&lt;T&gt;(List&lt;T&gt; collection) where T : class {
            if (collection != null) {
                Mock.Setup(x =&gt; x.Single(It.Is&lt;Expression&lt;Func&lt;T, bool&gt;&gt;&gt;(z =&gt; z != null)))
                    .Returns((Expression&lt;Func&lt;T, bool&gt;&gt; func) =&gt; collection.SingleOrDefault(func.Compile()));
                Mock.Setup(x =&gt; x.All&lt;T&gt;())
                    .Returns(collection.AsQueryable());
                Mock.Setup(x =&gt; x.Add(It.IsAny&lt;T&gt;()))
                    .Callback((T item) =&gt; collection.Add(item));
                Mock.Setup(x =&gt; x.Add(It.IsAny&lt;IEnumerable&lt;T&gt;&gt;()))
                    .Callback((IEnumerable&lt;T&gt; items) =&gt; items.ToList().ForEach(collection.Add));
                Mock.Setup(x =&gt; x.Delete(It.Is&lt;Expression&lt;Func&lt;T, bool&gt;&gt;&gt;(z =&gt; z != null)))
                    .Callback((Expression&lt;Func&lt;T, bool&gt;&gt; func) =&gt; collection.Remove(collection.SingleOrDefault(func.Compile())));
                Mock.Setup(x =&gt; x.Delete(It.IsAny&lt;T&gt;()))
                    .Callback((T item) =&gt; collection.Remove(item));
                Mock.Setup(x =&gt; x.DeleteAll&lt;T&gt;())
                    .Callback((T type) =&gt; collection.Clear());
            }
        }
    }
}</pre>
<p>The bread and butter of this class is obviously the <strong>LoadFakeCollection()</strong> method.&#160; Basically, we’re setting up a fake session that will actually perform the tasks that we want it to.&#160; This might make a few people cringe.&#160; I can hear the questions now:</p>
<ol>
<li><strong>Why are you creating logic within the mocked methods?</strong>
<p>I think the better question is “why not?”&#160; Honestly I don’t think we’re really creating any logic here that needs to be tested.&#160; If you look closely, we’re using internal .NET collections (List&lt;T&gt;) and their built-in methods.&#160; We’re actually hitting the framework here, not custom code.&#160; I don’t typically worry about testing the actual .NET framework.&#160; Do you? </li>
<li><strong>All these crazy lambda expressions make my head hurt.&#160; Couldn’t you do this another way?</strong>
<p>Yes, I probably could.&#160; But I wanted to make this session builder as generic as possible.&#160; This allows us to reuse the fake session in service test class.&#160; I don’t want to repeat myself any more than I have to.&#160; And let’s face it, the ISession interface itself may look simple (and actually implementing it is easy as pie), but slinging all those generics around does make mocking harder. </li>
<li><strong>Couldn’t you avoid mocking completely and just write another concrete implementation of ISession that isn’t tied to your database?</strong>
<p>Yeah, I suppose I could.&#160; But I honestly think it would be a lot harder, and it would repeat a lot more code.&#160; Moq also lets me do neat things like verifying that a method is actually called in a much easier way.&#160; I like the flexibility that Moq gives me, and this code is actually pretty elegant, in my opinion.&#160; I dare you to write a concrete implementation that handles everything as cleanly as Moq does. </li>
</ol>
<h3>So how do you use this thing?</h3>
<p>It’s actually pretty simple.&#160; I’m sure you’re familiar with the arrange, act, assert method of testing, right?&#160; Well in my tests for my service layer, I create my fake session, load it up with any collections I want it to contain, and then use that in the arrangement for my tests.&#160; I’m sure a code sample would help here, so here you go:</p>
<pre class="brush: csharp;">using System.Collections.Generic;
using System.Linq;
using MyApplication.Models;
using MyApplication.Services;
using MyApplication.Tests.Mocks;
using Xunit;

namespace MyApplication.Tests.Admin {
    public class MyCustomServiceTests {

        public ISession GetFakeSession() {
            // First grab collections of fake objects used in the test
            List&lt;MyCustomModel&gt; models1 = Mocks.GetListOfFakeCustomModels();
            List&lt;MyOtherModel&gt; models2 = Mocks.GetListOfFakeOtherModels();

            // Now build a fake session loaded with these collections
            var fakeSession = new FakeSessionBuilder();
            fakeSession.LoadFakeCollection(models1);
            fakeSession.LoadFakeCollection(models2);
            return fakeSession.Mock.Object;
        }

        [Fact]
        public void GetMyCustomModelByID() {
            // Arrange
            ISession session = GetFakeSession();
            var service = new MyCustomService(session);

            // Act
            MyCustomModel model = service.GetByID(1);

            // Assert
            Assert.NotNull(model);
            Assert.Equal(1, model.ID);
        }
    }
}</pre>
<h3>Wrapping it up</h3>
<p>I hope you can see how easy it is to use the <strong>FakeSessionBuilder</strong> object.&#160; I’m definitely not a TDD guru.&#160; I’d love to hear from you to see exactly how you would accomplish the same tests in your application.&#160; Hopefully you find this useful.&#160; I’ve released it under the most free license I could find.&#160; Cheers!</p>
<img src="http://feeds.feedburner.com/~r/geeksharp/~4/HMD_6J1C5OA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://geeksharp.com/2010/08/26/mocking-rob-conery%e2%80%99s-isession/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://geeksharp.com/2010/08/26/mocking-rob-conery%e2%80%99s-isession/</feedburner:origLink></item>
	</channel>
</rss>

