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

<channel>
	<title>Simply Does Not Work &#187; Web Development</title>
	<atom:link href="http://nicholas.piasecki.name/blog/category/programming/web-development/feed/" rel="self" type="application/rss+xml" />
	<link>http://nicholas.piasecki.name/blog</link>
	<description>Confessions of a small business software developer</description>
	<lastBuildDate>Sat, 26 Feb 2011 16:06:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.5</generator>
		<item>
		<title>Inside Skiviez: Mailing Addresses</title>
		<link>http://nicholas.piasecki.name/blog/2010/11/inside-skiviez-mailing-addresses/</link>
		<comments>http://nicholas.piasecki.name/blog/2010/11/inside-skiviez-mailing-addresses/#comments</comments>
		<pubDate>Wed, 24 Nov 2010 16:27:44 +0000</pubDate>
		<dc:creator>Nicholas Piasecki</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[skiviez]]></category>
		<category><![CDATA[web stuff]]></category>

		<guid isPermaLink="false">http://nicholas.piasecki.name/blog/?p=714</guid>
		<description><![CDATA[Skiviez ships to about two dozen countries around the world. This means that our e-commerce system has to be able to accept and deal with international addresses. For a long time, Skiviez dealt with this problem in a way that I would say the vast majority of US-based e-commerce based retailers dealt with it: they [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.skiviez.com/">Skiviez</a> ships to about <a href="http://www.skiviez.com/underwear.aspx/pages/shipping-rates/us">two dozen countries</a> around the world. This means that our e-commerce system has to be able to accept and deal with international addresses.</p>

<p>For a long time, Skiviez dealt with this problem in a way that I would say the vast majority of US-based e-commerce based retailers dealt with it: they added a country dropdown, turned the State field into a textbox, and made the State field no longer required. And if you are not obsessive compulsive like I am, then this works reasonably well enough: international customers have to shoehorn their address into the format presented, but the data can still get in there.</p>

<p>However, after 10 years in operation, this approach was beginning to show some deficiencies:</p>

<p><strong>Magnetic attraction.</strong> There is, for lack of a better term, a magnetic attraction between users and text boxes. Even if the field is not required, users have a tendency to enter &#8220;N/A&#8221;, &#8220;.&#8221;, &#8220;?&#8221;, &#8220;none&#8221;, or some other placeholder value in fields that do not apply to them.</p>

<p><strong>Address quality problems.</strong> With the above method, the bumpers are off&#8211;a user could type &#8220;cheese&#8221; into the postal code field, and we&#8217;d just have to accept it on their word that &#8220;cheese&#8221; is a valid postal code for the United Kingdom because the site wasn&#8217;t doing any sort of validation except for United States-based addresses. Shipping a parcel to another country only to have it returned or destroyed as a result of an invalid or insufficient address is an expensive issue.</p>

<p><strong>Integration issues.</strong> To actually ship out international packages, we have to do deal with third-party carrier APIs (such as Endicia, FedEx, and UPS) to purchase postage and print shipping labels. Some of these APIs do perform more advanced validation on international addresses. This could cause problems because a poorly formatted address would make it nearly all of the way through our fulfillment process&#8211;order acceptance, picking, processing, and packaging&#8211;only to blow up with an error at the shipping desk. It&#8217;d be nice if we could catch problems earlier to avoid disrupting the shipping flow and eliminate the potential for misrouting the package.</p>

<h2>A smarter system</h2>

<p>With the October 2010 release of the Skiviez Web site (which was a pretty huge update), the Web site is now much, much smarter in how it asks for address information. For example, here&#8217;s the default address form for the United States, which is about what you&#8217;d expect:</p>

<p><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/11/11-22-2010-6-39-23-PM.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/11/11-22-2010-6-39-23-PM.png" alt="" title="United States Address Input" width="426" height="534" class="aligncenter size-full wp-image-728" /></a></p>

<p>But if you choose, say, Ireland in the countries drop down, the page refreshes and displays a new form:</p>

<p><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/11/11-22-2010-6-40-52-PM.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/11/11-22-2010-6-40-52-PM.png" alt="" title="Ireland Address Input" width="430" height="473" class="aligncenter size-full wp-image-729" /></a></p>

<p>The state drop down is gone (since Ireland doesn&#8217;t have states), the ZIP/postal code text box is gone (since Ireland does not use postal codes), and a new County text box is available.</p>

<p>Once an address is entered, it is formatted in the way a person native to that country would expect. For example, in a German address, the postal code comes before the city:</p>

<p><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/11/11-22-2010-6-49-33-PM.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/11/11-22-2010-6-49-33-PM.png" alt="" title="German Address Formatting" width="262" height="135" class="aligncenter size-full wp-image-731" /></a></p>

<p>Taking it even further, if you select, say, Finland from the drop down, you get a form back that looks like this:</p>

<p><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/11/11-22-2010-6-46-10-PM.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/11/11-22-2010-6-46-10-PM.png" alt="" title="Finland Address Input" width="425" height="482" class="aligncenter size-full wp-image-730" /></a></p>

<p>The postal code validates against the postal code format used in Finland, and that field appears before the Municipality field, since the convention throughout most of the EU is to write &#8220;{Postal Code} {City}&#8221; instead of the American &#8220;{City} {State} {Postal Code}&#8221; way.</p>

<p>Clearly, we&#8217;ve made a lot of improvements to address handling at Skiviez, and this simple input format actually has <em>a lot</em> of complexity behind it. So how does it all work?</p>

<h2>Tweaking the existing database schema</h2>

<p>At Skiviez, we were clearly working from a legacy database schema. The customer addresses table has been sitting there for 10 years, and we&#8217;re not about to change it any time soon. And while there is some internal cruft, the fields in the database more or less looked like the following:</p>

<p><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/11/Fields.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/11/Fields.png" alt="" title="Original Fields" width="169" height="396" class="aligncenter size-full wp-image-717" /></a></p>

<p>This is a normal, relational schema. So how do we enhance this table so that it can store addresses from the dozens of countries that we ship to? That sounds like a tall order: surely the addresses of the world are all wildly different from one another, and we&#8217;ll have to go <a href="http://en.wikipedia.org/wiki/Entity-attribute-value_model">entity-attribute-value</a>, throwing away the relational bit of our relational data store, to be able to accurately store this diverse information, right?</p>

<p>Well, it turns out that you can take these existing fields, relax away any <code>NOT NULL</code> constraints, and rename them to field names that are operating at a higher level of abstraction. (We didn&#8217;t actually rename the fields in the database, as this would have broken old code, but the new field names do exist in the object model, described later.)</p>

<p>In other words, you can shoehorn most of the addresses in the world (most importantly, the ones that Skiviez ships to), by just thinking of the existing fields in these terms:</p>

<p><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/11/fields2.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/11/fields2.png" alt="" title="Renamed Fields" width="434" height="424" class="aligncenter size-full wp-image-718" /></a></p>

<p>Nothing has really changed. We&#8217;re just making the concession that it&#8217;s OK that the meaning of the data within these fields will change slightly depending on the country we&#8217;re talking about. In the United States, the &#8220;AdministrativeArea&#8221; is the state, territory, or military post office. In Ireland, the &#8220;AdministrativeArea&#8221; is the county. And in Finland, the &#8220;AdministrativeArea&#8221; is <code>NULL</code> because it simply isn&#8217;t used at all.</p>

<h2>Creating a sane object model</h2>

<p>There is something wrong with the database schema, though, and for the sake of preserving legacy code and data, I worked around it in the new object model that is persisted to this schema. The problem is as follows:</p>

<p><strong>A mailing address is not the same as a contact.</strong></p>

<p>Frequently while coding over the years, I found myself wanting to deal with a physical address when I didn&#8217;t have any related contact information. That is, I had a group of data for <code>123 Main St; Richmond, VA 23221; United States</code>, but I didn&#8217;t know who lived there or what the phone number was. The only object I had in my model was an <code>Address</code> object that was a 1-1 mapping with the old database schema, so this meant having <code>Address</code> instances with a <code>null</code> name and a <code>null</code> phone number.</p>

<p>A more natural model is to split the fields into three objects and create a fourth object that is composed of all of them:</p>

<p><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/11/diagram.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/11/diagram.png" alt="" title="Basic Object Model" width="648" height="470" class="aligncenter size-full wp-image-721" /></a></p>

<p>So instead of one big honking <code>Address</code> object, we have</p>

<ul>
<li>an <code>Address</code> object that just contains physical address information;</li>
<li>a <code>Country</code> object (not shown in the above diagram) that contains information necessary to format and validate an address (more on this later);</li>
<li>a <code>PersonalName</code> object that binds all of the name fields together;</li>
<li>a <code>Contact</code> object that groups together a <code>PersonalName</code>, an optional company name string, and a <code>PhoneNumberBase</code> object; and</li>
<li>a <code>MailingAddress</code> object that pairs a <code>Contact</code> with an <code>Address</code>.</li>
</ul>

<p>By splitting the old <code>Address</code> object into these individual components, I can now freely re-use these components elsewhere in the application. For example, the <code>PersonalName</code> object also gets used in the <code>Customer</code> object. The return form generator expects a <code>MailingAddress</code> object, but a shipping rate calculator can deal with an <code>Address</code> object directly, since the latter has no need for the <code>Contact</code> information. In other words, the object model went from coarse-grained to fine-grained.</p>

<p>But perhaps the most important aspect of this model is that each of the four above classes is <strong>immutable</strong>.</p>

<h2>Why are immutable addressing objects better?</h2>

<p>When an object is immutable, it can&#8217;t be altered after it is first instanced. In other words, everything about the object is permanently set at construction time; its instance methods won&#8217;t mutate the object, and its properties don&#8217;t have public setters. In domain driven design, this is often referred to as a value type, but I don&#8217;t like that terminology as it can cause some confusion with value-vs-reference types in the .NET Framework.</p>

<p>This means that if I have an instance of an <code>Address</code> and want to edit the <code>PostalCode</code> property, then I will need to create a brand new instance of an <code>Address</code>, copy most of the properties over, and set my new postal code at construction time.</p>

<p>There are a few advantages to this approach:</p>

<ul>
<li>The instance can validate itself once at construction time. This can be a big win if validation is particularly complex and dependent on the values of other properties (which is exactly what happens in an address, since the country determines whether or not a field is required and what format it needs to be in). If anything else is referencing that <code>Address</code> instance, then it can assume that that instance won&#8217;t get put into an invalid state. For example, a <code>SalesOrder</code> has a <code>ShippingAddress</code> property that takes a <code>MailingAddress</code> instance. The <code>SalesOrder</code> doesn&#8217;t have to worry about someone coming along and saying <code>ShippingAddress.PostalCode = null</code> at some point, bypassing any validation checks. The whole <code>ShippingAddress</code> instance would have to be replaced, which means building a new <code>Address</code> instance, which means running the validation logic built into the address builder.</li>
<li>The hash code of the instance is consistent throughout the object&#8217;s lifetime. This is useful for modeling an address property as a component in NHibernate, which I won&#8217;t get into here.</li>
</ul>

<p>But a big disadvantage to this approach is that it can be tedious to deal with in code. At face level, this means that our <code>Address</code> object would need a gigantic constructor or support an <code>IFreezable</code>-type of implementation. A cleaner way is to use <a href="http://en.wikipedia.org/wiki/Builder_pattern">the builder pattern</a> to allow us to set the fields in any order and validate the <code>Address</code> in one shot:</p>


<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">var country <span style="color: #008000;">=</span> CountryMother<span style="color: #008000;">.</span><span style="color: #0000FF;">UnitedStates</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #0600FF; font-weight: bold;">return</span> <span style="color: #008000;">new</span> Address<span style="color: #008000;">.</span><span style="color: #0000FF;">Builder</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">.</span><span style="color: #0000FF;">WithPrimaryStreetLine</span><span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;3005 SOME ST&quot;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">.</span><span style="color: #0000FF;">WithMunicipality</span><span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;RICHMOND&quot;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">.</span><span style="color: #0000FF;">WithAdministrativeArea</span><span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;VIRGINIA&quot;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">.</span><span style="color: #0000FF;">WithPostalCode</span><span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;23221&quot;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">.</span><span style="color: #0000FF;">WithCountry</span><span style="color: #008000;">&#40;</span>country<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">.</span><span style="color: #0000FF;">Build</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span> <span style="color: #008080; font-style: italic;">// exception thrown here if validation errors</span></pre></div></div>


<p>If we want to get a list of detailed validation problems instead of throwing an exception, the builder provides a mechanism for that:</p>


<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">var country <span style="color: #008000;">=</span> CountryMother<span style="color: #008000;">.</span><span style="color: #0000FF;">UnitedStates</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
var builder <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> Address<span style="color: #008000;">.</span><span style="color: #0000FF;">Builder</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">.</span><span style="color: #0000FF;">WithPrimaryStreetLine</span><span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;3005 SOME ST&quot;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">.</span><span style="color: #0000FF;">WithMunicipality</span><span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;RICHMOND&quot;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">.</span><span style="color: #0000FF;">WithAdministrativeArea</span><span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;VIRGINIA&quot;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">.</span><span style="color: #0000FF;">WithPostalCode</span><span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;23221&quot;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">.</span><span style="color: #0000FF;">WithCountry</span><span style="color: #008000;">&#40;</span>country<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
var results <span style="color: #008000;">=</span> builder<span style="color: #008000;">.</span><span style="color: #0000FF;">Validate</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span>results<span style="color: #008000;">.</span><span style="color: #0000FF;">Any</span><span style="color: #008000;">&#40;</span>x <span style="color: #008000;">=&gt;</span> <span style="color: #008000;">!</span>x<span style="color: #008000;">.</span><span style="color: #0000FF;">Success</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0600FF; font-weight: bold;">foreach</span> <span style="color: #008000;">&#40;</span>var error <span style="color: #0600FF; font-weight: bold;">in</span> results<span style="color: #008000;">.</span><span style="color: #0600FF; font-weight: bold;">Where</span><span style="color: #008000;">&#40;</span>x <span style="color: #008000;">=&gt;</span> <span style="color: #008000;">!</span>x<span style="color: #008000;">.</span><span style="color: #0000FF;">Success</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        Console<span style="color: #008000;">.</span><span style="color: #0000FF;">WriteLine</span><span style="color: #008000;">&#40;</span>
            <span style="color: #666666;">&quot;Field {0}, Error {1}&quot;</span>, 
            error<span style="color: #008000;">.</span><span style="color: #0000FF;">Field</span>, 
            error<span style="color: #008000;">.</span><span style="color: #0000FF;">Message</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0600FF; font-weight: bold;">else</span>
<span style="color: #008000;">&#123;</span>
    var instance <span style="color: #008000;">=</span> builder<span style="color: #008000;">.</span><span style="color: #0000FF;">Build</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>


<p>This allows the user interface to be able to get to detailed error messages pretty easily. But how does that call to <code>Validate()</code> work? How does the builder really know what format an address should be in?</p>

<h2>Validation</h2>

<p>We need to define a way for a <code>Country</code> to know how its mailing addresses need to be formatted. Since we have all countries of the world in our database, but we don&#8217;t ship to all countries in the world, I created a nullable property on the <code>Country</code> object called <code>Scheme</code>. The <code>Scheme</code> is an instance of the <code>AddressScheme</code> class and it&#8217;s persisted to the database along with the country.</p>

<p>If we try to build an address without a country specified or with a country that doesn&#8217;t have an <code>AddressScheme</code>, then we throw an exception saying that we just can&#8217;t do that. Otherwise, our <code>Validate()</code> method will run through a list of the <code>AddressFieldRule</code>s that are contained within the <code>AddressScheme</code> instance, calling the <code>Validate(string)</code> method on the rule for a particular field.</p>

<p>To be able to easily persist these rules in the database, I created an <code>enum</code> that parallels the generic properties of the <code>Address</code> class that we defined earlier:</p>


<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">enum</span> AddressField <span style="color: #008000;">:</span> <span style="color: #6666cc; font-weight: bold;">int</span>
<span style="color: #008000;">&#123;</span>
    Unknown <span style="color: #008000;">=</span> <span style="color: #FF0000;">0</span>,
    AdministrativeArea <span style="color: #008000;">=</span> <span style="color: #FF0000;">1</span>,
    Country <span style="color: #008000;">=</span> <span style="color: #FF0000;">2</span>,
    Municipality <span style="color: #008000;">=</span> <span style="color: #FF0000;">3</span>,
    PostalCode <span style="color: #008000;">=</span> <span style="color: #FF0000;">4</span>,
    PrimaryStreetLine <span style="color: #008000;">=</span> <span style="color: #FF0000;">5</span>,
    SecondaryStreetLine <span style="color: #008000;">=</span> <span style="color: #FF0000;">6</span>,
    SubAdministrativeArea <span style="color: #008000;">=</span> <span style="color: #FF0000;">7</span>
<span style="color: #008000;">&#125;</span></pre></div></div>


<p>Internally, the <code>Address</code> object maintains its state via a <code>Hashtable</code> of fields, where the key is the <code>AddressField</code> enumerated value and the value is an object, usually <code>string</code> but sometimes a <code>Country</code>. The properties of the <code>Address</code> object are really just strongly-typed convenience mappings onto that <code>Hashtable</code> as in the following example:</p>


<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #0600FF; font-weight: bold;">virtual</span> <span style="color: #6666cc; font-weight: bold;">string</span> AdministrativeArea
<span style="color: #008000;">&#123;</span>
	get
	<span style="color: #008000;">&#123;</span>
		<span style="color: #0600FF; font-weight: bold;">return</span> <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">&#91;</span>AddressField<span style="color: #008000;">.</span><span style="color: #0000FF;">AdministrativeArea</span><span style="color: #008000;">&#93;</span> <span style="color: #0600FF; font-weight: bold;">as</span> <span style="color: #6666cc; font-weight: bold;">string</span><span style="color: #008000;">;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
	<span style="color: #0600FF; font-weight: bold;">private</span> set
	<span style="color: #008000;">&#123;</span>
		<span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">&#91;</span>AddressField<span style="color: #008000;">.</span><span style="color: #0000FF;">AdministrativeArea</span><span style="color: #008000;">&#93;</span> <span style="color: #008000;">=</span> value<span style="color: #008000;">;</span>
	<span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>


<p>The implementation of the <code>AddressFieldRule</code> is fairly straightforward. I provide the capability to validate against a regular expression (such as might happen with a postal code field), to simply consider the field required (such as might happen with a city field), and to ensure that the value is a member of a list of a predefined list of values (such as might happen with a province field). The <code>Validate(string)</code> method figures out which rules to apply based on the properties that are set and returns an <code>AddressFieldRuleValidationResult</code> that describes what went right and what went wrong.</p>


<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span>
<span style="color: #008080; font-style: italic;">/// Describes a requirement for an address field for a particular address.</span>
<span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span>
<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">class</span> AddressFieldRule
<span style="color: #008000;">&#123;</span>
    <span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span>
    <span style="color: #008080; font-style: italic;">/// The list of allowed values; this may be null if no particular set of</span>
    <span style="color: #008080; font-style: italic;">/// values is required.</span>
    <span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span>
    <span style="color: #0600FF; font-weight: bold;">private</span> IEnumerable<span style="color: #008000;">&lt;</span>AddressFieldAllowedValue<span style="color: #008000;">&gt;</span> allowedValues<span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span>
    <span style="color: #008080; font-style: italic;">/// The description of the field and its format.</span>
    <span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span>
    <span style="color: #0600FF; font-weight: bold;">private</span> <span style="color: #6666cc; font-weight: bold;">string</span> description<span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span>
    <span style="color: #008080; font-style: italic;">/// The address field.</span>
    <span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span>
    <span style="color: #0600FF; font-weight: bold;">private</span> AddressField field<span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span>
    <span style="color: #008080; font-style: italic;">/// Whether or not the field is required.</span>
    <span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span>
    <span style="color: #0600FF; font-weight: bold;">private</span> <span style="color: #6666cc; font-weight: bold;">bool</span> isRequired<span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span>
    <span style="color: #008080; font-style: italic;">/// The localized name.</span>
    <span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span>
    <span style="color: #0600FF; font-weight: bold;">private</span> <span style="color: #6666cc; font-weight: bold;">string</span> name<span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span>
    <span style="color: #008080; font-style: italic;">/// An optional validation regular expression template.</span>
    <span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span>
    <span style="color: #0600FF; font-weight: bold;">private</span> <span style="color: #6666cc; font-weight: bold;">string</span> validationRegex<span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span>
    <span style="color: #008080; font-style: italic;">/// Initializes a new instance of the &lt;see cref=&quot;AddressFieldRule&quot;/&gt; class.</span>
    <span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span>
    <span style="color: #008080; font-style: italic;">/// &lt;param name=&quot;field&quot;&gt;The field.&lt;/param&gt;</span>
    <span style="color: #008080; font-style: italic;">/// &lt;param name=&quot;isRequired&quot;&gt;if set to &lt;c&gt;true&lt;/c&gt; [is required].&lt;/param&gt;</span>
    <span style="color: #008080; font-style: italic;">/// &lt;param name=&quot;name&quot;&gt;English, localized name for the field. Required.&lt;/param&gt;</span>
    <span style="color: #008080; font-style: italic;">/// &lt;param name=&quot;description&quot;&gt;The english description.&lt;/param&gt;</span>
    <span style="color: #008080; font-style: italic;">/// &lt;param name=&quot;validationRegex&quot;&gt;The validation regex. Optional.&lt;/param&gt;</span>
    <span style="color: #008080; font-style: italic;">/// &lt;param name=&quot;allowedValues&quot;&gt;The allowed values. Optional; if null, then</span>
    <span style="color: #008080; font-style: italic;">/// no particular set of values is required.&lt;/param&gt;</span>
    <span style="color: #008080; font-style: italic;">/// &lt;exception cref=&quot;T:System.ArgumentNullException&quot;&gt;if the englishName is null</span>
    <span style="color: #008080; font-style: italic;">/// or empty&lt;/exception&gt;</span>
    <span style="color: #008080; font-style: italic;">/// &lt;exception cref=&quot;T:System.ArgumentOutOfRangeException&quot;&gt;if the address field</span>
    <span style="color: #008080; font-style: italic;">/// is not in a valid range&lt;/exception&gt;</span>
    <span style="color: #0600FF; font-weight: bold;">public</span> AddressFieldRule<span style="color: #008000;">&#40;</span>
        AddressField field,
        <span style="color: #6666cc; font-weight: bold;">bool</span> isRequired,
        <span style="color: #6666cc; font-weight: bold;">string</span> name,
        <span style="color: #6666cc; font-weight: bold;">string</span> description,
        <span style="color: #6666cc; font-weight: bold;">string</span> validationRegex,
        IEnumerable<span style="color: #008000;">&lt;</span>AddressFieldAllowedValue<span style="color: #008000;">&gt;</span> allowedValues<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #6666cc; font-weight: bold;">string</span><span style="color: #008000;">.</span><span style="color: #0000FF;">IsNullOrEmpty</span><span style="color: #008000;">&#40;</span>name<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0600FF; font-weight: bold;">throw</span> <span style="color: #008000;">new</span> ArgumentNullException<span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;name&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #008000;">!</span><span style="color: #6666cc; font-weight: bold;">Enum</span><span style="color: #008000;">.</span><span style="color: #0000FF;">IsDefined</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">typeof</span><span style="color: #008000;">&#40;</span>AddressField<span style="color: #008000;">&#41;</span>, field<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0600FF; font-weight: bold;">throw</span> <span style="color: #008000;">new</span> ArgumentOutOfRangeException<span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;field&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #008000;">!</span><span style="color: #6666cc; font-weight: bold;">string</span><span style="color: #008000;">.</span><span style="color: #0000FF;">IsNullOrEmpty</span><span style="color: #008000;">&#40;</span>validationRegex<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&amp;&amp;</span>
            allowedValues <span style="color: #008000;">!=</span> <span style="color: #0600FF; font-weight: bold;">null</span> <span style="color: #008000;">&amp;&amp;</span>
            allowedValues<span style="color: #008000;">.</span><span style="color: #0000FF;">Count</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0600FF; font-weight: bold;">throw</span> <span style="color: #008000;">new</span> ArgumentException<span style="color: #008000;">&#40;</span>
                <span style="color: #666666;">&quot;The ValidationRegex and the AllowedValues options are mutually exclusive.&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">field</span> <span style="color: #008000;">=</span> field<span style="color: #008000;">;</span>
        <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">description</span> <span style="color: #008000;">=</span> description<span style="color: #008000;">;</span>
        <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">isRequired</span> <span style="color: #008000;">=</span> isRequired<span style="color: #008000;">;</span>
        <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">name</span> <span style="color: #008000;">=</span> name<span style="color: #008000;">;</span>
        <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">allowedValues</span> <span style="color: #008000;">=</span> allowedValues <span style="color: #008000;">??</span> <span style="color: #008000;">new</span> List<span style="color: #008000;">&lt;</span>AddressFieldAllowedValue<span style="color: #008000;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">validationRegex</span> <span style="color: #008000;">=</span> validationRegex<span style="color: #008000;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span>
    <span style="color: #008080; font-style: italic;">/// Initializes a new instance of the &lt;see cref=&quot;AddressFieldRule&quot;/&gt; class.</span>
    <span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span>
    <span style="color: #0600FF; font-weight: bold;">protected</span> AddressFieldRule<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span>
    <span style="color: #008080; font-style: italic;">/// Gets values that, if not empty, then the address field value </span>
    <span style="color: #008080; font-style: italic;">/// should be one of the membersin the First property of each of these </span>
    <span style="color: #008080; font-style: italic;">/// Pairs. The Second property, if</span>
    <span style="color: #008080; font-style: italic;">/// set, is an alternative name that could be displayed in a dropdown to</span>
    <span style="color: #008080; font-style: italic;">/// the user.</span>
    <span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span>
    <span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #0600FF; font-weight: bold;">virtual</span> IEnumerable<span style="color: #008000;">&lt;</span>AddressFieldAllowedValue<span style="color: #008000;">&gt;</span> AllowedValues
    <span style="color: #008000;">&#123;</span>
        get
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0600FF; font-weight: bold;">return</span> <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">allowedValues</span><span style="color: #008000;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF; font-weight: bold;">private</span> set
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">allowedValues</span> <span style="color: #008000;">=</span> value<span style="color: #008000;">;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span>
    <span style="color: #008080; font-style: italic;">/// Gets a human-readable string that describes the required format for the</span>
    <span style="color: #008080; font-style: italic;">/// field. It may give an example, such as &quot;JYX 938&quot;.</span>
    <span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span>
    <span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #0600FF; font-weight: bold;">virtual</span> <span style="color: #6666cc; font-weight: bold;">string</span> Description
    <span style="color: #008000;">&#123;</span>
        get <span style="color: #008000;">&#123;</span> <span style="color: #0600FF; font-weight: bold;">return</span> <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">description</span><span style="color: #008000;">;</span> <span style="color: #008000;">&#125;</span>
        <span style="color: #0600FF; font-weight: bold;">private</span> set <span style="color: #008000;">&#123;</span> <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">description</span> <span style="color: #008000;">=</span> value<span style="color: #008000;">;</span> <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span>
    <span style="color: #008080; font-style: italic;">/// Gets the field that this metadata describes.</span>
    <span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span>
    <span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #0600FF; font-weight: bold;">virtual</span> AddressField Field
    <span style="color: #008000;">&#123;</span>
        get <span style="color: #008000;">&#123;</span> <span style="color: #0600FF; font-weight: bold;">return</span> <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">field</span><span style="color: #008000;">;</span> <span style="color: #008000;">&#125;</span>
        <span style="color: #0600FF; font-weight: bold;">private</span> set <span style="color: #008000;">&#123;</span> <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">field</span> <span style="color: #008000;">=</span> value<span style="color: #008000;">;</span> <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span>
    <span style="color: #008080; font-style: italic;">/// Gets a value indicating whether or not the field must be </span>
    <span style="color: #008080; font-style: italic;">/// included in the address.</span>
    <span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span>
    <span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #0600FF; font-weight: bold;">virtual</span> <span style="color: #6666cc; font-weight: bold;">bool</span> IsRequired
    <span style="color: #008000;">&#123;</span>
        get
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0600FF; font-weight: bold;">return</span> <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">isRequired</span><span style="color: #008000;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF; font-weight: bold;">private</span> set
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">isRequired</span> <span style="color: #008000;">=</span> value<span style="color: #008000;">;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span>
    <span style="color: #008080; font-style: italic;">/// Gets an English, localized name for the field. For example, the</span>
    <span style="color: #008080; font-style: italic;">/// StateOrProvince field has a name of &quot;Province or Territory&quot; for</span>
    <span style="color: #008080; font-style: italic;">/// Canadian addresses.</span>
    <span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span>
    <span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #0600FF; font-weight: bold;">virtual</span> <span style="color: #6666cc; font-weight: bold;">string</span> Name
    <span style="color: #008000;">&#123;</span>
        get <span style="color: #008000;">&#123;</span> <span style="color: #0600FF; font-weight: bold;">return</span> <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">name</span><span style="color: #008000;">;</span> <span style="color: #008000;">&#125;</span>
        <span style="color: #0600FF; font-weight: bold;">private</span> set <span style="color: #008000;">&#123;</span> <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">name</span> <span style="color: #008000;">=</span> value<span style="color: #008000;">;</span> <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span>
    <span style="color: #008080; font-style: italic;">/// Gets an optional validation regular expression template, which may</span>
    <span style="color: #008080; font-style: italic;">/// be null.</span>
    <span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span>
    <span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #0600FF; font-weight: bold;">virtual</span> <span style="color: #6666cc; font-weight: bold;">string</span> ValidationRegex
    <span style="color: #008000;">&#123;</span>
        get
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0600FF; font-weight: bold;">return</span> <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">validationRegex</span><span style="color: #008000;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF; font-weight: bold;">private</span> set
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">validationRegex</span> <span style="color: #008000;">=</span> value<span style="color: #008000;">;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span>
    <span style="color: #008080; font-style: italic;">/// Gets or sets the data store identifier for the rule.</span>
    <span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span>
    <span style="color: #0600FF; font-weight: bold;">private</span> <span style="color: #6666cc; font-weight: bold;">int</span><span style="color: #008000;">?</span> Identity
    <span style="color: #008000;">&#123;</span>
        get<span style="color: #008000;">;</span>
        set<span style="color: #008000;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span>
    <span style="color: #008080; font-style: italic;">/// Validates the value.</span>
    <span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span>
    <span style="color: #008080; font-style: italic;">/// &lt;param name=&quot;value&quot;&gt;The value to validate.&lt;/param&gt;</span>
    <span style="color: #008080; font-style: italic;">/// &lt;returns&gt;The validation result.&lt;/returns&gt;</span>
    <span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #0600FF; font-weight: bold;">virtual</span> AddressFieldRuleValidationResult Validate<span style="color: #008000;">&#40;</span><span style="color: #6666cc; font-weight: bold;">string</span> value<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>value <span style="color: #008000;">==</span> <span style="color: #0600FF; font-weight: bold;">null</span> <span style="color: #008000;">||</span> value<span style="color: #008000;">.</span><span style="color: #0000FF;">Trim</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Length</span> <span style="color: #008000;">==</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&amp;&amp;</span> <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">IsRequired</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            var message <span style="color: #008000;">=</span> <span style="color: #6666cc; font-weight: bold;">string</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Format</span><span style="color: #008000;">&#40;</span>
                CultureInfo<span style="color: #008000;">.</span><span style="color: #0000FF;">CurrentCulture</span>,
                <span style="color: #666666;">&quot;The field '{0}' is required, but the value was empty or blank.&quot;</span>,
                <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Name</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF; font-weight: bold;">return</span> <span style="color: #008000;">new</span> AddressFieldRuleValidationResult<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
            <span style="color: #008000;">&#123;</span>
                Field <span style="color: #008000;">=</span> <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Field</span>,
                Original <span style="color: #008000;">=</span> value,
                Message <span style="color: #008000;">=</span> message
            <span style="color: #008000;">&#125;</span><span style="color: #008000;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span>value <span style="color: #008000;">!=</span> <span style="color: #0600FF; font-weight: bold;">null</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            var input <span style="color: #008000;">=</span> value<span style="color: #008000;">.</span><span style="color: #0000FF;">Trim</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span>input<span style="color: #008000;">.</span><span style="color: #0000FF;">Length</span> <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">&#41;</span>
            <span style="color: #008000;">&#123;</span>
                <span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #008000;">!</span><span style="color: #6666cc; font-weight: bold;">string</span><span style="color: #008000;">.</span><span style="color: #0000FF;">IsNullOrEmpty</span><span style="color: #008000;">&#40;</span><span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">ValidationRegex</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&amp;&amp;</span>
                    <span style="color: #008000;">!</span>Regex<span style="color: #008000;">.</span><span style="color: #0000FF;">IsMatch</span><span style="color: #008000;">&#40;</span>input, <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">ValidationRegex</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
                <span style="color: #008000;">&#123;</span>
                    var message <span style="color: #008000;">=</span> <span style="color: #6666cc; font-weight: bold;">string</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Format</span><span style="color: #008000;">&#40;</span>
                        CultureInfo<span style="color: #008000;">.</span><span style="color: #0000FF;">CurrentCulture</span>,
                        <span style="color: #666666;">&quot;The field '{0}' has an unexpected or incorrectly formatted value.&quot;</span>,
                        <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Name</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
                    <span style="color: #0600FF; font-weight: bold;">return</span> <span style="color: #008000;">new</span> AddressFieldRuleValidationResult<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
                    <span style="color: #008000;">&#123;</span>
                        Field <span style="color: #008000;">=</span> <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Field</span>,
                        Original <span style="color: #008000;">=</span> value,
                        Message <span style="color: #008000;">=</span> message
                    <span style="color: #008000;">&#125;</span><span style="color: #008000;">;</span>
                <span style="color: #008000;">&#125;</span>
&nbsp;
                <span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">AllowedValues</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Count</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">&#41;</span>
                <span style="color: #008000;">&#123;</span>
                    <span style="color: #6666cc; font-weight: bold;">string</span> preferred<span style="color: #008000;">;</span>
&nbsp;
                    <span style="color: #008080; font-style: italic;">// If an alternative value is detected, select the preferred.</span>
                    var alternativeAllowedValue <span style="color: #008000;">=</span>
                        <span style="color: #008000;">&#40;</span><span style="color: #0600FF; font-weight: bold;">from</span> av <span style="color: #0600FF; font-weight: bold;">in</span> <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">AllowedValues</span>
                            <span style="color: #0600FF; font-weight: bold;">where</span> <span style="color: #008000;">!</span><span style="color: #6666cc; font-weight: bold;">string</span><span style="color: #008000;">.</span><span style="color: #0000FF;">IsNullOrEmpty</span><span style="color: #008000;">&#40;</span>av<span style="color: #008000;">.</span><span style="color: #0000FF;">Alternative</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&amp;&amp;</span>
                            av<span style="color: #008000;">.</span><span style="color: #0000FF;">Alternative</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Equals</span><span style="color: #008000;">&#40;</span>input, StringComparison<span style="color: #008000;">.</span><span style="color: #0000FF;">OrdinalIgnoreCase</span><span style="color: #008000;">&#41;</span>
                            <span style="color: #0600FF; font-weight: bold;">select</span> av<span style="color: #008000;">&#41;</span><span style="color: #008000;">.</span><span style="color: #0000FF;">SingleOrDefault</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
                    <span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span>alternativeAllowedValue <span style="color: #008000;">!=</span> <span style="color: #0600FF; font-weight: bold;">null</span><span style="color: #008000;">&#41;</span>
                    <span style="color: #008000;">&#123;</span>
                        <span style="color: #008080; font-style: italic;">// We matched an alternative value, so let's use the</span>
                        <span style="color: #008080; font-style: italic;">// corresponding primary value</span>
                        preferred <span style="color: #008000;">=</span> alternativeAllowedValue<span style="color: #008000;">.</span><span style="color: #0000FF;">Preferred</span><span style="color: #008000;">;</span>
&nbsp;
                        <span style="color: #0600FF; font-weight: bold;">return</span> <span style="color: #008000;">new</span> AddressFieldRuleValidationResult<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
                        <span style="color: #008000;">&#123;</span>
                            Field <span style="color: #008000;">=</span> <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Field</span>,
                            Original <span style="color: #008000;">=</span> value,
                            Preferred <span style="color: #008000;">=</span> preferred,
                            Success <span style="color: #008000;">=</span> <span style="color: #0600FF; font-weight: bold;">true</span>
                        <span style="color: #008000;">&#125;</span><span style="color: #008000;">;</span>
                    <span style="color: #008000;">&#125;</span>
                    <span style="color: #0600FF; font-weight: bold;">else</span>
                    <span style="color: #008000;">&#123;</span>
                        <span style="color: #008080; font-style: italic;">// Search on the primary value, then.</span>
                        var primaryAllowedValue <span style="color: #008000;">=</span>
                            <span style="color: #008000;">&#40;</span><span style="color: #0600FF; font-weight: bold;">from</span> av <span style="color: #0600FF; font-weight: bold;">in</span> <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">AllowedValues</span>
                                <span style="color: #0600FF; font-weight: bold;">where</span> av<span style="color: #008000;">.</span><span style="color: #0000FF;">Preferred</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Equals</span><span style="color: #008000;">&#40;</span>input, StringComparison<span style="color: #008000;">.</span><span style="color: #0000FF;">OrdinalIgnoreCase</span><span style="color: #008000;">&#41;</span>
                                <span style="color: #0600FF; font-weight: bold;">select</span> av<span style="color: #008000;">&#41;</span><span style="color: #008000;">.</span><span style="color: #0000FF;">SingleOrDefault</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
                        <span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span>primaryAllowedValue <span style="color: #008000;">!=</span> <span style="color: #0600FF; font-weight: bold;">null</span><span style="color: #008000;">&#41;</span>
                        <span style="color: #008000;">&#123;</span>
                            <span style="color: #008080; font-style: italic;">// We matched the primary value, let's re-assign</span>
                            <span style="color: #008080; font-style: italic;">// it to get the correct casing</span>
                            preferred <span style="color: #008000;">=</span> primaryAllowedValue<span style="color: #008000;">.</span><span style="color: #0000FF;">Preferred</span><span style="color: #008000;">;</span>
&nbsp;
                            <span style="color: #0600FF; font-weight: bold;">return</span> <span style="color: #008000;">new</span> AddressFieldRuleValidationResult<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
                            <span style="color: #008000;">&#123;</span>
                                Field <span style="color: #008000;">=</span> <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Field</span>,
                                Original <span style="color: #008000;">=</span> value,
                                Preferred <span style="color: #008000;">=</span> preferred,
                                Success <span style="color: #008000;">=</span> <span style="color: #0600FF; font-weight: bold;">true</span>
                            <span style="color: #008000;">&#125;</span><span style="color: #008000;">;</span>
                        <span style="color: #008000;">&#125;</span>
                        <span style="color: #0600FF; font-weight: bold;">else</span>
                        <span style="color: #008000;">&#123;</span>
                            var message <span style="color: #008000;">=</span> <span style="color: #6666cc; font-weight: bold;">string</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Format</span><span style="color: #008000;">&#40;</span>
                                CultureInfo<span style="color: #008000;">.</span><span style="color: #0000FF;">CurrentCulture</span>,
                                <span style="color: #666666;">&quot;The field '{0}' was not in the list of expected values.&quot;</span>,
                                <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Name</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
                            <span style="color: #0600FF; font-weight: bold;">return</span> <span style="color: #008000;">new</span> AddressFieldRuleValidationResult<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
                            <span style="color: #008000;">&#123;</span>
                                Field <span style="color: #008000;">=</span> <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Field</span>,
                                Original <span style="color: #008000;">=</span> value,
                                Message <span style="color: #008000;">=</span> message
                            <span style="color: #008000;">&#125;</span><span style="color: #008000;">;</span>
                        <span style="color: #008000;">&#125;</span>
                    <span style="color: #008000;">&#125;</span>
                <span style="color: #008000;">&#125;</span>
            <span style="color: #008000;">&#125;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF; font-weight: bold;">return</span> <span style="color: #008000;">new</span> AddressFieldRuleValidationResult<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            Field <span style="color: #008000;">=</span> <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Field</span>,
            Original <span style="color: #008000;">=</span> value,
            Preferred <span style="color: #008000;">=</span> value,
            Success <span style="color: #008000;">=</span> <span style="color: #0600FF; font-weight: bold;">true</span>
        <span style="color: #008000;">&#125;</span><span style="color: #008000;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>


<p>(In the case of a state or province field, where we ensure that the value belongs to a predefined list of <code>AddressFieldAllowedValue</code>s, we also let the rule tell the consumer which value is &#8220;preferred.&#8221; For example, a user might enter &#8220;Virginia&#8221;, but the system will spit back &#8220;VA&#8221; as the preferred formatting for that value.)</p>

<p>As a result, that <code>Validate()</code> method on the builder doesn&#8217;t have to do much heavy lifting:</p>


<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF; font-weight: bold;">public</span> IEnumerable<span style="color: #008000;">&lt;</span>AddressFieldRuleValidationResult<span style="color: #008000;">&gt;</span> Validate<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    var failures <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> List<span style="color: #008000;">&lt;</span>AddressFieldRuleValidationResult<span style="color: #008000;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">address</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Country</span> <span style="color: #008000;">==</span> <span style="color: #0600FF; font-weight: bold;">null</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        var result <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> AddressFieldRuleValidationResult<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            Field <span style="color: #008000;">=</span> AddressField<span style="color: #008000;">.</span><span style="color: #0000FF;">Country</span>,
            Message <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;The country is required.&quot;</span>
        <span style="color: #008000;">&#125;</span><span style="color: #008000;">;</span>
&nbsp;
        failures<span style="color: #008000;">.</span><span style="color: #0000FF;">Add</span><span style="color: #008000;">&#40;</span>result<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0600FF; font-weight: bold;">else</span> <span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">address</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Country</span><span style="color: #008000;">.</span><span style="color: #0000FF;">AddressScheme</span> <span style="color: #008000;">==</span> <span style="color: #0600FF; font-weight: bold;">null</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        var result <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> AddressFieldRuleValidationResult<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            Field <span style="color: #008000;">=</span> AddressField<span style="color: #008000;">.</span><span style="color: #0000FF;">Country</span>,
            Message <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;The country must have an address scheme.&quot;</span>
        <span style="color: #008000;">&#125;</span><span style="color: #008000;">;</span>
&nbsp;
        failures<span style="color: #008000;">.</span><span style="color: #0000FF;">Add</span><span style="color: #008000;">&#40;</span>result<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0600FF; font-weight: bold;">else</span>
    <span style="color: #008000;">&#123;</span>
        var scheme <span style="color: #008000;">=</span> <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">address</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Country</span><span style="color: #008000;">.</span><span style="color: #0000FF;">AddressScheme</span><span style="color: #008000;">;</span>
&nbsp;
        <span style="color: #0600FF; font-weight: bold;">foreach</span> <span style="color: #008000;">&#40;</span>AddressField field <span style="color: #0600FF; font-weight: bold;">in</span> <span style="color: #008000;">new</span> ArrayList<span style="color: #008000;">&#40;</span><span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">address</span><span style="color: #008000;">.</span><span style="color: #0000FF;">fields</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Keys</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span>field <span style="color: #008000;">!=</span> AddressField<span style="color: #008000;">.</span><span style="color: #0000FF;">Country</span> <span style="color: #008000;">&amp;&amp;</span>
                field <span style="color: #008000;">!=</span> AddressField<span style="color: #008000;">.</span><span style="color: #0000FF;">Unknown</span><span style="color: #008000;">&#41;</span>
            <span style="color: #008000;">&#123;</span>
                <span style="color: #008080; font-style: italic;">// If the field is not Country or Unknown, let's</span>
                <span style="color: #008080; font-style: italic;">// see if the scheme has a rule defined for it.</span>
                <span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span>scheme<span style="color: #008000;">.</span><span style="color: #0000FF;">HasRuleFor</span><span style="color: #008000;">&#40;</span>field<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
                <span style="color: #008000;">&#123;</span>
                    <span style="color: #008080; font-style: italic;">// Since a rule is defined, let's validate the field.</span>
                    var result <span style="color: #008000;">=</span> scheme<span style="color: #008000;">.</span><span style="color: #0000FF;">ValidateField</span><span style="color: #008000;">&#40;</span>field, <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">address</span><span style="color: #008000;">&#91;</span>field<span style="color: #008000;">&#93;</span> <span style="color: #0600FF; font-weight: bold;">as</span> <span style="color: #6666cc; font-weight: bold;">string</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
                    <span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span>result<span style="color: #008000;">.</span><span style="color: #0000FF;">Success</span><span style="color: #008000;">&#41;</span>
                    <span style="color: #008000;">&#123;</span>
                        <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">address</span><span style="color: #008000;">&#91;</span>field<span style="color: #008000;">&#93;</span> <span style="color: #008000;">=</span> result<span style="color: #008000;">.</span><span style="color: #0000FF;">Preferred</span><span style="color: #008000;">;</span>
                    <span style="color: #008000;">&#125;</span>
                    <span style="color: #0600FF; font-weight: bold;">else</span>
                    <span style="color: #008000;">&#123;</span>
                        failures<span style="color: #008000;">.</span><span style="color: #0000FF;">Add</span><span style="color: #008000;">&#40;</span>result<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
                    <span style="color: #008000;">&#125;</span>
                <span style="color: #008000;">&#125;</span>
                <span style="color: #0600FF; font-weight: bold;">else</span>
                <span style="color: #008000;">&#123;</span>
                    <span style="color: #008080; font-style: italic;">// No rule is defined, so strip the data out of the</span>
                    <span style="color: #008080; font-style: italic;">// address.</span>
                    <span style="color: #0600FF; font-weight: bold;">this</span><span style="color: #008000;">.</span><span style="color: #0000FF;">address</span><span style="color: #008000;">&#91;</span>field<span style="color: #008000;">&#93;</span> <span style="color: #008000;">=</span> <span style="color: #0600FF; font-weight: bold;">null</span><span style="color: #008000;">;</span>
                <span style="color: #008000;">&#125;</span>
            <span style="color: #008000;">&#125;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0600FF; font-weight: bold;">return</span> failures<span style="color: #008000;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>


<p>Where do all of these address rules come from? There is nothing more valuable than <a href="http://www.columbia.edu/kermit/postal.html">Frank&#8217;s Compulsive Guide to Postal Addresses</a>.</p>

<h2>Formatting</h2>

<p>Another important property on the <code>AddressScheme</code> is the <code>Formatter</code>. This is an object that knows how to format an address for a particular country. The <code>ToString()</code> implementation on the <code>Address</code> can then just call <code>this.Country.Formatter.Format("M", this)</code> to get a string back that contains the correctly formatted address, where &#8220;M&#8221; is our <code>IFormattable</code> code for an address format that includes newlines.</p>

<p>My <code>AddressFormatter</code> object works by taking a template string that is loaded from the database. The template format is pretty simple: it&#8217;s a combination of the <code>AddressField</code> enumerated values (delimited by braces) and the semicolon (which indicates separate lines of the address). For example, the template for a German address is specified as:</p>

<p><pre>{PrimaryStreetLine};{SecondaryStreetLine};DE-{PostalCode}  {Municipality};{Country}</pre></p>

<p>Given an &#8220;S&#8221; format code (for &#8220;single-line output&#8221;), we&#8217;ll substitute the values and leave the semicolons. Given an &#8220;M&#8221; format code (for &#8220;mailing output&#8221;), we&#8217;ll substitute the values and swap the semicolons with newlines. We also remove any contiguous separators that might happen, such as when the <code>SecondaryStreetLine</code> is blank, to avoid having a blank line in the address.</p>

<p>So given an address that was built as</p>


<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">var country <span style="color: #008000;">=</span> CountryMother<span style="color: #008000;">.</span><span style="color: #0000FF;">Germany</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #0600FF; font-weight: bold;">return</span> <span style="color: #008000;">new</span> Address<span style="color: #008000;">.</span><span style="color: #0000FF;">Builder</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">.</span><span style="color: #0000FF;">WithPrimaryStreetLine</span><span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;42 Kaiserstrasse&quot;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">.</span><span style="color: #0000FF;">WithMunicipality</span><span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;Berlin&quot;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">.</span><span style="color: #0000FF;">WithPostalCode</span><span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;12345&quot;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">.</span><span style="color: #0000FF;">WithCountry</span><span style="color: #008000;">&#40;</span>country<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">.</span><span style="color: #0000FF;">Build</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span></pre></div></div>


<p>our formatter, given a format code of &#8220;M&#8221;, will spit out</p>

<p><pre>
42 Kaiserstrasse
DE-12345 Berlin
Germany
</pre></p>

<p>Since the address object is immutable, we know it&#8217;s valid, so the formatter doesn&#8217;t have to worry about handling a potentially invalid address object.</p>

<p>The user interface of the Web site also uses the template to figure what input fields to display and what order to display them in.</p>

<h2>Determining address kind</h2>

<p>When shipping, it&#8217;s often important to know the &#8220;kind&#8221; of an address, as in the following enumeration demonstrates:</p>


<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">enum</span> AddressKind <span style="color: #008000;">:</span> <span style="color: #6666cc; font-weight: bold;">int</span>
<span style="color: #008000;">&#123;</span>
    Unknown <span style="color: #008000;">=</span> <span style="color: #FF0000;">0</span>,
    Commercial <span style="color: #008000;">=</span> <span style="color: #FF0000;">1</span>,
    PostOfficeBox <span style="color: #008000;">=</span> <span style="color: #FF0000;">2</span>,
    Residential <span style="color: #008000;">=</span> <span style="color: #FF0000;">3</span>,
    Military <span style="color: #008000;">=</span> <span style="color: #FF0000;">4</span>
<span style="color: #008000;">&#125;</span></pre></div></div>


<p>Why is this important? For example, you can only use USPS to ship to a PO box or a military (APO/FPO/DPO) address, and you can&#8217;t use FedEx Home Service on a commercial address.</p>

<p>One mistake that I made over the years was trying to store the <code>AddressKind</code> right in the <code>Address</code> object. This was a mistake for a few reasons:</p>

<ul>
<li>I don&#8217;t always care about the address kind, such as for an international address, so having it appear on every <code>Address</code> instance is wasteful.</li>
<li>Computing the address kind can be expensive. While figuring out a PO box or a military address just involves scanning the address fields, determining commercial or residential status means calling a Web service supplied by FedEx, which can take seconds to complete. By having the <code>Kind</code> property on the address, I&#8217;m left with a bad situation: I can either keep the immutability of my address object by determining the address kind for <em>every</em> address when I instantiate them, or I can break immutability, which negates the advantage of not having to worry about change tracking on these objects.</li>
</ul>

<p>As a result, our new Web site simply doesn&#8217;t store the address kind at all. The kind, if needed, is determined on the fly by calling the <code>DetermineAddressKind()</code> method of an <code>IAddressKindDeterminer</code> instance.</p>

<h2>Being flexible: Legacy data and third-party integration points</h2>

<p>Finally, there&#8217;s one last point to be made. This new address validation and formatting is great and all, but there are two potential problems:</p>

<ul>
<li>There is 10 years of less-than-satisfactory address data already in the database, and it could be in an &#8220;invalid&#8221; format according to these new guidelines. Obviously, we want to maintain backward compatibility here, as we don&#8217;t want to force our customers to re-type their address data, and we don&#8217;t want to blow up when simply trying to load the address from the database.</li>
<li>Addresses sometimes get force-fed to the system via third-party integrations such as PayPal Express Checkout or Google Checkout. I can&#8217;t really reject addresses coming from these sources, so I have to be able to &#8220;take it like it is,&#8221; even if it means it doesn&#8217;t quite adhere to my preferred format.</li>
</ul>

<p>As a result, the new address system has to be able to grandfather in old addresses and graciously accept other addresses from integration. For accepting addresses from integration, I simply added an overload to the address builder&#8217;s <code>Build()</code> method that does not perform any validation&#8211;and trust myself only to use that overload in the proper scenarios.</p>

<p>For handling legacy address data, I simply let NHibernate set the address fields directly when loading objects from the database. That is, since the address isn&#8217;t constructed via the address builder but is instead built up via reflection, no validation is run on the legacy address and so the legacy address will still load.</p>

<p>One advantage of this model comes from the <code>Address</code> object&#8217;s immutability. Since the address can&#8217;t be changed, if the user wishes to edit an old address, they&#8217;ll be forced to bring the whole address up to snuff since a new <code>Address</code> instance will need to be created.</p>

<h2>Conclusions and delusions</h2>

<p>At the end of the day, we&#8217;re left with a robust implementation of address storage and address validation:</p>

<p><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/11/11-24-2010-10-41-55-AM.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/11/11-24-2010-10-41-55-AM.png" alt="" title="Source Fields" width="356" height="573" class="aligncenter size-full wp-image-751" /></a></p>

<p>International address validation, input, and handling has never been better at Skiviez, and for the first time in years, I feel like it&#8217;s finally under control&#8211;thanks to a clean object design, immutability, and a few days of thinking really hard about the problem. I hope this post gives someone some insight on their own project out there. Good luck!</p>
]]></content:encoded>
			<wfw:commentRss>http://nicholas.piasecki.name/blog/2010/11/inside-skiviez-mailing-addresses/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Inside Skiviez: Catalog Listings and Search Queries</title>
		<link>http://nicholas.piasecki.name/blog/2010/10/inside-skiviez-catalog-listings-and-search-queries/</link>
		<comments>http://nicholas.piasecki.name/blog/2010/10/inside-skiviez-catalog-listings-and-search-queries/#comments</comments>
		<pubDate>Sun, 10 Oct 2010 16:09:30 +0000</pubDate>
		<dc:creator>Nicholas Piasecki</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[skiviez]]></category>
		<category><![CDATA[web stuff]]></category>

		<guid isPermaLink="false">http://nicholas.piasecki.name/blog/?p=648</guid>
		<description><![CDATA[Last Tuesday, I rolled out a new release of the Skiviez Web site. It is the most significant technical change at Skiviez since 2007 and brings with it a lot of improvements in how it operates against our company&#8217;s 10-year-old database. One of these new features is a fast, faceted product catalog. Faceting is the [...]]]></description>
			<content:encoded><![CDATA[<p>Last Tuesday, I rolled out a new release of the <a href="http://www.skiviez.com/">Skiviez Web site</a>. It is the most significant technical change at Skiviez since 2007 and brings with it a lot of improvements in how it operates against our company&#8217;s 10-year-old database.</p>

<p><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/10/10-10-2010-9-56-40-AM.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/10/10-10-2010-9-56-40-AM.png" alt="" title="Facets" width="208" height="432" class="alignleft size-full wp-image-649" /></a></p>

<p>One of these new features is a fast, <a href="http://www.lucidimagination.com/Community/Hear-from-the-Experts/Articles/Faceted-Search-Solr">faceted</a> product catalog. Faceting is the technical name for something you&#8217;ve seen in many e-commerce stores like NewEgg, Zappo&#8217;s, and Lowe&#8217;s: a list of links that quickly allow you to drill down to the content that you&#8217;d like to see.</p>

<p>Trying to do this kind of thing efficiently in a traditional relational database is not going to happen unless you want to start adding and removing indexes on the fly or go full on <a href="http://en.wikipedia.org/wiki/Entity-attribute-value_model">Entity-Attribute-Value</a>, which somewhat defeats the purpose of using a relational database. You lose efficient indexing, you lose type information, you lose, well, the relations.</p>

<p>Instead, Skiviez now uses <a href="http://lucene.apache.org/solr/">Solr</a>&#8211;an open source search platform that is based on <a href="http://lucene.apache.org/java/docs/index.html">Lucene</a>, a text search engine library&#8211;for managing catalog listing pages and search pages.</p>

<h2>Solr from 10,000 feet</h2>

<p>Solr is not relational. It doesn&#8217;t have tables. The schema is flat; all &#8220;documents&#8221; in the Solr store share the same schema. From a relational perspective, you could think of it as one table with many columns, except that not every row in the table uses all of the columns. (This isn&#8217;t how it internally works at all, but it&#8217;s a useful metaphor.)</p>

<p>Some fields are &#8220;stored,&#8221; which means you can get back the data that you put in. Some fields are &#8220;indexed,&#8221; which means that you can query on them directly and use them for faceting. And some fields are &#8220;multivalued&#8221;, which means that they can hold more than one value at a time. For example, our <code>&lt;sizeInStock&gt;</code> field can hold <code>S</code>, <code>M</code>, and <code>L</code> values all at once for a particular product, and just <code>L</code> for another.</p>

<p>Why would you ever want a value to not be &#8220;stored&#8221;? Why add data that you can&#8217;t get back? Well, in Solr, storing and indexing are distinct concepts, so you can a value that is not stored, just indexed. A good example from the Skiviez Solr schema would be the <code>salesVolume</code> field, which indicates how many units of a particular item were sold in the past week:</p>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;field</span></span>
<span style="color: #009900;">			<span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;salesVolume&quot;</span></span>
<span style="color: #009900;">			<span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;sint&quot;</span></span>
<span style="color: #009900;">			<span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span></span>
<span style="color: #009900;">			<span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;false&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span></pre></div></div>


<p>This is just an integer, a number of units sold. In my UI, I&#8217;m not going to ever actually display that number&#8211;that would reveal a little too much information about our business. But I still want our users to be able to sort catalog listings by &#8220;Top Selling&#8221; products. By creating an index, we enable sorting; by disallowing storage, we save some space.</p>

<p>The Skiviez Solr schema defines a &#8220;type&#8221; field, some fields that are shared among all document types, and a few type-specific fields. This works well because the only intended use of Solr is catalog listings and searching; if I had to store more disparate kinds of data, I might create several Solr schemas.</p>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">&lt;!--</span>
<span style="color: #808080; font-style: italic;">	This field is used to indicate the type of data that is stored within</span>
<span style="color: #808080; font-style: italic;">	the document. Since the Skiviez Solr instance represents a variety of</span>
<span style="color: #808080; font-style: italic;">	different types, this field helps to indicate what kind of data you are </span>
<span style="color: #808080; font-style: italic;">	looking at.</span>
&nbsp;
<span style="color: #808080; font-style: italic;">	Types that are currently understood the Web site include:</span>
&nbsp;
<span style="color: #808080; font-style: italic;">		BLOGARTICLE</span>
<span style="color: #808080; font-style: italic;">		BRAND</span>
<span style="color: #808080; font-style: italic;">		LINE</span>
<span style="color: #808080; font-style: italic;">		PRODUCT</span>
<span style="color: #808080; font-style: italic;">		PRODUCTSUMMARY</span>
<span style="color: #808080; font-style: italic;">                PROMOTION</span>
<span style="color: #808080; font-style: italic;">		STYLE</span>
<span style="color: #808080; font-style: italic;">		WEBPAGE</span>
<span style="color: #808080; font-style: italic;">--&gt;</span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;field</span></span>
<span style="color: #009900;">	<span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;type&quot;</span></span>
<span style="color: #009900;">	<span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;string&quot;</span></span>
<span style="color: #009900;">	<span style="color: #000066;">indexed</span>=<span style="color: #ff0000;">&quot;true&quot;</span></span>
<span style="color: #009900;">	<span style="color: #000066;">stored</span>=<span style="color: #ff0000;">&quot;true&quot;</span></span>
<span style="color: #009900;">	<span style="color: #000066;">required</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span></pre></div></div>


<p>Why is this useful? Well, the search portion of the Skiviez Web site can use the <code>&lt;type&gt;</code> field and the fields that are used by all of the different document types to quickly search a wide variety of sources:</p>

<p><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/10/10-10-2010-11-45-05-AM.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/10/10-10-2010-11-45-05-AM.png" alt="" title="A wide variety of sources" class="aligncenter size-full wp-image-684" /></a></p>

<p>In this case, we&#8217;re looking at our <code>&lt;type&gt;</code>, <code>&lt;urlKey&gt;</code>, <code>&lt;name&gt;</code>, and <code>&lt;image&gt;</code> fields. The Web site can use this to quickly sort information and build links to content.</p>

<p>The <code>PRODUCT</code> type uses a wealth of product-specific fields, however, and when we query to display catalog pages, we tell Solr to only return documents of type <code>PRODUCT</code>. I could have created a second Solr schema for this purpose, but why bother?</p>

<h2>Getting data into Solr</h2>

<p>The traditional SQL database is still the &#8220;authoritative&#8221; data store, and the Solr indexes are read-only snapshots of that data. This means that the data coming from Solr is always slightly stale, so I had to ask myself:</p>

<ul>
<li>How stale is too stale?</li>
<li>When do I value speed or querying over staleness?</li>
</ul>

<p>Part of the new Skiviez Web site is a Windows service that I call the &#8220;Worker.&#8221; It uses <a href="http://quartznet.sourceforge.net/">Quartz.NET</a> to execute C# <code>IJob</code> implementations periodically. You can think of them as traditional scheduled tasks in Windows; the only difference is that I am explicitly managing them in code, using the same object-oriented model of our domain in those jobs, and, as long as the service is installed, I don&#8217;t need to worry about configuring scheduled tasks.</p>

<p>Every three hours, one of those <code>IJob</code>s that gets executed is the <code>RefreshSolrIndexesJob</code>, and all that job does is ping an <code>HttpWebRequest</code> over to <code>http://solr.example.com/dataimport?command=full-import</code>, where <code>solr.example.com</code> is placed with the FQDN of our internal Solr server. This is because I use Solr&#8217;s built-in <a href="http://wiki.apache.org/solr/DataImportHandler"><code>DataImportHandler</code></a> to actually suck in the data from the SQL database; the job just has to &#8220;touch&#8221; that URL periodically to make the sync work. Because the <code>DataImportHandler</code> commits the changes periodically, this is all effectively running in the background, transparent to the users of the Web site. And because the Skiviez product catalog is reasonably small (a few thousand items), we can blow away the whole Solr index and re-build it in fewer than two minutes.</p>

<p>There&#8217;s also a function in our backend application that allows employees to trigger the index rebuilding immediately; this can happen when new product arrives in the warehouse and we want to get it up on the Web site right away.</p>

<p><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/10/10-10-2010-11-18-03-AM.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/10/10-10-2010-11-18-03-AM.png" alt="" title="Manual Rebuild Function" class="aligncenter size-full wp-image-676" /></a></p>

<p>The <code>DataImportHandler</code> is built into Solr, and configuring it is a little confusing because it uses some strange terminology. It just takes an XML configuration file, and whenever you ping its request handler, it performs synchronization tasks based on what has been specified in its configuration.</p>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;entity</span></span>
<span style="color: #009900;">        <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;brands&quot;</span></span>
<span style="color: #009900;">        <span style="color: #000066;">dataSource</span>=<span style="color: #ff0000;">&quot;undiesDatabase&quot;</span></span>
<span style="color: #009900;">        <span style="color: #000066;">transformer</span>=<span style="color: #ff0000;">&quot;TemplateTransformer&quot;</span></span>
<span style="color: #009900;">        <span style="color: #000066;">query</span>=<span style="color: #ff0000;">&quot;</span>
<span style="color: #009900;">            SELECT</span>
<span style="color: #009900;">                b.ID AS BrandId,</span>
<span style="color: #009900;">                b.[Name] AS BrandName,</span>
<span style="color: #009900;">                b.Description AS BrandDescription,</span>
<span style="color: #009900;">                b.UrlKey AS BrandUrlKey,</span>
<span style="color: #009900;">                CASE b.Active</span>
<span style="color: #009900;">                  WHEN 'Y' THEN 'True'</span>
<span style="color: #009900;">                  ELSE 'False'</span>
<span style="color: #009900;">                END AS BrandIsActive</span>
<span style="color: #009900;">            FROM na.brands AS b</span>
<span style="color: #009900;">            ORDER BY b.[Name];&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;field</span> <span style="color: #000066;">column</span>=<span style="color: #ff0000;">&quot;id&quot;</span> <span style="color: #000066;">template</span>=<span style="color: #ff0000;">&quot;BRAND-${brands.BrandId}&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;field</span> <span style="color: #000066;">column</span>=<span style="color: #ff0000;">&quot;type&quot;</span> <span style="color: #000066;">template</span>=<span style="color: #ff0000;">&quot;BRAND&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;field</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;identity&quot;</span> <span style="color: #000066;">column</span>=<span style="color: #ff0000;">&quot;BrandId&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;field</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;name&quot;</span> <span style="color: #000066;">column</span>=<span style="color: #ff0000;">&quot;BrandName&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;field</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;description&quot;</span> <span style="color: #000066;">column</span>=<span style="color: #ff0000;">&quot;BrandDescription&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;field</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;isActive&quot;</span> <span style="color: #000066;">column</span>=<span style="color: #ff0000;">&quot;BrandIsActive&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;field</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;urlKey&quot;</span> <span style="color: #000066;">column</span>=<span style="color: #ff0000;">&quot;BrandUrlKey&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/entity<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>


<p>I say the terminology is confusing because in <code>&lt;field&gt;</code> elements, the @column attribute is the name of the Solr field and the name of the column in the SQL result set. But if the @name attribute is specified, then the @column attribute is the name of the column in the result set and the @name attribute is the name of the Solr field. It&#8217;s confusing because some <code>&lt;field&gt;</code> elements don&#8217;t pull directly from the result set, instead relying on a &#8220;transformer.&#8221; You would expect to just specify a @name for those fields, but specifying just @column is correct. In the above example, the &#8220;Template Transformer&#8221; is used on the <code>id</code> field to format Solr identities in the format of <code>BRAND-127</code>, where <code>127</code> is the SQL database&#8217;s primary key for the brand.</p>

<p>(And yes, attributes can have newlines in them. I&#8217;m not sure how I went through years of programming without realizing this, but once I realized that I could do it, it made reading those SQL queries much easier! This example is by far the shortest query for pulling Solr data from the SQL database; the one for products is over 200 lines long.)</p>

<h2>Querying data: how stale is too stale?</h2>

<p>This does mean that information in the Skiviez product catalog can be up to three hours stale. A user might click a link for &#8220;Medium In Stock (3)&#8221; on the catalog page (since this kind of faceted data is generated by querying Solr) but then see on the product detail page that no mediums are in stock (since on this page, the quantity information is one of the few things not cached and queried directly against the database). This is annoying, but generally rare in our particular scenario (we are a reasonably small business and not that high traffic), and it will be fixed up in 3 hours anyway when we rebuild the whole index again from scratch, so I have accepted this as a reasonable trade-off.</p>

<p>(If I really wanted to solve this problem, there are a few approaches that I could take. I could use <a href="http://www.udidahan.com/2009/06/14/domain-events-salvation/">domain events</a> to fire off partial updates to the Solr index whenever a Save/Update operation occurred on an <code>Item</code> or <code>ItemGroup</code> in the Skiviez domain model, or I could insert a record into a table named, say, <code>dbo.IdentitiesOfStuffThatNeedsUpdatingInSolr</code>, and have an <code>IJob</code> that reads that list and executes partial updates every minute. And even if I did these things, I&#8217;d still probably want to do a periodic &#8220;blow it all away and refresh&#8221; in case one of those partial updates failed in the background.)</p>

<p>As for querying this data from Solr, there are a few approaches that I could have taken. One is to hide the fact that Solr exists entirely via the methods of a repository-like class: the <code>Get*()</code> methods would access Solr, and the Create/Update/Delete methods would access the database. I didn&#8217;t like this approach because my Solr schema is already shamelessly tailored to the UI that will be accessing that data, as it should be&#8211;I&#8217;ve already made the decision to use Solr to provide easy faceting, sorting, and fast display of information, so I might as well use it to its fullest extent. This means making it explicit in code as to when I mean to access Solr and when I mean to access the up-to-date, non-cached database object.</p>

<p>In my case, I ended up using <a href="http://nhforge.org/Default.aspx">NHibernate</a> to do the CRUD access (e.g., loading an <code>ItemGroup</code>, futzing with its pricing rules, and then saving it back), forgoing the repository pattern because I don&#8217;t typically see its value when NHibernate and its mappings are already abstracting the database. (Sometimes abstracting out NHibernate is useful, however, as we&#8217;ll see below.)</p>

<p><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/10/10-10-2010-10-20-52-AM.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/10/10-10-2010-10-20-52-AM.png" alt="" title="Trade-offs" width="328" height="81" class="aligncenter size-full wp-image-655" /></a></p>

<p>When querying for data, I know pretty well if I&#8217;m using it for catalog-oriented purposes (in which I care about <em>speed</em> and <em>querying features</em>) or for displaying in a table on a back-end administrative application (I care about <em>currency</em>). For querying on the Web site, I have an interface called <code>IListingQuery</code>. It has a <code>Search()</code> method that accepts a <code>ListingRequest</code> where I define some parameters&#8211;selected facets, search terms, page number, number of items per page, etc.&#8211;and gives back a <code>ListingResponse</code>&#8211;remaining facets, number of results, the results on this page, etc. This interface is pretty boring stuff.</p>

<p><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/10/moew.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/10/moew.png" alt="" title="Simpler than it looks" class="aligncenter size-full wp-image-672" /></a></p>

<p>Where it gets interesting is that the implementation of <code>IListingQuery</code> that gets dependency injected into my Web site&#8217;s <code>ProductsController</code> is using a list of <code>IListingQueryStrategy</code>s underneath. The default strategy, the <code>SolrListingQueryStrategy</code>, hits Solr directly via a plain old-fashioned <code>HttpWebRequest</code> and parses the XML in the <code>HttpWebResponse</code> (which is much easier to use, in my humble opinion, than some of the Solr client libraries).</p>

<p>If the Solr-based strategy throws an exception or vomits for some reason, then the <code>DatabaseListingQueryStrategy</code> runs next and hits the database directly&#8211;although it ignores some parameters of the <code>ListingRequest</code>, like faceting or advanced text searching, since that is inefficient to do there and is the whole reason I am using Solr in the first place. The idea is that usually Solr is answering my search requests quickly in their full-featured glory, but if something blows up and Solr goes down, then the catalog pages of the site can still function in &#8220;reduced-functionality mode&#8221; by hitting the database with a limited feature set directly. (As implemented on the Skiviez site today, you would realize that this happened if the filters list on the left-hand side becomes empty and search parameters are ignored.)</p>

<p>(The explosion of classes that you see in the screenshot above is mostly due to testability. For example, Solr works by sending long, complicated GET requests to it. So I&#8217;ve pulled out of the URI-building functionality into its own class; it serves a single purpose and can be tested as such. The actual <code>SolrListingQueryStrategy</code> class implementation is very short, with most of the work delegated to other classes within that folder.)</p>

<h2>Conclusions and delusions</h2>

<p><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/10/10-10-2010-11-56-35-AM1.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2010/10/10-10-2010-11-56-35-AM1.png" alt="" title="Putting it together" class="aligncenter size-full wp-image-688" /></a></p>

<p>What is important is that I have made explicit in code that this is a search&#8211;by using <code>IListingQuery</code> instead of NHibernate&#8211;so the database-based strategy can take some liberties in ignoring some of the search parameters without worrying about affecting some of its down-level callers too severely. The decision to perform a query against a possibly-stale data store versus the authoritative data store has been made explicit&#8211;if I want fast, possibly stale data with advanced search features, I use <code>IListingQuery</code>. If I want slow, up-to-date data with insert/update/delete capability, I use NHibernate&#8217;s named queries. And if I make a change in the SQL database, I know that the out-of-process Worker service will update Solr eventually, making things eventually consistent.</p>

<p>The end result? Fast catalog pages for our customers that gracefully fall back to the old behavior when something doesn&#8217;t work.</p>
]]></content:encoded>
			<wfw:commentRss>http://nicholas.piasecki.name/blog/2010/10/inside-skiviez-catalog-listings-and-search-queries/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Add AVS and CVN to Magento&#8217;s Admin Screen in Just 637 Easy Steps</title>
		<link>http://nicholas.piasecki.name/blog/2009/10/add-avs-and-cvn-to-magentos-admin-screen-in-just-637-easy-steps/</link>
		<comments>http://nicholas.piasecki.name/blog/2009/10/add-avs-and-cvn-to-magentos-admin-screen-in-just-637-easy-steps/#comments</comments>
		<pubDate>Sat, 03 Oct 2009 20:28:51 +0000</pubDate>
		<dc:creator>Nicholas Piasecki</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[magento]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[web stuff]]></category>

		<guid isPermaLink="false">http://nicholas.piasecki.name/blog/?p=361</guid>
		<description><![CDATA[We&#8217;ve recently set up a new e-commerce store at Men&#8217;s Underwear Discounters that represents a division of the company that I work for, Skiviez. We decided to save time for this discount store by using Magento, the current darling child in the open source e-commerce platform market segment. A brief interlude on consulting, documentation, and [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_364" class="wp-caption aligncenter" style="width: 310px"><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2009/10/avs-in-magento.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2009/10/avs-in-magento-300x113.png" alt="AVS Information In Magento" title="Displaying AVS information in Magento" width="300" height="113" class="size-medium wp-image-364" /></a><p class="wp-caption-text">AVS Information In Magento</p></div>

<p>We&#8217;ve recently set up a new e-commerce store at <a href="http://www.mensunderweardiscounters.com">Men&#8217;s Underwear Discounters</a> that represents a division of the company that I work for, <a href="http://www.skiviez.com">Skiviez</a>. We decided to save time for this discount store by using <a href="http://www.magentocommerce.com">Magento</a>, the current darling child in the open source e-commerce platform market segment.</p>

<h2>A brief interlude on consulting, documentation, and open source</h2>

<p>Now, to be clear, it doesn&#8217;t take much to exceed expectations in the &#8220;open source e-commerce platform&#8221; market because prior to Magento, your options were pretty much limited to <a href="http://www.oscommerce.com">osCommerce</a>, which is quite possibly the most reckless, idiotic excuse of an e-commerce platform that I have seen (and I don&#8217;t like to insult code), and its slightly-less-retarded sibling <a href="http://www.zen-cart.com">Zen Cart</a>. (I will save the osCommerce rants for another post.)</p>

<p>Magento seems to be a dream come true: thousands of man-hours of development into an e-commerce platform for free. So what&#8217;s the catch? While Varien (&#8220;the Magento company&#8221;) has done a great service to the world and the open source community by creating Magento, they&#8217;re still in it to make a buck&#8211;and that&#8217;s not a bad thing&#8211;but you might not realize how they make those bucks until you&#8217;ve started playing around with your own Magento store. They make money on support, consulting, and customization because Magento is <em>huge</em> and poorly documented.</p>

<p>Actually, &#8220;poorly documented&#8221; would imply that there was at least some documentation, and while there truly is some documentation available in the source code and on Varien&#8217;s Magento Web site, in reality, that amount of documentation is a statistical rounding error. And when you actually view your Magento installation in an FTP program, you will be absolutely <em>astounded</em> at the number of directories and files. You can try inspecting the source files to try to put it all together, but a lot of it is &#8220;magic&#8221;: a framework erected at runtime by XML configuration files and PHP&#8217;s idiotic <code>__call</code> mechanism for magic functions that appear at runtime out of thin air. You can see references to a function called <code>getOrder()</code>, for example, grep the entire installation for &#8220;getOrder()&#8221;, and not get any results because the function doesn&#8217;t actually exist at compile time. Personally, I&#8217;ve always considered magic methods to be an extremely unwise idea, a &#8220;too clever&#8221; approach to programming. But for people new to PHP looking to do a little customization to their Magento store, it makes the codebase all the more impenetrable. That&#8217;s more consulting dollars.</p>

<p>You could go to the Magento forums, but you won&#8217;t find too many helpful answers because Magento obviously doesn&#8217;t want to give help for free, since giving help is central to their business model. So if you need help, your best bet is to generally (a) pay for it or (b) hope that you stumble across somebody&#8217;s blog who took the time to post a solution to your exact problem.</p>

<h2>Why do I need to do this, anyway?</h2>

<p>Magento has a lot of stuff built in. But we need to remember that Magento was built by software developers, and software developers generally don&#8217;t understand the problem domain of running an e-commerce business very well. Sure, every software developer has built the pet shop&#8211;products, categories, inventory, orders, how hard could it be?&#8211;but they stop or fail to understand that there&#8217;s a whole class of operations that need to happen after the order has been placed.</p>

<p>One of those operations is fraud analysis. The Address Verification System (AVS) and the Card Verification Number (CVN) system for credit cards enable merchants to help determine if a credit card has been fraudulently used on an order. AVS will tell the merchant whether or not the billing address specified by the customer matches or partially matches the billing address on the credit card&#8217;s billing statement. And the CVN number represents the number that (supposedly) exists in only two places in the world: on the physical credit card and in the issuing bank&#8217;s files. If a CVN doesn&#8217;t match and the AVS doesn&#8217;t match, then there&#8217;s a good bet that there is something wrong with the order.</p>

<p>Because software developers are nerds, this information doesn&#8217;t currently display by default in Magento&#8217;s administration section. So let&#8217;s add it.</p>

<h2>Can&#8217;t I just edit the template?</h2>

<p>I&#8217;m talking about adding this AVS display functionality in the context of the CyberSource extension for Magento. After spelunking through the myriad files and directories, I discovered that the Varien-provided CyberSource extension is saving the AVS (<code>setCcAvsStatus()</code>) and CVN (<code>setCcCidStatus()</code>) information when it authorizes the card, but it doesn&#8217;t display in the information block in the administration section.</p>

<p>While you could just modify <code>app/design/adminhtml/default/default/template/cybersource/info.phtml</code> directly (yes, that is the actual path to the file that displays the little &#8220;Payment&#8221; block), your changes would be lost and overwritten in the future if you ever upgraded the CyberSource extension via Magento Connect. That&#8217;s obviously less than ideal.</p>

<p>A better way would be to use Magento&#8217;s &#8220;rewrite&#8221; mechanism. We&#8217;ll create our own Magento module and instruct Magento to replace the CyberSource extension&#8217;s information block with our own.</p>

<h2>Creating our own module</h2>

<p>First, we&#8217;ll create a new empty directory to hold our files. Let&#8217;s call it <code>avsdisplay</code>. Then we&#8217;ll create <code>code</code>, <code>etc</code>, and <code>design</code> subdirectories. These directories mirror the subdirectories in the <code>app</code> folder of your Magento installation.</p>

<p>In the <code>etc</code> directory, we need to create an XML configuration file. Magento scans this directory at runtime for XML files and reads them to know which modules to load. I&#8217;ve named my configuration file <code>Mud_Avsdisplay.xml</code>, and the naming is very important. (Magento uses a mixture of convention and configuration.) The part of the filename before the underscore is your &#8220;namespace,&#8221; since PHP doesn&#8217;t support namespaces. And the part of the filename after the underscore is the name of your module. Mine is &#8220;Avsdisplay.&#8221; Don&#8217;t try to use something like &#8220;AvsDisplay,&#8221; however, because that would break Magento&#8217;s convention as we&#8217;ll see in a moment.</p>

<p>Inside this file, we tell Magento to load our module in the <code>local</code> pool and to actually run it (by setting &#8220;active&#8221; to &#8220;true&#8221;). (The other pools are <code>core</code>, for those modules provided by Varien, and <code>community</code>, for those modules that you can download via Magento Connect.)</p>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;config<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;modules<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Mud_Avsdisplay<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;active<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/active<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;codePool<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>local<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/codePool<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Mud_Avsdisplay<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/modules<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/config<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>


<p>Now it&#8217;s time to create the meat of the module. In the code folder, create a <code>local</code> directory. Within that, create a directory named after your chosen namespace (<code>Mud</code> in my example) and within that yet another subdirectory named after your module (<code>Avsdisplay</code> in my example). (This is why naming was important. If I had called it &#8220;Mud_AvsDisplay,&#8221; with a capital &#8216;D&#8217;, then Magento would have looked in <code>app/code/local/Mud/Avs/Display</code> for my module instead of <code>app/code/local/Mud/Avsdisplay</code>.)</p>

<p>Within your module directory, you&#8217;ll need to create three <em>more</em> subdirectories: <code>Block</code>, <code>etc</code>, and <code>Helper</code>. When it&#8217;s all said and done, you&#8217;ll end up with a hierarchy that looks like this (ignore the &#8220;design&#8221; directory, we&#8217;ll get to that later):</p>

<div id="attachment_367" class="wp-caption aligncenter" style="width: 202px"><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2009/10/directories.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2009/10/directories.png" alt="Directory Structure" title="directories" width="192" height="236" class="size-full wp-image-367" /></a><p class="wp-caption-text">Directory Structure</p></div>

<h3>Creating the block</h3>

<p>Next, we need to create the &#8220;block&#8221; that we&#8217;ll be replacing. After searching through the codebase, I figured out that I wanted to replace the <code>Mage_Cybersource_Block_Info</code> block (for reference, by Magento&#8217;s convention, that file lives in <code>app/core/Mage/Cybersource/Block/Info.php</code> &#8212; see the convention?). But I really only want to add stuff to it, not replace it outright, so I&#8217;ll create a new file in my <code>Block</code> folder called <code>Info.php</code> that extends that class. Something like:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> Mud_AvsDisplay_Block_Info <span style="color: #000000; font-weight: bold;">extends</span> Mage_Cybersource_Block_Info
<span style="color: #009900;">&#123;</span>
	<span style="color: #666666; font-style: italic;">// Yes, these really have to be protected, not private, due to more Magento</span>
	<span style="color: #666666; font-style: italic;">// &quot;magic&quot;</span>
	<span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$avsDescriptions</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
		<span style="color: #666666; font-style: italic;">// Snipped for brevity; download file at end of blog post</span>
	<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$ccCidDescriptions</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
		<span style="color: #666666; font-style: italic;">// Snipped for brevity; download file at end of blog post</span>
	<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> _construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		parent<span style="color: #339933;">::</span>_construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setTemplate</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'avsdisplay/info.phtml'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getAvsStatusDescription<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$info</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getInfo</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$avsCode</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$info</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCcAvsStatus</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$avsDescription</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Unrecognized response code.'</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">array_key_exists</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$avsCode</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">avsDescriptions</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$avsDescription</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">avsDescriptions</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$avsCode</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #b1b100;">return</span> <span style="color: #000088;">$avsDescription</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getCcCidDescription<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$info</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getInfo</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$ccCidCode</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$info</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCcCidStatus</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$ccCidDescription</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Unrecognized response code.'</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">array_key_exists</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ccCidCode</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">ccCidDescriptions</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$ccCidDescription</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">ccCidDescriptions</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$ccCidCode</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
		<span style="color: #b1b100;">return</span> <span style="color: #000088;">$ccCidDescription</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>


<p>Okay, this makes sense. I&#8217;m doing everything the old CyberSource info block did, except I added two new functions that give me human-friendly descriptions of the AVS and CVN codes, and I&#8217;m setting the template to something called <code>avsdisplay/info.phtml</code> instead of <code>cybersouce/info.phtml</code>. How this comes into play will make sense in a minute.</p>

<h3>Creating the helper</h3>

<p>In my <code>Helper</code> directory, I need to add a <code>Data.php</code> file that looks like this:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> Mud_Avsdisplay_Helper_Data <span style="color: #000000; font-weight: bold;">extends</span> Mage_Core_Helper_Abstract
<span style="color: #009900;">&#123;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>


<p>That&#8217;s right, it does nothing except inherit from a Magento-provided abstract class. What is a helper? I have no idea, but you have to do it&#8211;Magento looks for this file.</p>

<h3>Telling Magento to do the swap</h3>

<p>In my <code>etc</code> directory, I need to add a <code>config.xml</code> file that will tell Magento some information about my module and, most importantly, that I want to be swapped with the CyberSource extension&#8217;s info block:</p>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;config<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;modules<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Mud_Avsdisplay<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>0.0.1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Mud_Avsdisplay<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/modules<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;global<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;helpers<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;avsdisplay<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
				<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Mud_Avsdisplay_Helper_Data<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/avsdisplay<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/helpers<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;blocks<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;cybersource<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
				<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;rewrite<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
					<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;info<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Mud_Avsdisplay_Block_Info<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/info<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
				<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/rewrite<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/cybersource<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/blocks<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/global<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/config<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>


<p>Under <code>&lt;modules&gt;</code>, I&#8217;m just telling Magento the version number of my module. Under <code>&lt;global&gt;</code>, I say that I want to &#8220;rewrite&#8221; the CyberSource info block with my own class named <code>Mud_Avsdisplay_Block_Info</code>, which, by convention, Magento will look for in <code>[module-root]/Mud/Avsdisplay/Block/Info.php</code>. That is the file that I just created. Great.</p>

<h3>Finally, writing the template that displays the information</h3>

<p>But we haven&#8217;t actually changed any HTML at this point! Remember in my <code>Info.php</code> file where I set the template to something called <code>info.phtml</code>? Well, I need to create that file. At the top of my module folder&#8211;the one with the <code>code</code> and <code>etc</code> subdirectories&#8211;I&#8217;ll need to create some more subdirectories. A lot of them. In fact, I&#8217;ll need to create a bunch of empty directories that look like this:</p>

<p><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2009/10/design-directories.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2009/10/design-directories.png" alt="Design Directory Structure" title="Design Directory Structure" width="164" height="133" class="aligncenter size-full wp-image-368" /></a></p>

<p>In the bottom-most subdirectory, I&#8217;ll create the <code>info.phtml</code> file. This is a PHP file, except that when I use the <code>$this</code> pseudo-variable in this file, <code>$this</code> will be pointing to an instance of my <code>Mud_Avsdisplay_Block_Info</code> class. So I&#8217;ll be able to call my <code>getAvsStatusDescription()</code> method here among other things:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$info</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getInfo</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">?&gt;</span>
			&lt;strong&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMethod</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTitle</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/strong&gt;&lt;br /&gt;
			&lt;strong&gt;Type:&lt;/strong&gt; <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCcTypeName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;br /&gt;
			&lt;strong&gt;Number:&lt;/strong&gt; xxxx-<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$info</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCcLast4</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;br /&gt;
			&lt;strong&gt;Expiry:&lt;/strong&gt; <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'%s/%s'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCcExpMonth</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$info</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCcExpYear</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;br /&gt;
			&lt;strong&gt;AVS:&lt;/strong&gt; (<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$info</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCcAvsStatus</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>) <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAvsStatusDescription</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;br /&gt;
			&lt;strong&gt;CCID:&lt;/strong&gt; (<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$info</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCcCidStatus</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>) <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCcCidDescription</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;br /&gt;
		<span style="color: #000000; font-weight: bold;">&lt;?php</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>


<h2>Conclusions and delusions</h2>

<p>And that&#8217;s it. Upload this entire directory structure to your Magento installation&#8217;s <code>app</code> directory, <em>merging</em> the contents as necessary, and you should be able to see AVS information for your CyberSource orders in the administration section.</p>

<p>How did I figure out how to learn all of this? It was mostly by lots of Googling, picking apart existing modules to see how they were organized, and piecing together lots of blog posts. I hope this helps someone out there. Good luck!</p>

<p><a href='http://nicholas.piasecki.name/blog/wp-content/uploads/2009/10/avsdisplay-0.0.2.zip'>Download the code used in this article.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://nicholas.piasecki.name/blog/2009/10/add-avs-and-cvn-to-magentos-admin-screen-in-just-637-easy-steps/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>When in doubt: OpenID is a bad idea for your Web site</title>
		<link>http://nicholas.piasecki.name/blog/2009/07/when-in-doubt-openid-is-a-bad-idea-for-your-web-site/</link>
		<comments>http://nicholas.piasecki.name/blog/2009/07/when-in-doubt-openid-is-a-bad-idea-for-your-web-site/#comments</comments>
		<pubDate>Tue, 07 Jul 2009 00:15:36 +0000</pubDate>
		<dc:creator>Nicholas Piasecki</dc:creator>
				<category><![CDATA[Rants]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[openid]]></category>
		<category><![CDATA[web stuff]]></category>

		<guid isPermaLink="false">http://nicholas.piasecki.name/blog/?p=291</guid>
		<description><![CDATA[Well, that&#8217;s a bit of an inflammatory title. But this screenshot speaks volumes: What has happened here is that my OpenID provider, Verisign Labs, is down for some reason while StackOverflow, the site that I&#8217;m trying to log on to, is still up. A single point of failure While this isn&#8217;t a big deal for [...]]]></description>
			<content:encoded><![CDATA[<p>Well, that&#8217;s a bit of an inflammatory title. But this screenshot speaks volumes:</p>

<div id="attachment_292" class="wp-caption aligncenter" style="width: 310px"><a href="http://nicholas.piasecki.name/blog/wp-content/uploads/2009/07/openid.png"><img src="http://nicholas.piasecki.name/blog/wp-content/uploads/2009/07/openid-300x136.png" alt="I can&#039;t log in!" title="openid" width="300" height="136" class="size-medium wp-image-292" /></a><p class="wp-caption-text">I can't log in!</p></div>

<p>What has happened here is that my <a href="http://openid.net/">OpenID</a> provider, <a href="https://pip.verisignlabs.com/">Verisign Labs</a>, is down for some reason while StackOverflow, the site that I&#8217;m trying to log on to, is still up.</p>

<h2>A single point of failure</h2>

<p>While this isn&#8217;t a big deal for a site that I use recreationally, it is kind of a big deal in principle: all sites that use OpenID are inaccessible to me, since I only have this single OpenID provider. It is a single point of failure.</p>

<p>Sure, I could have multiple OpenID accounts, such as a &#8220;backup&#8221; OpenID account at another provider, but this defeats the purpose of OpenID, of having a central point of authority regarding my online identity. If I have to create a second OpenID provider, I might as well just make a native username and password at the site that I&#8217;m trying to log into. I could also be my own OpenID provider, but I shouldn&#8217;t have to do that, and the average OpenID consumer is not going to know how to do that, anyway. It&#8217;s faster just to create a &#8220;native account&#8221; at the Web site that I&#8217;m trying to access and be done with it.</p>

<h2>An unnecessary third-party dependency</h2>

<p>For any e-commerce business, it&#8217;s usually unwise to take on <em>any</em> third-party dependency. Speaking from experience, that third-party will go down for some reason at some point and <em>you</em> will be the one fielding angry customer support calls for something that isn&#8217;t your problem. Even worse, if something as critical as authentication through OpenID goes down, then you&#8217;re losing sales, and that means that you&#8217;re not doing your job.</p>

<p>If you&#8217;re going to add OpenID to an e-commerce Web site or a &#8220;mission-critical&#8221; Web site, then you should implement it as a red-headed step-child, &#8220;convenience only&#8221; implementation; this way, your users can fall back onto their &#8220;native credentials&#8221; (those stored in <em>your</em> database) when their preferred OpenID provider explodes. In this way, OpenID is a shortcut, not a single authoritative source, much how like customers use PayPal&#8217;s Express Checkout to save time when entering payment and addressing information during checkout. If PayPal&#8217;s Web Service API goes down (and believe you me, it&#8217;s gone down several times this year alone), customers can still begrudgingly use the &#8220;native checkout&#8221; to complete their purchase. Some lost conversions due to the inconvenience&#8211;and for incorrectly faulting the integrity of your Web site for the third party&#8217;s failure&#8211;but at least <em>the sale is still actually possible.</em> If OpenID is your only authentication mechanism, and a user&#8217;s OpenID provider goes down, then that user is simply screwed. The onus should not be on the consumer to provide a backup authentication mechanism to <em>your</em> Web site.</p>

<h2>It&#8217;s just complicated</h2>

<p>OpenID is still just too complicated. I&#8217;m not the smartest software developer in the world by any means, but if I can barely wrap my mind around it enough just to get my first account, then I am 100% certain that our customers would have problems with it:</p>

<ul>
<li>Why do I have to go to some third-party provider to sign in? That doesn&#8217;t make any sense.</li>
<li>Why should I trust that third-party provider? I&#8217;m not even sure that I trust you!</li>
<li>I still don&#8217;t know which third-party provider to use! Oh well, I guess I&#8217;ll use Verisign, at least I&#8217;ve heard of them.</li>
<li>What happens to my credentials when that third-party provider goes under?</li>
<li>Can I call your business to reset my password when I forget it? I will anyway!</li>
</ul>

<p>Even with our &#8220;native registration&#8221; of e-mail addresses and passwords, we had to use an Amazon.com style login form because users kept filling out the &#8220;new customer&#8221; form even when they already had an account:</p>

<blockquote>
  <p>Login screen. Amazon&#8217;s sign-in screen remains a model to be emulated, minimizing the common problem of new customers who try to log in without having registered. Amazon presents two questions in linear order: (1) &#8220;What is your email address?&#8221; and (2) &#8220;Do you have an Amazon.com password?&#8221; For the second question, users can select one of two radio buttons: &#8220;No, I am a new customer,&#8221; or &#8220;Yes, I have a password.&#8221; Many other sites present the new- and established-user sections side-by-side, and thereby divert new users to the established-user section through the magnetic attraction of type-in fields. &#8212; Jakob Niesen, <a href="http://www.useit.com/alertbox/20050725.html">useit.com</a></p>
</blockquote>

<p>When our users have trouble navigating two fields and a radio button, you can imagine the hilarity that ensues when they are presented with multiple authentication mechanisms. Especially one that doesn&#8217;t ask for a password.</p>

<h2>A leaky abstraction</h2>

<p>While the idea of consolidating your online identity to a single source sounds like a good idea, it simply does not work in practice. Not even the United States government has a consistent picture of my identity: my identity is stored with the IRS, the Social Security Administration, the United States Postal service, the Virginia Department of Taxation, the Virginia Department of Motor Vehicles, and the City of Richmond&#8217;s Voter Registrar. These are all <em>independent</em> identity stores that, in general, agree that I am who I say that I am, but each identity is stored and updated independently of one another. Consider OpenID the RealID act of the Internet: what happens when your centralized identity gets screwed up? It&#8217;s an existentialist crisis and you just have to deal with it: identity is what other people say you are; it&#8217;s <em>not</em> what <em>you</em> say you are. Better to have multiple voices confirming your identity than just one.</p>

<h2>Conclusions and Delusions</h2>

<p>If you&#8217;re implementing a social-oriented Web site that is designed to integrate with Facebook or some of the Web-2.0-savvy consumers, then OpenID might make sense. Those nerds may have heard of OpenID and know how to use it, foibles and all. Until the dust settles on OpenID, though, I wouldn&#8217;t add it to a commercial site even if you paid for it: nobody has asked for it; it will cause problems.</p>

<p>My general recommendation would be to have the usual in house username and password mechanism that can be supplemented by OpenID. But realize that each alternative identification mechanism that you add runs the risk of customer confusion, bugs, security holes, and increased customer support. When in doubt, leave it out.</p>
]]></content:encoded>
			<wfw:commentRss>http://nicholas.piasecki.name/blog/2009/07/when-in-doubt-openid-is-a-bad-idea-for-your-web-site/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>On IIS 6, Content-Location, Internal IP Addresses, and URL Redirection</title>
		<link>http://nicholas.piasecki.name/blog/2008/12/on-iis-6-content-location-internal-ip-addresses-and-url-redirection/</link>
		<comments>http://nicholas.piasecki.name/blog/2008/12/on-iis-6-content-location-internal-ip-addresses-and-url-redirection/#comments</comments>
		<pubDate>Fri, 05 Dec 2008 14:36:51 +0000</pubDate>
		<dc:creator>Nicholas Piasecki</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[iis]]></category>
		<category><![CDATA[web stuff]]></category>

		<guid isPermaLink="false">http://nicholas.piasecki.name/blog/?p=103</guid>
		<description><![CDATA[One of our automated security scans of our Web site turned up a low priority notice that our server was revealing its internal IP address on some redirect requests. It&#8217;s a &#8220;feature&#8221; of IIS that occurs when a client requests a resource via HTTP 1.0 (or without the Host header) that results in a redirection. [...]]]></description>
			<content:encoded><![CDATA[<p>One of our automated security scans of our Web site turned up a low priority notice that our server was revealing its internal IP address on some redirect requests. It&#8217;s a &#8220;feature&#8221; of IIS that occurs when a client requests a resource via HTTP 1.0 (or without the Host header) that results in a redirection. The output of a telnet session to such a resource looks something like this:</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span>npiaseck ~<span style="color: #7a0874; font-weight: bold;">&#93;</span>$ telnet www.example.com <span style="color: #000000;">80</span>
Trying 10.1.10.38...
Connected to www.example.com <span style="color: #7a0874; font-weight: bold;">&#40;</span>10.1.10.38<span style="color: #7a0874; font-weight: bold;">&#41;</span>.
Escape character is <span style="color: #ff0000;">'^]'</span>.
GET <span style="color: #000000; font-weight: bold;">/</span>Media HTTP<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">1.0</span>
&nbsp;
HTTP<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">1.1</span> <span style="color: #000000;">301</span> Moved Permanently
Content-Length: <span style="color: #000000;">152</span>
Content-Type: text<span style="color: #000000; font-weight: bold;">/</span>html
Location: http:<span style="color: #000000; font-weight: bold;">//</span>10.1.10.38<span style="color: #000000; font-weight: bold;">/</span>Media<span style="color: #000000; font-weight: bold;">/</span>
Server: Microsoft-IIS<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">6.0</span>
Date: Fri, 05 Dec <span style="color: #000000;">2008</span> <span style="color: #000000;">13</span>:<span style="color: #000000;">50</span>:00 GMT
Connection: close
&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;</span><span style="color: #c20cb9; font-weight: bold;">head</span><span style="color: #000000; font-weight: bold;">&gt;&lt;</span>title<span style="color: #000000; font-weight: bold;">&gt;</span>Document Moved<span style="color: #000000; font-weight: bold;">&lt;/</span>title<span style="color: #000000; font-weight: bold;">&gt;&lt;/</span><span style="color: #c20cb9; font-weight: bold;">head</span><span style="color: #000000; font-weight: bold;">&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;</span>body<span style="color: #000000; font-weight: bold;">&gt;&lt;</span>h1<span style="color: #000000; font-weight: bold;">&gt;</span>Object Moved<span style="color: #000000; font-weight: bold;">&lt;/</span>h1<span style="color: #000000; font-weight: bold;">&gt;</span>
This document may be found <span style="color: #000000; font-weight: bold;">&lt;</span>a <span style="color: #007800;">HREF</span>=<span style="color: #ff0000;">&quot;http://10.1.10.38/Media/&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span>here<span style="color: #000000; font-weight: bold;">&lt;/</span>a<span style="color: #000000; font-weight: bold;">&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;/</span>body<span style="color: #000000; font-weight: bold;">&gt;</span>
&nbsp;
Connection closed by foreign host.</pre></div></div>


<p>I&#8217;ve made up an internal IP address, but the point is that IIS is inserting the internal IP address in the body of the document as well as the Location header. If you make the same request with the Host header supplied, such as in <code>Host: www.example.com</code>, then IIS would use <code>www.example.com</code> instead of supplying the IP address.</p>

<p>The recommended Microsoft solution is detailed in <a href="http://support.microsoft.com/kb/834141">KB834141</a>. Namely, you edit the <code>SetHostName</code> metabase entry for the Web site to <code>www.example.com</code>, and now IIS will use that instead of the IP address in the above redirection scenario. Easy as pie, right?</p>

<p>Well, that change broke some code. For reasons that are not clear to me, here&#8217;s the mechanism by which IIS 6 determines what to use in these redirect requests:</p>

<ol>
<li>Is the <code>UseHostName</code> property set to <code>true</code>? If so, use the machine&#8217;s host name.</li>
<li>Is the <code>SetHostName</code> property set to some value? If so, use that value.</li>
<li>Is a <code>Host</code> header supplied in the HTTP request? If so, use that value.</li>
<li>If all of the above fail, just use the IP address, which is probably internal.</li>
</ol>

<p>For search engine optimization reasons, all of the requests on our Web site redirect all requests that come in without the <code>www</code> subdomain to ones with the <code>www</code> subdomain. This prevents Google from dinging us for having duplicated content. The code was implemented as an ASP.NET HTTP module that ran before every request and inspected the incoming URL by looking at the <code>HttpContext.Current.Request.Url.OriginalString</code> property. If the domain didn&#8217;t match, then it issued a permanent redirect.</p>

<p>The problem with the above precedence order is that IIS will substitute the value of <code>HTTP_HOST</code> and other server variables passed into ASP.NET with the <code>SetHostName</code> value, not the <code>Host</code> header if so supplied. The net effect is that our redirection method suddenly stopped working because the code was always seeing the <code>SetHostName</code> value, <code>www.example.com</code>, regardless of the URL that was actually used to make the request. To make matters worse, if we were to set the <code>UseHostName</code> property, the code would <em>always</em> see a mismatch and enter a redirect loop. Neither are desirable scenarios.</p>

<p>The solution is to change the code to inspect the <code>Host</code> header directly, if present, instead of looking at the URL as passed into the server variables array. It ends up looking something like this:</p>


<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF; font-weight: bold;">private</span> <span style="color: #6666cc; font-weight: bold;">void</span> OnContextBeginRequest<span style="color: #008000;">&#40;</span><span style="color: #6666cc; font-weight: bold;">object</span> sender, EventArgs e<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	HttpContext context<span style="color: #008000;">;</span>
	<span style="color: #6666cc; font-weight: bold;">string</span> originalRequestHost<span style="color: #008000;">;</span>
	<span style="color: #6666cc; font-weight: bold;">int</span> portIndex<span style="color: #008000;">;</span>
	HttpRequest request<span style="color: #008000;">;</span>
	<span style="color: #6666cc; font-weight: bold;">string</span> redirectUri<span style="color: #008000;">;</span>
&nbsp;
	context <span style="color: #008000;">=</span> HttpContext<span style="color: #008000;">.</span><span style="color: #0000FF;">Current</span><span style="color: #008000;">;</span>
	request <span style="color: #008000;">=</span> context<span style="color: #008000;">.</span><span style="color: #0000FF;">Request</span><span style="color: #008000;">;</span>
&nbsp;
	originalRequestHost <span style="color: #008000;">=</span> request<span style="color: #008000;">.</span><span style="color: #0000FF;">Headers</span><span style="color: #008000;">&#91;</span><span style="color: #666666;">&quot;Host&quot;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">;</span>
&nbsp;
	<span style="color: #008080; font-style: italic;">// Some clients will pass in the port number in the Host header if</span>
	<span style="color: #008080; font-style: italic;">// it's not going over port 80</span>
	portIndex <span style="color: #008000;">=</span> originalRequestHost<span style="color: #008000;">.</span><span style="color: #0000FF;">LastIndexOf</span><span style="color: #008000;">&#40;</span><span style="color: #666666;">':'</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span>portIndex <span style="color: #008000;">!=</span> <span style="color: #008000;">-</span><span style="color: #FF0000;">1</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		originalRequestHost <span style="color: #008000;">=</span> 
			originalRequestHost<span style="color: #008000;">.</span><span style="color: #0000FF;">Substring</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">0</span>, portIndex<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
	<span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span>originalRequestHost <span style="color: #008000;">!=</span> <span style="color: #0600FF; font-weight: bold;">null</span> <span style="color: #008000;">&amp;&amp;</span> originalRequestHost <span style="color: #008000;">!=</span> mPreferredSubdomain<span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		redirectUri <span style="color: #008000;">=</span> <span style="color: #6666cc; font-weight: bold;">string</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Format</span><span style="color: #008000;">&#40;</span>
			<span style="color: #666666;">&quot;http://{0}{1}{2}&quot;</span>,
			mPreferredSubdomain, 
			request<span style="color: #008000;">.</span><span style="color: #0000FF;">Url</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Port</span> <span style="color: #008000;">!=</span> <span style="color: #FF0000;">80</span> <span style="color: #008000;">?</span> <span style="color: #666666;">&quot;:&quot;</span> <span style="color: #008000;">+</span> request<span style="color: #008000;">.</span><span style="color: #0000FF;">Url</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Port</span><span style="color: #008000;">.</span><span style="color: #0000FF;">ToString</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">:</span> <span style="color: #6666cc; font-weight: bold;">string</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Empty</span>,
			request<span style="color: #008000;">.</span><span style="color: #0000FF;">RawUrl</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
		cLog<span style="color: #008000;">.</span><span style="color: #0000FF;">InfoFormat</span><span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;Redirecting from to {0} (domain: {1}, preferred: {2}).&quot;</span>,
			redirectUri, originalRequestHost, mPreferredSubdomain<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
		context<span style="color: #008000;">.</span><span style="color: #0000FF;">Response</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Redirect</span><span style="color: #008000;">&#40;</span>redirectUri, <span style="color: #0600FF; font-weight: bold;">true</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>


<p>The code looks at the host header. If it&#8217;s set, and doesn&#8217;t match, then it redirects. (It does a little bit of finagling to strip off the port number if a non-standard port is used in the request.)</p>

<p>With this code in place, we can now use the <code>SetHostName</code> property and still have our URL redirection work properly for HTTP/1.1 requests. We&#8217;re out of luck when it comes to HTTP/1.0 requests, but this is something that we can live with.</p>
]]></content:encoded>
			<wfw:commentRss>http://nicholas.piasecki.name/blog/2008/12/on-iis-6-content-location-internal-ip-addresses-and-url-redirection/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

