<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Scott On Writing.NET</title><link>http://scottonwriting.net/sowblog/default.aspx</link><description>Musings on technical writing...</description><dc:language>en</dc:language><generator>CommunityServer 2007 (Build: 20423.869)</generator><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/ScottOnWriting" /><feedburner:info uri="scottonwriting" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:browserFriendly>This is an XML content feed. It is intended to be viewed in a newsreader or syndicated to another site, subject to copyright and fair use.</feedburner:browserFriendly><item><title>Using Templates to Display Boolean Values as Yes/No Options</title><link>http://feedproxy.google.com/~r/ScottOnWriting/~3/rHBRtcnWXA0/using-templates-to-display-boolean-values-as-yes-no-options.aspx</link><pubDate>Tue, 22 Nov 2011 01:11:08 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:200696</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>1</slash:comments><wfw:commentRss>http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=200696</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2011/11/22/using-templates-to-display-boolean-values-as-yes-no-options.aspx#comments</comments><description>&lt;p&gt;One of ASP.NET MVC’s most useful features is its powerful templating system. Templates were introduced with ASP.NET MVC 2 as a way to have the view render either a display- or editing-related user interface for the entire model or for a property of the model. The &lt;strong&gt;Html.DisplayFor&lt;/strong&gt; and &lt;strong&gt;Html.EditorFor&lt;/strong&gt; methods provide a strongly-typed mechanism for rendering the appropriate template for a particular model property:&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;@Html.DisplayFor(model =&amp;gt; model.PropertyName)

@Html.EditorFor(model =&amp;gt; model.PropertyName)&lt;/pre&gt;

&lt;p&gt;For an in-depth overview of templates in ASP.NET MVC, see Brad Wilson’s multi-part article series, &lt;a href="http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html"&gt;ASP.NET MVC 2 Templates&lt;/a&gt;. (The content in Brad’s articles apply the same to ASP.NET MVC 3.)&lt;/p&gt;

&lt;h2&gt;&lt;/h2&gt;

&lt;h2&gt;How Html.DisplayFor and Html.EditorFor Determine Which Template to Use&lt;/h2&gt;

&lt;p&gt;ASP.NET MVC includes a number of built-in display and editor templates. For instance, when rendering a display or editing template for a Boolean value ASP.NET MVC will render either a disabled or enabled checkbox. When rendering a display template for an email address, ASP.NET MVC will render an actual &lt;strong&gt;mailto:&lt;/strong&gt; anchor tag so that the email address is clickable. The editor template for a password property renders an &lt;strong&gt;&amp;lt;input type=”password” /&amp;gt;&lt;/strong&gt; textbox so that the user’s input is masked. Additionally, you can create your own custom display and editor templates.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Html.DisplayFor&lt;/strong&gt; and &lt;strong&gt;Html.EditorFor&lt;/strong&gt; methods, when called, need to determine which template to render for the given property. To make this determination these methods examine the specified property’s &lt;em&gt;metadata&lt;/em&gt;, which includes information like the property’s data type (&lt;strong&gt;bool&lt;/strong&gt;, &lt;strong&gt;string&lt;/strong&gt;, &lt;strong&gt;int&lt;/strong&gt;, etc.) along with attributes decorating the model properties. For instance, in your model you can decorate a property with a &lt;strong&gt;DataType&lt;/strong&gt; attribute to inform the view and the templating system the type of data this property expresses. In the following model, the property Password is decorated as a password data type, while the Bio property is decorated as a multiline text input (which will render a multiline textbox for this property’s editor template).&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;public class MyModel
{
    ...

    [DataType(DataType.Password)]
    public string Password { get; set; }

    [DataType(DataType.MultilineText)]
    public string Bio { get; set; }

    ...
}&lt;/pre&gt;

&lt;p&gt;Specifically, the &lt;strong&gt;Html.DisplayFor&lt;/strong&gt; and &lt;strong&gt;Html.EditorFor&lt;/strong&gt; methods consult the following metadata in this order:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The &lt;strong&gt;UIHint&lt;/strong&gt; attribute - specifies the name of the template to use.&lt;/li&gt;

  &lt;li&gt;The &lt;strong&gt;DataType&lt;/strong&gt; attribute&lt;/li&gt;

  &lt;li&gt;The data type&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Creating a custom template in ASP.NET MVC is a breeze. Simply add &lt;strong&gt;DisplayTemplates&lt;/strong&gt; and &lt;strong&gt;EditorTemplates&lt;/strong&gt; subfolders to the &lt;strong&gt;Views\Shared&lt;/strong&gt; folder. Then add a view file (e.g., &lt;strong&gt;.cshtml&lt;/strong&gt;) to the subfolder with the name of the template. You can override the default templates by naming the template with the same name as the data type to override – such as &lt;strong&gt;String.cshtml&lt;/strong&gt; or &lt;strong&gt;DateTime.cshtml&lt;/strong&gt; – or you can give it a unique name – such as &lt;strong&gt;YesNo.cshtml&lt;/strong&gt; – in which case you specify the template to use via the &lt;strong&gt;UIHint&lt;/strong&gt; attribute. The custom template is a view that defines the incoming model via the &lt;strong&gt;@model&lt;/strong&gt; directive and emits the desired output.&lt;/p&gt;

&lt;h2&gt;&lt;a href="http://nbaweblog.com/images/sowblog/Templates_2B648F0C.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top: 0px; border-right: 0px; padding-top: 0px" title="Templates" border="0" alt="Templates" align="right" src="http://nbaweblog.com/images/sowblog/Templates_thumb_78948897.png" width="218" height="132" /&gt;&lt;/a&gt;Building a Yes/No Template for Boolean Values&lt;/h2&gt;

&lt;p&gt;ASP.NET MVC’s default display template for Boolean values renders a disabled checkbox, but replacing it with the text “Yes” or “No” is quite simple to do when using templates. Start by adding a new template to the &lt;strong&gt;Views\Shared\DisplayTemplates&lt;/strong&gt; folder named &lt;strong&gt;YesNo.cshtml &lt;/strong&gt;with the following content:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;@model bool

@if (Model)
{
    &amp;lt;text&amp;gt;Yes&amp;lt;/text&amp;gt;
}
else
{
    &amp;lt;text&amp;gt;No&amp;lt;/text&amp;gt;
}&lt;/pre&gt;

&lt;p&gt;The display template starts by defining the incoming model’s type (&lt;strong&gt;bool&lt;/strong&gt;) via the &lt;strong&gt;@model&lt;/strong&gt; directive. Next, it emits the literal string “Yes” if the incoming value (&lt;strong&gt;Model&lt;/strong&gt;) is true, “No” otherwise. That’s all there is to it!&lt;/p&gt;

&lt;p&gt;At this point we have the display template defined, but no view will use it unless we specifically instruct it to do so. (In other words, ASP.NET MVC will continue to use its default display template for Boolean values, which is the disabled checkbox.) To instruct a particular model property to use our display template rather than the default, use the &lt;strong&gt;UIHint&lt;/strong&gt; attribute like so:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;public class MyModel
{
    ...

    [UIHint(&amp;quot;YesNo&amp;quot;)]
    public bool ReceiveNewsletter { get; set; }

    ...
}&lt;/pre&gt;

&lt;p&gt;With those two pieces of the puzzle in place – the template itself and the &lt;strong&gt;UIHint&lt;/strong&gt; attribute – a view will render the text “Yes” or “No” when using the following code:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;@Html.DisplayFor(model =&amp;gt; model.ReceiveNewsletter)&lt;/pre&gt;

&lt;p&gt;What about editing? Here we need to create a new template file with the same name (&lt;strong&gt;YesNo.cshtml&lt;/strong&gt;) in the &lt;strong&gt;Views\Shared\EditorTemplates&lt;/strong&gt; folder and then add the following content:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;@model bool

@Html.DropDownList(&amp;quot;&amp;quot;, new SelectListItem[] { new SelectListItem() { Text = &amp;quot;Yes&amp;quot;, Value = &amp;quot;true&amp;quot;, Selected = Model }, new SelectListItem() { Text = &amp;quot;No&amp;quot;, Value = &amp;quot;false&amp;quot;, Selected = !Model }})&lt;/pre&gt;

&lt;p&gt;As with the display template, we start by defining the incoming model’s type (&lt;strong&gt;bool&lt;/strong&gt;) via the &lt;strong&gt;@model&lt;/strong&gt; directive. Then we render a drop-down using the &lt;strong&gt;Html.DropDownList&lt;/strong&gt; method. This drop-down is composed of two select options – Yes and No with the values true and false, respectively. The first item is selected if the incoming value (&lt;strong&gt;Model&lt;/strong&gt;) is true, while the second option is selected if the incoming value is false.&lt;/p&gt;

&lt;p&gt;And we’re done! The screen shot below shows the output of a Boolean value when decorated with the &lt;strong&gt;[UIHint(&amp;quot;YesNo&amp;quot;)]&lt;/strong&gt; attribute and displayed using the &lt;strong&gt;Html.EditorFor&lt;/strong&gt; method.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://nbaweblog.com/images/sowblog/Templates2_57A115F0.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="Templates2" border="0" alt="Templates2" src="http://nbaweblog.com/images/sowblog/Templates2_thumb_29479043.png" width="242" height="97" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy Programming!&lt;/p&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=200696" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><feedburner:origLink>http://scottonwriting.net/sowblog/archive/2011/11/22/using-templates-to-display-boolean-values-as-yes-no-options.aspx</feedburner:origLink></item><item><title>Searching SQL Server Stored Procedure and Trigger Text</title><link>http://feedproxy.google.com/~r/ScottOnWriting/~3/OJn-ghBXXOM/searching-sql-server-stored-procedure-and-trigger-text.aspx</link><pubDate>Fri, 30 Sep 2011 16:16:55 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:196934</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>2</slash:comments><wfw:commentRss>http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=196934</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2011/09/30/searching-sql-server-stored-procedure-and-trigger-text.aspx#comments</comments><description>&lt;p&gt;While I like to consider myself a web developer, every now and then I have to put on my DBA hat to address some SQL related issue. This little script has saved my butt more than once. It searches the text of triggers, UDFs, stored procedures and views for a particular substring, returning the name and type of those database objects that match.&lt;/p&gt;  &lt;pre class="brush: sql;"&gt;DECLARE @Search varchar(255)
SET @Search='text_to_search'

SELECT DISTINCT
    o.name AS Object_Name,o.type_desc
    FROM sys.sql_modules        m 
        INNER JOIN sys.objects  o ON m.object_id=o.object_id
    WHERE m.definition Like '%'+@Search+'%'
    ORDER BY 2,1&lt;/pre&gt;

&lt;p&gt;The above script is one of many in my “bag of scripts” I’ve collected over the years. This particular gem was snagged from Stackoverflow: &lt;a href="http://stackoverflow.com/questions/674623/how-to-find-a-text-inside-sql-server-procedures-triggers/674872#674872"&gt;How to find a text inside SQL Server procedures / triggers?&lt;/a&gt;&lt;/p&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=196934" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/SQL/default.aspx">SQL</category><feedburner:origLink>http://scottonwriting.net/sowblog/archive/2011/09/30/searching-sql-server-stored-procedure-and-trigger-text.aspx</feedburner:origLink></item><item><title>ASP.NET Training in San Diego on Saturday, September 24th</title><link>http://feedproxy.google.com/~r/ScottOnWriting/~3/w87xEzBfJc4/asp-net-training-in-san-diego-on-saturday-september-24th.aspx</link><pubDate>Thu, 15 Sep 2011 18:19:39 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:196040</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=196040</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2011/09/15/asp-net-training-in-san-diego-on-saturday-september-24th.aspx#comments</comments><description>&lt;p&gt;On Saturday September 24th I’ll be doing two four-hour &lt;a href="http://www.asp.net/mvc"&gt;ASP.NET MVC&lt;/a&gt; 3 and Razor training events in San Diego:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;&lt;a href="http://fuzzylogicinc.net/InDepth/Outline.aspx?coid=278f5309-69f6-494f-844d-0f2ef6c4f0b1"&gt;Getting Started with ASP.NET MVC 3 and Razor&lt;/a&gt;&lt;/strong&gt; – (8 AM to Noon) - This four hour morning class introduces ASP.NET MVC 3 and the new Razor view syntax, explores how to build ASP.NET MVC applications, covers key differences between Web Forms and ASP.NET MVC, and highlights the benefits of ASP.NET MVC. It is intended for developers who are interested in getting started with or learning more about ASP.NET MVC 3 and what it has to offer, as well as for developers using ASP.NET MVC 2 who want to see what's new with ASP.NET MVC 3.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;a href="http://fuzzylogicinc.net/InDepth/Outline.aspx?coid=107ae94e-87f7-4ddc-b3f1-7f6af3ac2efe"&gt;Building Real-World Web Applications with ASP.NET MVC 3&lt;/a&gt;&lt;/strong&gt; – (1 to 5 PM) - This four hour afternoon class examines building real-world web applications using ASP.NET MVC 3. Learn how to craft lean controllers that comprise only a few lines of code. See how to use display and editor templates to decouple the user interface from your views. And practice creating rich and expressive view-specific models. Best practices on mapping domain models to view models, on input validation, and other topics will be explored. (This class is intended for students who attended the morning’s &lt;em&gt;Getting Started with ASP.NET MVC and Razor&lt;/em&gt; class or who are already familiar with ASP.NET MVC.)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Both classes will be held at the University City Center office building, which is located on the 805 off the Governor St. exit (directions and map). And for both classes, students receive electronic access and printed copies of the training materials. Parking is free and coffee, snacks and lunch are provided.&lt;/p&gt;  &lt;p&gt;To sign up, or to see a detailed outline for each course, please visit &lt;a href="http://fuzzylogicinc.net/InDepth"&gt;http://fuzzylogicinc.net/InDepth&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Hope to see you there!&lt;/p&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=196040" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><feedburner:origLink>http://scottonwriting.net/sowblog/archive/2011/09/15/asp-net-training-in-san-diego-on-saturday-september-24th.aspx</feedburner:origLink></item><item><title>Full Day ASP.NET MVC 3 Training Event in Los Angeles on August 27th, 2011</title><link>http://feedproxy.google.com/~r/ScottOnWriting/~3/DgXXExNz204/full-day-asp-net-mvc-3-training-event-in-los-angeles-on-august-27th-2011.aspx</link><pubDate>Thu, 18 Aug 2011 04:28:13 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:194551</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=194551</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2011/08/18/full-day-asp-net-mvc-3-training-event-in-los-angeles-on-august-27th-2011.aspx#comments</comments><description>&lt;p&gt;In conjunction with the Los Angeles .NET Developer's Group I will be presenting &lt;a href="http://goo.gl/LQBKp"&gt;a full day, hands-on lab/presentation/training event on ASP.NET MVC 3 Tips, Tricks, and Best Practices on Saturday, August 27th&lt;/a&gt;. The event is a 8 hour training with breakfast and lunch served. Attendees are asked to bring their own laptop and participate in a hands-on session. This event is geared for developers already familiar with ASP.NET MVC.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Event: &lt;/strong&gt;LADOTNET Master Series: ASP.NET MVC3 – Tips, Tricks, and Best Practices with Scott Mitchell    &lt;br /&gt;&lt;strong&gt;Date&lt;/strong&gt;:&lt;strong&gt; &lt;/strong&gt;Saturday, August 27th, 2011    &lt;br /&gt;&lt;strong&gt;Cost:&lt;/strong&gt; $50.00 – &lt;a href="http://goo.gl/LQBKp"&gt;signup&lt;/a&gt;    &lt;br /&gt;&lt;strong&gt;Location:     &lt;br /&gt;&lt;/strong&gt;Outlook Amusements    &lt;br /&gt;2900 W. Alameda Ave, Suite 400    &lt;br /&gt;Burbank, CA 91505    &lt;br /&gt;[&lt;a href="http://www.bing.com/maps/default.aspx?v=2&amp;amp;style=r&amp;amp;lvl=100&amp;amp;where1=2900%20W.%20Alameda%20Ave%2CBurbank%2CCA%2C91505"&gt;Map&lt;/a&gt;]    &lt;br /&gt;&lt;strong&gt;Abstract:&lt;/strong&gt;&amp;#160; &lt;/p&gt;  &lt;p&gt;When building an ASP.NET MVC application developers are faced with a lot of questions. What comprises the Models in MVC? What techniques are available to build simple, yet powerful views? How best to keep your controllers from ballooning in size? And what sort of busywork and tedium can be offloaded to tools?   &lt;br /&gt;&amp;#160; &lt;br /&gt;In this all-day, hands-on event, attendees start with a &amp;quot;baseline&amp;quot; ASP.NET MVC 3 application and together, we will add new features. Along the way we'll explore a variety of tips and best practices. We'll encounter pain points and discuss and implement various solutions. Topics will range from high-level, over-arching ones like options for building a domain model and persistence layer, to ones very specific to ASP.NET MVC, like creating and using custom display and editor templates in your views. And there will be plenty of hands-on experience with popular open source tools like AutoMapper.    &lt;br /&gt;&amp;#160; &lt;br /&gt;This talk is tailored for developers who are already familiar with core ASP.NET MVC concepts and are comfortable building ASP.NET MVC applications.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Signup at:&lt;/strong&gt; &lt;a href="http://mastersseries004.eventbrite.com/"&gt;http://mastersseries004.eventbrite.com/&lt;/a&gt;&lt;/p&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=194551" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><feedburner:origLink>http://scottonwriting.net/sowblog/archive/2011/08/18/full-day-asp-net-mvc-3-training-event-in-los-angeles-on-august-27th-2011.aspx</feedburner:origLink></item><item><title>Creating a Currency Masked TextBox with On-the-Fly Currency Formatting</title><link>http://feedproxy.google.com/~r/ScottOnWriting/~3/MNQiPQ8pWDE/creating-a-currency-masked-textbox-with-on-the-fly-currency-formatting.aspx</link><pubDate>Fri, 24 Jun 2011 23:21:54 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:189984</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=189984</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2011/06/25/creating-a-currency-masked-textbox-with-on-the-fly-currency-formatting.aspx#comments</comments><description>&lt;p&gt;By default, a user can enter any character into a textbox. Masked textboxes help reduce user input error by limiting what characters a user can type into a textbox. Masked textboxes have been a standard user input element in desktop applications for decades, but are less common in web applications for a variety of reasons. However, it’s not terribly difficult to implement masked textboxes. All that’s required is a touch of JavaScript and a sprinkle of jQuery.&lt;/p&gt;  &lt;p&gt;In a recent project the client wanted a masked textbox for the textboxes on the page collecting currency information. Moreover, he wanted the user’s input to automatically be displayed as a formatted currency value in the textbox after entering their value. (Check out &lt;a href="http://jsfiddle.net/CBDea/1/"&gt;a live demo&lt;/a&gt; of my script…) But first things first, let’s see how to create a currency masked textbox.&lt;/p&gt;  &lt;h2&gt;&lt;/h2&gt;  &lt;h2&gt;Allowing Only Currency-Related Characters In a TextBox&lt;/h2&gt;  &lt;p&gt;There are a number of existing masked input plugins for jQuery. After trying some out I decided to roll my own JavaScript functions. I intend to come back to these and turn them into jQuery plugins, but for now they’re just JavaScript functions. As you can see in the script below, I created four functions:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;numbersOnly&lt;/strong&gt; – allows just number inputs, whether they are from the letters at the top of the keyboard or from the number pad.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;numbersAndCommasOnly &lt;/strong&gt;– allows number inputs and commas.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;decimalsOnly&lt;/strong&gt; – allows numbers, commas, and periods (either from the main keyboard or the number pad).&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;currenciesOnly&lt;/strong&gt; – allows numbers, commas, periods, and the dollar sign.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;In addition to the allowed characters discussed above, the functions also permit “special character key codes,” namely Delete, Backspace, left arrow, right arrow, Home, End and Tab. What keycodes are valid are listed in the variables at the top of the script; see &lt;a href="http://www.cambiaresearch.com/c4/702b8cd1-e5b0-42e6-83ac-25f0306e3e25/Javascript-Char-Codes-Key-Codes.aspx"&gt;Javascript Char Codes&lt;/a&gt; for a table listing the keys and their corresponding key codes.&lt;/p&gt;  &lt;p&gt;Here is the script of interest:&lt;/p&gt;  &lt;pre class="brush: js;"&gt;// JavaScript I wrote to limit what types of input are allowed to be keyed into a textbox 
var allowedSpecialCharKeyCodes = [46,8,37,39,35,36,9];
var numberKeyCodes = [44, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105];
var commaKeyCode = [188];
var decimalKeyCode = [190,110];

function numbersOnly(event) {
    var legalKeyCode =
        (!event.shiftKey &amp;amp;&amp;amp; !event.ctrlKey &amp;amp;&amp;amp; !event.altKey)
            &amp;amp;&amp;amp;
        (jQuery.inArray(event.keyCode, allowedSpecialCharKeyCodes) &amp;gt;= 0
            ||
        jQuery.inArray(event.keyCode, numberKeyCodes) &amp;gt;= 0);

    if (legalKeyCode === false)
        event.preventDefault();
}

function numbersAndCommasOnly(event) {
    var legalKeyCode =
        (!event.shiftKey &amp;amp;&amp;amp; !event.ctrlKey &amp;amp;&amp;amp; !event.altKey)
            &amp;amp;&amp;amp;
        (jQuery.inArray(event.keyCode, allowedSpecialCharKeyCodes) &amp;gt;= 0
            ||
        jQuery.inArray(event.keyCode, numberKeyCodes) &amp;gt;= 0
            ||
        jQuery.inArray(event.keyCode, commaKeyCode) &amp;gt;= 0);

    if (legalKeyCode === false)
        event.preventDefault();
}

function decimalsOnly(event) {
    var legalKeyCode =
        (!event.shiftKey &amp;amp;&amp;amp; !event.ctrlKey &amp;amp;&amp;amp; !event.altKey)
            &amp;amp;&amp;amp;
        (jQuery.inArray(event.keyCode, allowedSpecialCharKeyCodes) &amp;gt;= 0
            ||
        jQuery.inArray(event.keyCode, numberKeyCodes) &amp;gt;= 0
            ||
        jQuery.inArray(event.keyCode, commaKeyCode) &amp;gt;= 0
            ||
        jQuery.inArray(event.keyCode, decimalKeyCode) &amp;gt;= 0);

    if (legalKeyCode === false)
        event.preventDefault();
}

function currenciesOnly(event) {
    var legalKeyCode =
        (!event.shiftKey &amp;amp;&amp;amp; !event.ctrlKey &amp;amp;&amp;amp; !event.altKey)
            &amp;amp;&amp;amp;
        (jQuery.inArray(event.keyCode, allowedSpecialCharKeyCodes) &amp;gt;= 0
            ||
        jQuery.inArray(event.keyCode, numberKeyCodes) &amp;gt;= 0
            ||
        jQuery.inArray(event.keyCode, commaKeyCode) &amp;gt;= 0
            ||
        jQuery.inArray(event.keyCode, decimalKeyCode) &amp;gt;= 0);

    // Allow for $
    if (!legalKeyCode &amp;amp;&amp;amp; event.shiftKey &amp;amp;&amp;amp; event.keyCode == 52)
        legalKeyCode = true;

    if (legalKeyCode === false)
        event.preventDefault();
}&lt;/pre&gt;

&lt;p&gt;My script is, admittedly, very US-centric. I have not tested the key codes with a non-English keyboard and for currencies I only allow a dollar sign. For the project I wrote this script for this is (currently) a non-issue since it is used within the corporate firewall and all sales are domestic, but clearly the above script would not work as well for international settings.&lt;/p&gt;

&lt;h2&gt;Applying the Currency Masking Script to a TextBox on the Page&lt;/h2&gt;

&lt;p&gt;With the above script in place you can have a textbox on the page mask its input by having the appropriate function called in response to the &lt;strong&gt;keydown&lt;/strong&gt; event. The following jQuery syntax wires up this logic to all single-line textboxes that have the CSS class &lt;strong&gt;currenciesOnly&lt;/strong&gt;.&lt;/p&gt;

&lt;pre class="brush: js;"&gt;$(document).ready(function () {
    $(&amp;quot;input[type=text].currenciesOnly&amp;quot;).live('keydown', currenciesOnly);
});&lt;/pre&gt;

&lt;p&gt;That’s it!&lt;/p&gt;

&lt;h2&gt;Formatting the Just-Entered Currency&lt;/h2&gt;

&lt;p&gt;Another requirement my client had was to format the just-entered number as a currency. That is, to change the user’s input – say, 45000 – to a formatted value like $45,000.00 immediately after their tabbed out of the textbox. To accomplish this I used &lt;a href="http://www.bendewey.com/blog/"&gt;Ben Dewey&lt;/a&gt;’s &lt;a href="http://code.google.com/p/jquery-formatcurrency/"&gt;jQuery Format Currency Plugin&lt;/a&gt;, which you can see a demo of at &lt;a href="http://www.bendewey.com/code/formatcurrency/demo/"&gt;http://www.bendewey.com/code/formatcurrency/demo/&lt;/a&gt;. This plugin adds a &lt;strong&gt;formatCurrency&lt;/strong&gt; function that you can call on a set of elements returned by a jQuery selector.&lt;/p&gt;

&lt;p&gt;To use this plugin I updated the &lt;strong&gt;$(document).ready&lt;/strong&gt; event handler shown above to also call the &lt;strong&gt;formatCurrency&lt;/strong&gt; function on &lt;strong&gt;blur&lt;/strong&gt;:&lt;/p&gt;

&lt;pre class="brush: js;"&gt;$(document).ready(function () {
    $(&amp;quot;input[type=text].currenciesOnly&amp;quot;).live('keydown', currenciesOnly)
                        .live('blur', 
                                 function () { 
                                     $(this).formatCurrency(); 
                                 }
                              );
});&lt;/pre&gt;

&lt;p&gt;In short, whenever a textbox with a CSS class of &lt;strong&gt;currenciesOnly&lt;/strong&gt; is blurred, the just-blurred textbox’s inputs are formatted as a currency thanks to the &lt;strong&gt;formatCurrency&lt;/strong&gt; function.&lt;/p&gt;

&lt;p&gt;And that’s all there is to it, folks.&lt;/p&gt;

&lt;p align="center"&gt;&lt;font size="5"&gt;To see a live demo of the above code, check out this jsfiddle script: &lt;/font&gt;&lt;a href="http://jsfiddle.net/CBDea/1/"&gt;&lt;font size="5"&gt;http://jsfiddle.net/CBDea/1/&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy Programming!&lt;/p&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=189984" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/jQuery/default.aspx">jQuery</category><feedburner:origLink>http://scottonwriting.net/sowblog/archive/2011/06/25/creating-a-currency-masked-textbox-with-on-the-fly-currency-formatting.aspx</feedburner:origLink></item><item><title>A Synchronized Visual Studio Crash</title><link>http://feedproxy.google.com/~r/ScottOnWriting/~3/hnZqTIBS4FY/a-synchronized-visual-studio-crash.aspx</link><pubDate>Mon, 20 Jun 2011 19:52:17 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:189648</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=189648</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2011/06/20/a-synchronized-visual-studio-crash.aspx#comments</comments><description>&lt;p&gt;About month ago at a user group meeting the guy sitting across from me shared the tale of a talk he had attended. The speaker’s laptop had downloaded a slew of Windows Updates in the background, after which the “Restart your computer to finish installing important updates” dialog box appeared. The speaker unwittingly clicked the “Restart now” button, which closed the presentation and displayed those ominous words: “Please do not power off or unplug your machine… Installing update 1 of 43.” But how many speakers have the distinction of not only crashing their own system, but in addition the laptops of dozens of others in the audience? I am now among those hallowed ranks.&lt;/p&gt;  &lt;p&gt;On Saturday I presented another &lt;a href="http://scottonwriting.net/sowblog/archive/2011/05/12/full-day-asp-net-mvc-3-training-event-in-los-angeles-on-may-21st-2011.aspx"&gt;full-day ASP.NET MVC 3 training event&lt;/a&gt; in Los Angeles. Attendees were encouraged to bring their laptops and to follow along as I presented the material. At one point, I was creating a demo and writing some HTML in the &lt;strong&gt;_Layout.cshtml&lt;/strong&gt; file. After typing in some HTML I switched from the &lt;strong&gt;_Layout.cshtml&lt;/strong&gt; file to a controller at which point Visual Studio froze on me. Hard. And with vengeance. I quickly apologized and launched Windows Task Manager to kill VS and restart it.&lt;/p&gt;  &lt;p&gt;As Visual Studio was restarting I heard a rising murmur from the crowd – many other people just had Visual Studio crash on them, too! Several people were following along with me key stroke for key stroke and had experienced the same crash. Lovely. I asked the audience to humor me and I tried to reproduce the crash again, but had no luck. But clearly whatever sequence of events caused Visual Studio to crash was deterministic seeing that several other people had the same experience when following the same steps.&lt;/p&gt;  &lt;p&gt;So the next time you are at a conference or user group and are swapping stories of speaker flubs or miscues, feel free to tell them about this one guy who not only crashed his own demo, but was so bad that also he crashed dozens of other laptops in the audience.&lt;/p&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=189648" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/Miscellaneous/default.aspx">Miscellaneous</category><feedburner:origLink>http://scottonwriting.net/sowblog/archive/2011/06/20/a-synchronized-visual-studio-crash.aspx</feedburner:origLink></item><item><title>Export an ADO.NET DataTable to Excel using NPOI</title><link>http://feedproxy.google.com/~r/ScottOnWriting/~3/wpy1YhxfAnA/export-an-ado-net-datatable-to-excel-using-npoi.aspx</link><pubDate>Tue, 07 Jun 2011 23:10:41 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:188924</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=188924</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2011/06/08/export-an-ado-net-datatable-to-excel-using-npoi.aspx#comments</comments><description>&lt;p&gt;My latest article on &lt;a href="http://dotnetslackers.com/"&gt;DotNetSlackers&lt;/a&gt; looks at how to &lt;a href="http://dotnetslackers.com/articles/aspnet/Create-Excel-Spreadsheets-Using-NPOI.aspx"&gt;create Excel spreadsheets using NPOI&lt;/a&gt;. &lt;a href="http://npoi.codeplex.com/"&gt;NPOI&lt;/a&gt; is a free, open-source .NET library for creating and reading Excel spreadsheets and is a port of the &lt;a href="http://poi.apache.org/"&gt;Java POI library&lt;/a&gt;. In the article I show how to use NPOI to programmatically export data into a spreadsheet with multiple sheets, formatting, and so on. Specifically, my demos look at having a set of objects to export – for example, a set of Linq-to-Sql entity objects – and then crafting an Excel spreadsheet by enumerating those objects and adding applicable rows and columns to the spreadsheet.&lt;/p&gt;  &lt;p&gt;Recently, I needed the ability to allow for more generic exports to Excel. In one of the web applications I work on there is an Excel Export page that offers a number of links that, when clicked, populate an ADO.NET DataTable with the results of a particular database view, generate a &lt;a href="http://en.wikipedia.org/wiki/Comma-separated_values"&gt;CSV file&lt;/a&gt;, and then stream that file down to the client with a &lt;strong&gt;Content-Type&lt;/strong&gt; of &lt;strong&gt;application/vnd.ms-excel&lt;/strong&gt;, which prompts the browser to display the CSV content in Excel. This has worked well enough over the years, but unfortunately such data cannot be viewed from the iPad; however, the iPad can display a native Excel file (&lt;strong&gt;.xls&lt;/strong&gt;). The solution, then, was to update the code to use NPOI to return an actual Excel spreadsheet rather than a CSV file.&lt;/p&gt;  &lt;p&gt;To accomplish this I wrote a bit of code that exports the contents of any ol’ DataTable into an Excel spreadsheet using NPOI. It’s pretty straightforward, looping through the rows of the DataTable and adding each as a row to the Excel spreadsheet. There were, however, a couple of gotcha points:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Excel 2003 limits a sheet inside a workbook to a maximum of 65,535 rows. To export more rows than this you need to use multiple sheets. &lt;a href="http://www.zachhunter.com/"&gt;Zach Hunter&lt;/a&gt;’s blog entry, &lt;a href="http://www.zachhunter.com/2010/05/npoi-excel-2003-row-limit/"&gt;NPOI and the Excel 2003 Row Limit&lt;/a&gt;, provided a simple approach to avoiding this problem. In short, I keep track of how many rows I’ve added to the current sheet and once it exceeds a certain threshold I create a new sheet and start from the top.&lt;/li&gt;    &lt;li&gt;Excel has limits and restrictions on the length of sheet names and what characters can appear in a sheet name. I have a method named &lt;strong&gt;EscapeSheetName&lt;/strong&gt; that ensures the sheet name is of a valid length and does not contain any offending characters.&lt;/li&gt;    &lt;li&gt;When exporting very large Excel spreadsheets you may bump into &lt;strong&gt;OutOfMemoryException&lt;/strong&gt;s if you are developing on a 32-bit system and are trying to dump the Excel spreadsheet into a &lt;strong&gt;MemoryStream&lt;/strong&gt; object, which is a common technique for streaming the data to the client. See this Stackoverflow discussion for more information and possible workarounds: &lt;strong&gt;&lt;a href="http://stackoverflow.com/questions/6270430/outofmemoryexception-when-generating-a-large-excel-spreadsheet"&gt;OutOfMemoryException When Generating a Large Excel Spreadsheet&lt;/a&gt;&lt;/strong&gt;.&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;To demonstrate exporting a DataTable to Excel using NPOI, I augmented the code demo available for download from my DotNetSlackers article to include a new class in the &lt;strong&gt;App_Code&lt;/strong&gt; folder named &lt;strong&gt;NPoiExport&lt;/strong&gt;, which you can download from &lt;a href="http://scottonwriting.net/demos/ExcelExportToDataTable.zip"&gt;http://scottonwriting.net/demos/ExcelExportToDataTable.zip&lt;/a&gt;. This class offers an &lt;strong&gt;ExportDataTableToWorkbook&lt;/strong&gt; method that takes as input a DataTable and the sheet name to use for the Excel workbook. (If there are multiple sheets needed, the second sheet is named “&lt;em&gt;sheetName&lt;/em&gt; – 2,” the third, “&lt;em&gt;sheetName&lt;/em&gt; – 3,” and so forth.)&lt;/p&gt;  &lt;p&gt;The &lt;strong&gt;ExportDataTableToWorkbook&lt;/strong&gt; method follows:&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;public void ExportDataTableToWorkbook(DataTable exportData, string sheetName)
{
    // Create the header row cell style
    var headerLabelCellStyle = this.Workbook.CreateCellStyle();
    headerLabelCellStyle.BorderBottom = CellBorderType.THIN;
    var headerLabelFont = this.Workbook.CreateFont();
    headerLabelFont.Boldweight = (short)FontBoldWeight.BOLD;
    headerLabelCellStyle.SetFont(headerLabelFont);

    var sheet = CreateExportDataTableSheetAndHeaderRow(exportData, sheetName, headerLabelCellStyle);
    var currentNPOIRowIndex = 1;
    var sheetCount = 1;

    for (var rowIndex = 0; rowIndex &amp;lt; exportData.Rows.Count; rowIndex++)
    {
        if (currentNPOIRowIndex &amp;gt;= MaximumNumberOfRowsPerSheet)
        {
            sheetCount++;
            currentNPOIRowIndex = 1;

            sheet = CreateExportDataTableSheetAndHeaderRow(exportData, 
                                                            sheetName + &amp;quot; - &amp;quot; + sheetCount, 
                                                            headerLabelCellStyle);
        }

        var row = sheet.CreateRow(currentNPOIRowIndex++);

        for (var colIndex = 0; colIndex &amp;lt; exportData.Columns.Count; colIndex++)
        {
            var cell = row.CreateCell(colIndex);
            cell.SetCellValue(exportData.Rows[rowIndex][colIndex].ToString());
        }
    }
}&lt;/pre&gt;

&lt;p&gt;Whenever a new sheet needs to be generated – either when starting or when the maximum number of rows per sheet is exceeded – the &lt;strong&gt;CreateExportDataTableSheetAndHeaderRow&lt;/strong&gt; method is called. This method creates a header row, listing the name of each column in the DataTable.&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;protected Sheet CreateExportDataTableSheetAndHeaderRow(DataTable exportData, string sheetName, CellStyle headerRowStyle)
{
    var sheet = this.Workbook.CreateSheet(EscapeSheetName(sheetName));

    // Create the header row
    var row = sheet.CreateRow(0);

    for (var colIndex = 0; colIndex &amp;lt; exportData.Columns.Count; colIndex++)
    {
        var cell = row.CreateCell(colIndex);
        cell.SetCellValue(exportData.Columns[colIndex].ColumnName);

        if (headerRowStyle != null)
            cell.CellStyle = headerRowStyle;
    }

    return sheet;
}&lt;/pre&gt;

&lt;p&gt;Here’s how you would go about using the &lt;strong&gt;NpoiExport&lt;/strong&gt; class to export a DataTable and then stream it down to the client:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Create and populate the DataTable with the data to export. Remember, the DataTable’s column names are what will appear in the header row so use aliases in the SQL query to provide more description/formatted column names, if you prefer.&lt;/li&gt;

  &lt;li&gt;Create an instance of the NpoiExport class.&lt;/li&gt;

  &lt;li&gt;Call the object’s &lt;strong&gt;ExportDataTableToWorkbook&lt;/strong&gt; method passing in the DataTable from step 1 (along with a sheet name of your choice).&lt;/li&gt;

  &lt;li&gt;Set the &lt;strong&gt;Content-Type&lt;/strong&gt; and &lt;strong&gt;Content-Disposition &lt;/strong&gt;response headers appropriately and then stream down the contents of the Excel document, which is accessible via the &lt;strong&gt;NpoiExport&lt;/strong&gt; object’s &lt;strong&gt;GetBytes&lt;/strong&gt; method.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The following code snippet illustrates the above four steps.&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;// Populate the DataTable
var myDataTable = new DataTable();
using (var myConnection = new SqlConnection(connectionString)
{
    using (var myCommand = new SqlCommand())
    {
        myCommand.Connection = myConnection;
        myCommand.CommandText = sqlQuery;

        using (var myAdapter = new SqlDataAdapter(myCommand))
        {
            myAdapter.Fill(myDataTable);
        }
    }
}


// Creat the NpoiExport object
using (var exporter = new NpoiExport())
{
    exporter.ExportDataTableToWorkbook(myDataTable, &amp;quot;Results&amp;quot;);

    string saveAsFileName = string.Format(&amp;quot;Results-{0:d}.xls&amp;quot;, DateTime.Now);

    Response.ContentType = &amp;quot;application/vnd.ms-excel&amp;quot;;
    Response.AddHeader(&amp;quot;Content-Disposition&amp;quot;, string.Format(&amp;quot;attachment;filename={0}&amp;quot;, saveAsFileName));
    Response.Clear();
    Response.BinaryWrite(exporter.GetBytes());
    Response.End();
}&lt;/pre&gt;

&lt;p&gt;That’s all there is to it. The screen shot below shows an example of the exported report. Note that it lacks the nice formatting, auto-sized columns, and other bells and whistles that are possible with NPOI when constructing a report by hand (as I showed in &lt;a href="http://dotnetslackers.com/articles/aspnet/Create-Excel-Spreadsheets-Using-NPOI.aspx"&gt;Create Excel Spreadsheets Using NPOI&lt;/a&gt;), but it does make exporting data to Excel an exercise of just a few lines of code. And its exported data that can be opened and viewed from an iPad.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://nbaweblog.com/images/sowblog/ExcelOutput_1CF187F3.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="ExcelOutput" border="0" alt="ExcelOutput" src="http://nbaweblog.com/images/sowblog/ExcelOutput_thumb_108364CA.png" width="644" height="460" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above Excel spreadsheet was created using the ad-hoc query:&lt;/p&gt;

&lt;pre class="brush: sql;"&gt;SELECT CategoryName AS [Category], 
       Description, 
       (SELECT COUNT(*) 
        FROM Products 
        WHERE Products.CategoryID = Categories.CategoryID) 
            AS [Product Count]
FROM Categories
WHERE CategoryID &amp;gt;= 3&lt;/pre&gt;

&lt;p&gt;Happy Programming!&lt;/p&gt;

&lt;p&gt;&lt;font size="4"&gt;&lt;strong&gt;Download:&lt;/strong&gt; &lt;/font&gt;&lt;a href="http://scottonwriting.net/demos/ExcelExportToDataTable.zip"&gt;&lt;font size="4"&gt;http://scottonwriting.net/demos/ExcelExportToDataTable.zip&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=188924" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/ASP.NET+Talk/default.aspx">ASP.NET Talk</category><feedburner:origLink>http://scottonwriting.net/sowblog/archive/2011/06/08/export-an-ado-net-datatable-to-excel-using-npoi.aspx</feedburner:origLink></item><item><title>Full Day ASP.NET MVC 3 Training Event in Los Angeles on May 21st, 2011</title><link>http://feedproxy.google.com/~r/ScottOnWriting/~3/-cwMG7Us-Hk/full-day-asp-net-mvc-3-training-event-in-los-angeles-on-may-21st-2011.aspx</link><pubDate>Thu, 12 May 2011 16:57:09 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:187195</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>3</slash:comments><wfw:commentRss>http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=187195</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2011/05/12/full-day-asp-net-mvc-3-training-event-in-los-angeles-on-may-21st-2011.aspx#comments</comments><description>&lt;p&gt;In conjunction with the Los Angeles .NET Developer's Group I will be presenting &lt;a href="http://www.eventbrite.com/event/1553162551?utm_source=eb_email&amp;amp;utm_medium=email&amp;amp;utm_campaign=new_eventv2&amp;amp;utm_term=eventurl_text"&gt;a full day, hands-on lab and training event on ASP.NET MVC 3 on Saturday, May 21st&lt;/a&gt;. The event is a 8 hour training with breakfast and lunch served. Attendees are asked to bring their own laptop and participate in a hands-on session. This event is geared for intermediate to experienced web developers new to ASP.NET MVC (or just new to ASP.NET MVC 3 and the Razor syntax). &lt;/p&gt;  &lt;p&gt;Over the course of the day we’ll explore MVC fundamentals, step through the process of building an ASP.NET MVC application, and implement common web application scenarios, such as: creating master/detail reports; working with forms; and building Create/Read/Update/Delete screens (CRUD). We’ll also explore interesting and powerful ASP.NET MVC tools and features, including scaffolding, partial views, layouts and layout sections, and more.&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;strong&gt;Event: &lt;/strong&gt;LADOTNET Master Series: ASP.NET MVC3 with Scott Mitchell      &lt;br /&gt;&lt;strong&gt;Date&lt;/strong&gt;:&lt;strong&gt; &lt;/strong&gt;Saturday, May 21st, 2011      &lt;br /&gt;&lt;strong&gt;Cost:&lt;/strong&gt; $50.00 – &lt;/font&gt;&lt;a href="http://www.eventbrite.com/event/1553162551?utm_source=eb_email&amp;amp;utm_medium=email&amp;amp;utm_campaign=new_eventv2&amp;amp;utm_term=eventurl_text"&gt;&lt;font size="4"&gt;signup&lt;/font&gt;&lt;/a&gt;    &lt;br /&gt;&lt;font size="4"&gt;&lt;strong&gt;Location:       &lt;br /&gt;&lt;/strong&gt;Outlook Amusements      &lt;br /&gt;2900 W. Alameda Ave, Suite 400      &lt;br /&gt;Burbank, CA 91505      &lt;br /&gt;[&lt;/font&gt;&lt;a href="http://www.bing.com/maps/default.aspx?v=2&amp;amp;style=r&amp;amp;lvl=100&amp;amp;where1=2900%20W.%20Alameda%20Ave%2CBurbank%2CCA%2C91505"&gt;&lt;font size="4"&gt;Map&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;]     &lt;br /&gt;&lt;strong&gt;Abstract:&lt;/strong&gt;&amp;#160; In this all-day, hands-on event attendees will build a complete, functional and interesting data-driven website over the course of the day using Microsoft's ASP.NET MVC 3 framework and the new Razor syntax.      &lt;br /&gt;&lt;strong&gt;Signup at:&lt;/strong&gt; &lt;/font&gt;&lt;a href="http://www.eventbrite.com/event/1553162551?utm_source=eb_email&amp;amp;utm_medium=email&amp;amp;utm_campaign=new_eventv2&amp;amp;utm_term=eventurl_text"&gt;&lt;font size="4"&gt;http://www.eventbrite.com/event/1553162551?utm_source=eb_email&amp;amp;utm_medium=email&amp;amp;utm_campaign=new_eventv2&amp;amp;utm_term=eventurl_text&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Hope to see you there!&lt;/p&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=187195" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><feedburner:origLink>http://scottonwriting.net/sowblog/archive/2011/05/12/full-day-asp-net-mvc-3-training-event-in-los-angeles-on-may-21st-2011.aspx</feedburner:origLink></item><item><title>Terse Markup and CSS for Aligned Form Labels and Inputs</title><link>http://feedproxy.google.com/~r/ScottOnWriting/~3/DigA1oy934o/terse-markup-and-css-for-aligned-form-labels-and-inputs.aspx</link><pubDate>Mon, 18 Apr 2011 17:46:39 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:184937</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>3</slash:comments><wfw:commentRss>http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=184937</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2011/04/18/terse-markup-and-css-for-aligned-form-labels-and-inputs.aspx#comments</comments><description>&lt;p&gt;Like many ASP.NET developers, I am most comfortable working with C# and VB. I know just enough HTML and CSS to be dangerous. I know enough to implement the overarching page layout without using &lt;strong&gt;&amp;lt;table&amp;gt;&lt;/strong&gt;s and instead to use CSS to position, size, and float the elements on the page, but when it comes to certain user interface designs within a page I’m quick to use &lt;strong&gt;&amp;lt;table&amp;gt;&lt;/strong&gt;s. For instance, if asked to create a contact form like the one pictured below, my first inclination would be to use a trusty &lt;strong&gt;&amp;lt;table&amp;gt;&lt;/strong&gt;. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://nbaweblog.com/images/sowblog/AlignedUI_69BB15DD.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="AlignedUI" border="0" alt="AlignedUI" src="http://nbaweblog.com/images/sowblog/AlignedUI_thumb_2918C96E.png" width="437" height="215" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Recently, my friend and colleague &lt;a href="http://yatesdigital.com/"&gt;Dave Yates&lt;/a&gt; showed me a website he had helped design and implement, &lt;a href="http://www.stonehengestyle.com"&gt;StonehengeStyle&lt;/a&gt;. I was particularly interested when Dave showed me the &lt;a href="http://www.stonehengestyle.com/contact_us.php"&gt;contact page&lt;/a&gt;, which contained very clean, terse, readable markup without the use of &lt;strong&gt;&amp;lt;table&amp;gt;&lt;/strong&gt;s.&lt;/p&gt;  &lt;p&gt;First, each right-aligned text label – Name, Phone, and so on - is implemented as a &lt;strong&gt;&amp;lt;label&amp;gt;&lt;/strong&gt; element. The input elements for collecting the input are simply &lt;strong&gt;&amp;lt;input&amp;gt;&lt;/strong&gt;, &lt;strong&gt;&amp;lt;textarea&amp;gt;&lt;/strong&gt; or &lt;strong&gt;&amp;lt;select&amp;gt;&lt;/strong&gt; elements. For example, the markup for the Name, Phone, and Email Address inputs follows. (Note: I removed the required indicator for brevity; view the contact form’s markup in your browser for the complete markup.)&lt;/p&gt;  &lt;pre class="brush: xml;"&gt;&amp;lt;label for=&amp;quot;name&amp;quot;&amp;gt;Name&amp;lt;/label&amp;gt; 
&amp;lt;input name=&amp;quot;name&amp;quot; type=&amp;quot;text&amp;quot; id=&amp;quot;name&amp;quot; class=&amp;quot;textfield&amp;quot; /&amp;gt; 

&amp;lt;label for=&amp;quot;phone&amp;quot;&amp;gt;Phone&amp;lt;/label&amp;gt; 
&amp;lt;input name=&amp;quot;phone&amp;quot; type=&amp;quot;text&amp;quot; id=&amp;quot;phone&amp;quot; class=&amp;quot;textfield&amp;quot; /&amp;gt; 

&amp;lt;label for=&amp;quot;email&amp;quot;&amp;gt;Email Address&amp;lt;/label&amp;gt; 
&amp;lt;input name=&amp;quot;email&amp;quot; type=&amp;quot;text&amp;quot; id=&amp;quot;email&amp;quot; class=&amp;quot;textfield&amp;quot; /&amp;gt; &lt;/pre&gt;

&lt;p&gt;Couldn’t be simpler, right? No filler &lt;strong&gt;&amp;lt;br /&amp;gt;&lt;/strong&gt; or &lt;strong&gt;&amp;lt;p&amp;gt; &lt;/strong&gt;elements, no &lt;strong&gt;&amp;lt;table&amp;gt;&lt;/strong&gt;s cluttering things up. Heck, no &lt;strong&gt;&amp;lt;div&amp;gt;&lt;/strong&gt;s, even.&lt;/p&gt;

&lt;p&gt;The layout of the &lt;strong&gt;&amp;lt;label&amp;gt;&lt;/strong&gt; and &lt;strong&gt;&amp;lt;input&amp;gt;&lt;/strong&gt; elements is handled in the CSS via the following rules. First, all &lt;strong&gt;&amp;lt;label&amp;gt;&lt;/strong&gt; elements are styled such that they are 180 pixels wide with 3 pixel padding on the top, 10 pixel padding on the right, and 2 pixel padding on the bottom. Their text is right-aligned and they clear left floating elements, which is why each &lt;strong&gt;&amp;lt;label&amp;gt;&lt;/strong&gt; appears beneath the one above it.&lt;/p&gt;

&lt;pre class="brush: css;"&gt;label {
    clear: left;
    float: left;
    padding: 3px 10px 2px;
    text-align: right;
    width: 180px;
}&lt;/pre&gt;

&lt;p&gt;The &lt;strong&gt;textfield&lt;/strong&gt;, &lt;strong&gt;textarea&lt;/strong&gt;, and &lt;strong&gt;selectlist&lt;/strong&gt; CSS classes, which assigned to &lt;strong&gt;&amp;lt;input&amp;gt;&lt;/strong&gt;, &lt;strong&gt;&amp;lt;textarea&amp;gt;&lt;/strong&gt;, and &lt;strong&gt;&amp;lt;select&amp;gt;&lt;/strong&gt; elements in this contact form, specify a width of 250 pixels with a bottom margin of 8 pixels.&lt;/p&gt;

&lt;pre class="brush: css;"&gt;.textfield, .textarea, .selectlist {
    font-family: Arial,Helvetica,sans-serif;
    font-size: 12px;
    margin: 0 0 8px;
    width: 250px;
}&lt;/pre&gt;

&lt;p&gt;And that’s all there is to it! Pretty simple and straightforward.&lt;/p&gt;

&lt;p&gt;This may not be terribly exciting for seasoned web developers or designers, but for someone like me, with just a working knowledge of HTML and CSS, this markup/CSS pattern is a gem and is how I’ve started doing my contact forms and other similar in-page layouts.&lt;/p&gt;

&lt;p&gt;Happy Programming!&lt;/p&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=184937" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/ASP.NET+Talk/default.aspx">ASP.NET Talk</category><feedburner:origLink>http://scottonwriting.net/sowblog/archive/2011/04/18/terse-markup-and-css-for-aligned-form-labels-and-inputs.aspx</feedburner:origLink></item><item><title>I’ve Written My Last Article for 4GuysFromRolla</title><link>http://feedproxy.google.com/~r/ScottOnWriting/~3/zrPfQdfmfGM/i-ve-written-my-last-article-for-4guysfromrolla.aspx</link><pubDate>Tue, 29 Mar 2011 19:32:48 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:183641</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>118</slash:comments><wfw:commentRss>http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=183641</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2011/03/29/i-ve-written-my-last-article-for-4guysfromrolla.aspx#comments</comments><description>&lt;p&gt;&lt;font color="#ff0000"&gt;&lt;strong&gt;Warning!&lt;/strong&gt; This blog post is long and rife with navel-gazing.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;In 1998 I started an ASP resource site, 4GuysFromRolla.com. Toward the tail end of the dotcom boom I sold 4Guys to &lt;a href="http://internet.com/"&gt;Internet.com&lt;/a&gt;, but continued working as the editor and primary contributor for the site, writing a new article each week. This arrangement continued until just recently. My last article for 4Guys has been written – &lt;em&gt;&lt;a href="http://www.4guysfromrolla.com/articles/031611-1.aspx"&gt;Use MvcContrib Grid to Display a Grid of Data in ASP.NET MVC&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;  &lt;h2&gt;The Beginnings&lt;/h2&gt;  &lt;p&gt;My first exposure to web programming came in 1998 working at Empower Trainers and Consultants, a mid-sized consulting and training firm with locations in Kansas City, St. Louis, and Nashville. At the time I was an inexperienced, nervous, 19 year old sophomore at the &lt;a href="http://mst.edu/"&gt;University of Missouri-Rolla&lt;/a&gt; (UMR) who had landed an 8-month internship with Empower at their Kansas City location. My first assignment was to add some new features to the internal timekeeping tool, a custom-build data-driven web application powered by SQL Server and ASP. At the time I had done some rudimentary HTML development, but had zero experience with JavaScript, ASP, and SQL.&lt;/p&gt;  &lt;p&gt;Needless to say, I found ASP enthralling. The ability to quickly create an application that could be shared with the world amazed me then as it continues to amaze me to this day. At the time there weren’t many online resources for learning more about ASP. As my internship drew to an end I decided that once I got back to school I would start my own site rich with ASP information.&lt;/p&gt;  &lt;p&gt;Upon returning to university I cajoled three good friends into starting a website, 4GuysFromRolla.com. The idea was that the site would boast four sections:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;ASP Information &lt;/li&gt;    &lt;li&gt;Programming Information &lt;/li&gt;    &lt;li&gt;Linux Information &lt;/li&gt;    &lt;li&gt;Humor &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;If you couldn’t guess, we were four witty computer nerds (with an emphasis on the nerd part).&lt;/p&gt;  &lt;p&gt;In September 1998 4GuysFromRolla.com went live. Over time, the other three guys lost interest and moved onto other projects. By the time I graduated in May 2000, 4GuysFromRolla.com was run by one guy from Rolla and focused strictly on ASP.&lt;/p&gt;  &lt;h2&gt;&lt;/h2&gt;  &lt;h2&gt;Sale to Internet.com&lt;/h2&gt;  &lt;p&gt;The dotcom boom reached its fever pitch in 2000. Companies were paying $5,000 a month for a little 125x125 banner to appear on the 4Guys homepage and $500 for a two sentence text ad to appear in the weekly newsletter, not to mention the thousands of dollars per month companies were dropping to have their animated 468x60 banners in the rotation to appear at the top of each article. The spending frenzy also extended to the acquisitions side, as numerous ASP resource sites were gobbled up by larger players.&lt;/p&gt;  &lt;p&gt;In late 2000 I decided to “cash out.” 4Guys was sold to Internet.com.&lt;/p&gt;  &lt;p&gt;I wrestled with the decision on whether to sell the site or not for a long time. On one hand, 4Guys was my baby and I had poured uncounted hours into it over the previous three years. Having seen how sites like &lt;a href="http://15seconds.com/"&gt;15Seconds.com&lt;/a&gt; fared after their acquisition, I knew that selling 4Guys would be akin to signing its death warrant. When a larger company buys a smaller site it’s not uncommon for the original founders to exit stage right, either immediately or in the very near term. When that happens, and when the acquirer starts to turn the screws in an attempt to better monetize their purchase, the inevitable happens – the site withers on the vine, traffic languishes, and the death knell is sounded. On the other hand, by late 2000 I think it was pretty apparent to everyone that the dotcom boom was coming to an end.&lt;/p&gt;  &lt;p&gt;In the end, I decided to sell. The sales price reflected more than five years of dotcom boom revenue, which I deduced would be more like ten or more years of revenue once the boom ended. At age 22, five to ten years is an unimaginable window of time. I wondered, Would I be interested in writing about ASP ten years hence? Would I even be using ASP or web-based technologies? Since the answers to those questions were “maybe,” I decided to take the bird in the hand over the two in the bush.&lt;/p&gt;  &lt;p&gt;Of course, here we are, 11 years later, and I am still actively involved in ASP.NET and the ASP.NET community and, until recently, was still writing for 4Guys. If I had it to do over again (and knowing what I know now), I would not have sold the site. Hindsight is 20/20. But that’s not to say that I regret the decision to sell the site – I don’t. In fact, I still hold that it was the right decision at the time given the unknowns.&lt;/p&gt;  &lt;h2&gt;The Buying Eyeballs Business Model&lt;/h2&gt;  &lt;p&gt;The dotcom boom heralded an interesting time in the history of the web. At its peak, billions of dollars were spent buying traffic, or “eyeballs,” as it was commonly referred to back then. In 2000, companies like Internet.com and DevX (among many others) were buying technology resource sites not for their content or talent, but for their existing traffic. This was a workable business model at the time due to the high rates advertisers were paying. Unfortunately, it was not sustainable once the bottom dropped out of advertising.&lt;/p&gt;  &lt;p&gt;In 2009, Internet.com and its hundreds of technology-focused websites &lt;a href="http://www.internetnews.com/webcontent/article.php/3833856/WebMediaBrands-Sells-Internetcom-to-QuinStreet.htm"&gt;were sold to QuinStreet for $18 million&lt;/a&gt;. I continued working on 4Guys for QuinStreet (until recently). Unfortunately, QuinStreet’s purchase was a continuation of the buying eyeballs business model as evidenced by the lack of investment in the purchased web properties. 4Guys retained its dated look and feel as even more ads were squeezed onto the page.&lt;/p&gt;  &lt;p&gt;Sites like 4Guys were sold by Internet.com to QuinStreet for pennies on the dollar. Even at such a steep discount, the question remains: did QuinStreet overpay? Time will tell.&lt;/p&gt;  &lt;h2&gt;Withering On the Vine&lt;/h2&gt;  &lt;p&gt;After the sale of 4Guys to Internet.com in 2000 I continued on as the site’s editor and primary contributor, authoring an article each week. Despite my continued work on the site, 4Guys started to lose prevalence in the ASP.NET community. There were many times I talked to a developer at a User Group or at a conference who would say something nice like, “I taught myself classic ASP from your articles on 4GuysFromRolla.com - I used to go there all the time.” The message was always the same – a meaningful compliment that had embedded in it a reflection on the current state of the site - &lt;em&gt;I &lt;strong&gt;used&lt;/strong&gt; to visit 4Guys&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;There are probably a lot of different reasons why the importance and relevance of 4GuysFromRolla diminished over the years. Some of the reasons I’ve arrived at include:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;My predominant use of VB code samples (rather than C#).&lt;/strong&gt; In recent years, I started writing more C#-focused articles, as well as articles with code samples in both VB and C#, but the majority of articles on 4Guys are VB-only. And my switch to a more C#-friendly style came long after C# had become the de facto .NET language. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Increased attempts at monetization.&lt;/strong&gt; More ads, bigger ads, flashier ads, and more annoying ads all made the site more difficult and less enjoyable to use. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;A dated look and feel.&lt;/strong&gt; If you couldn’t guess, the 4GuysFromRolla.com website hasn’t had a site redesign since 2002. It just looks old and dated. I’d like to think that the quality and quantity of content can make up for such aesthetic issues, but I understand why visitors would find the site appearance off-putting and why that might make them less likely to return, especially if there was similar content to be found elsewhere, which brings me to the next three factors… &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;The Google.&lt;/strong&gt; Google turned the Internet upside down. Prior to Google, when faced with a particular problem people would go to a particular site and start hunting (or searching) for a solution. Once Google made search quick, fast, easy, and accurate – something I think happened in the early 2000s – user behavior shifted radically. Now Google was where people went to find answers to their questions. Just ask &lt;a href="http://www.codinghorror.com/blog"&gt;Jeff Atwood&lt;/a&gt;, who &lt;a href="http://www.codinghorror.com/blog/2009/02/the-elephant-in-the-room-google-monoculture.html"&gt;notes that&lt;/a&gt;: “Currently, 83% of our total traffic [to Stackoverflow] is from search engines, or rather, one &lt;em&gt;particular&lt;/em&gt; search engine.” And that search engine, if you couldn’t guess, is Google. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;A stronger online presence from Microsoft.&lt;/strong&gt; In the late 90s and early 2000s, Microsoft offered a substandard web presence for their web technologies. There was technical documentation buried somewhere on Microsoft’s website, some articles on their MSDN site here and there, as well as articles from &lt;em&gt;MSDN Magazine&lt;/em&gt; that were available online. But everything was scattered and hard to find. Microsoft finally got it right in the mid-2000s when they made MSDN easier and quicker to search and separated out their core technologies into standalone sites – &lt;a href="http://www.asp.net"&gt;www.asp.net&lt;/a&gt;, &lt;a href="http://www.iis.net"&gt;www.iis.net&lt;/a&gt;, etc. This move sucked an appreciable amount of traffic from community-founded sites like 4GuysFromRolla. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;The proliferation of blogs.&lt;/strong&gt; Blogs are another technology that made resource sites like 4GuysFromRolla.com less relevant. Intelligent developers with something interesting or useful to share didn’t need to get their thoughts published on your site – instead, they could start their own blog. The explosion of blogs outpaced the demand for information, cutting into everyone’s traffic and relevance. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Of all of the reasons listed above only one of them falls on my shoulders, namely my slow move away from VB to C#. But perhaps there are other factors that are my fault that my ego is blinding me from. I do believe that the quality of writing that has appeared on 4Guys has improved over the years. When I read some of the articles I wrote while I was still in school (1998-2000) I cringe. Also, I posit that the articles’ topics are (relatively) timely and of interest to ASP.NET developers. (To be fair, I was a bit late to jQuery and ASP.NET MVC, but once I jumped on that bandwagon I wrote quite a bit on said topics.)&lt;/p&gt;  &lt;p&gt;The increased attempts and monetization and dated look and feel falls on Internet.com and QuinStreet’s shoulders. The last three factors were out of everyone’s control and affected all websites, not just those in my little corner of the web. And those macro changes, while perhaps detrimental to the growth of a site like 4Guys, are net gains for the Internet (and humanity) as a whole.&lt;/p&gt;  &lt;p&gt;Neither QuinStreet nor Internet.com has ever provided me with traffic numbers so I don’t have any hard data to back up my thoughts on this, but my presumption is that 4Guys is still used by hundreds of thousands of developers around the world each month, but that it’s become less and less relevant as time has gone on. Today, I imagine that most people reach 4Guys from a Google search or from a link posted on an old messageboard or newsgroup thread. Few visit the site to see what new content is available or because a coworker told them that it’s a great website for ASP.NET developers of any stripe.&lt;/p&gt;  &lt;p&gt;Yes, there are still many who find a solution to their problem on 4Guys, but few say, “How do I do &lt;em&gt;X&lt;/em&gt;? I bet 4Guys has the answer!”&lt;/p&gt;  &lt;h2&gt;Some Fun Facts&lt;/h2&gt;  &lt;p&gt;Is it just me, or is this blog post getting a little depressing? How about some fun 4Guys trivia.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;First online article I ever wrote was published on 4Guys on September 16th, 1998 – &lt;em&gt;&lt;a href="http://www.4guysfromrolla.com/webtech/091698-1.shtml"&gt;Using ActiveX Controls on Your Web Page&lt;/a&gt;&lt;/em&gt; &lt;/li&gt;    &lt;li&gt;First article on 4Guys about ASP.NET was published on July 15th, 2000 – &lt;em&gt;&lt;a href="http://www.4guysfromrolla.com/webtech/071500-1.shtml"&gt;ASP.NET: An Introduction and My Views on the Matter&lt;/a&gt;&lt;/em&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Rolla,_Missouri"&gt;Rolla&lt;/a&gt; is a small town in Missouri that is home to the University of Missouri – Rolla, now named &lt;a href="http://en.wikipedia.org/wiki/Missouri_University_of_Science_and_Technology"&gt;Missouri University of Science and Technology&lt;/a&gt;. Rolla is pronounced &lt;em&gt;Rawl-ah&lt;/em&gt;. It’s 4GuysFrom&lt;em&gt;Rawl-ah&lt;/em&gt;, not 4GuysFrom&lt;em&gt;Roll-ah&lt;/em&gt;. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;For those who have never been to Rolla, it is about an hour and a half west of St. Louis, located square in the middle of nowhere. The university in Rolla focuses on engineering and the sciences and the student body is predominantly male. Many people wonder how I had the time to write nearly 750 articles while a student at UMR. The answer is that I went to school in the middle of nowhere with no girls - free time was not something that was hard to find!&lt;/p&gt;  &lt;p&gt;When we started 4Guys, one of the other 4Guys created the site design. It had a black background with gray text and these bubbles that spanned the top and right of each page with links to each of the four sections. Together, we redesigned the site in 1999 to give it a more professional look. It was at this time that 4Guys adopted teal as its primary color. After acquiring the site, Internet.com did a resign in 2002. The redesign made the site a bit more graphics heavy and added some curved doodads here and there. I always found the 4Guys logo that Internet.com’s design team created to be hilarious.&lt;/p&gt;  &lt;p&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" src="http://www.4guysfromrolla.com/img/4guyslogo.gif" /&gt;&lt;/p&gt;  &lt;p&gt;The guy on the left looks depressed and ostracized from the group. The guy on the right wants nothing more than a big group hug. And those two guys in the middle? They look like a couple of real a-holes. Too cocky and arrogant to console their melancholy friend on the left, and too cool for school to hug the guy on the right. Jerks.&lt;/p&gt;  &lt;h2&gt;So Farewell…&lt;/h2&gt;  &lt;p&gt;My time with 4Guys has now come to an end. It was a fun and unforgettable run. I fondly remember huddled around a computer monitor with the other three guys from Rolla as we tried to decide on a domain name. I remember the excitement of landing my first advertiser and of depositing that first check. And I won’t forget the many emails from fellow developers who wrote in to thank me for an article that helped them solve a vexing problem. But most of all, my memories will center around writing the 4Guys article each week – drumming up a topic, banging out some code, and then putting that code into prose.&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000"&gt;&lt;font color="#555555"&gt;Having written a 4Guys article each of the preceding 650 or so weeks, it will be odd not to do so this week. Or next week. Or ever again.&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Farewell, old girl, it was a good run.&lt;/p&gt;  &lt;h2 align="center"&gt;&lt;font color="#ff0000"&gt;&lt;font color="#555555"&gt;&lt;font style="background-color: #ffff00; font-weight: normal" size="4"&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#ff0000"&gt;&lt;font color="#555555"&gt;&lt;font style="font-weight: normal" size="4"&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font style="font-weight: normal" color="#ff0000" size="5"&gt;Just to be clear, I am not retiring! I am a writer, that’s what I do. You’ll continue to see articles from me on this blog and on sites like &lt;/font&gt;&lt;font style="font-weight: normal" color="#ff0000" size="5"&gt;DotNetSlackers.com&lt;/font&gt;&lt;font style="font-weight: normal" color="#ff0000" size="5"&gt; and &lt;/font&gt;&lt;font style="font-weight: normal" color="#ff0000" size="5"&gt;ASPAlliance.com&lt;/font&gt;&lt;font style="font-weight: normal" color="#ff0000" size="5"&gt;. And I am always looking for additional engagements – if you have a need for a technical writer or prolific ASP.NET author, please don’t hesitate to &lt;a href="http://scottonwriting.net/ScottMitchell.asp"&gt;check out my resume&lt;/a&gt; and &lt;a href="http://scottonwriting.net/sowblog/contact.aspx"&gt;drop me a line&lt;/a&gt;.&lt;/font&gt;&lt;/h2&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=183641" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/About+Writing/default.aspx">About Writing</category><category domain="http://scottonwriting.net/sowblog/archive/tags/Miscellaneous/default.aspx">Miscellaneous</category><feedburner:origLink>http://scottonwriting.net/sowblog/archive/2011/03/29/i-ve-written-my-last-article-for-4guysfromrolla.aspx</feedburner:origLink></item><item><title>The Average Number of Words and Points in Boggle</title><link>http://feedproxy.google.com/~r/ScottOnWriting/~3/cOPLHQaimNA/the-average-number-of-words-and-points-in-boggle.aspx</link><pubDate>Fri, 04 Mar 2011 00:21:46 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:180959</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>2</slash:comments><wfw:commentRss>http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=180959</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2011/03/04/the-average-number-of-words-and-points-in-boggle.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Boggle"&gt;Boggle&lt;/a&gt; is a word game trademarked by Parker Brothers and Hasbro that involves several players trying to find as many words as they can in a 4x4 grid of letters. At the end of the game, players compare the words they found. During this comparison I've always wondered what about missed words. Was there some elusive 10-letter word that no one unearthed? Did we only discover 25 solutions when there were 200 or more?&lt;/p&gt;  &lt;p&gt;To answer these questions I created a Boggle solver web application (back in 2008) that prompts a user for the letters in the Boggle board and then recursively explores the board to locate (and display) all available solutions. This &lt;a href="http://fuzzylogicinc.net/Boggle/"&gt;Boggle solver&lt;/a&gt; is available online - &lt;a href="http://fuzzylogicinc.net/Boggle/"&gt;fuzzylogicinc.net/Boggle&lt;/a&gt;. My family uses it every time we get together and play Boggle. For more information on how it works and to get your hands on the code, check out my article, &lt;a href="http://www.4guysfromrolla.com/articles/040208-1.aspx"&gt;Creating an Online Boggle Solver&lt;/a&gt;. In November 2010, I updated the code to make it more Ajax-friendly; see &lt;a href="http://www.4guysfromrolla.com/articles/112410-1.aspx"&gt;Updating My Online Boggle Solver Using jQuery Templates&lt;/a&gt; and WCF for details.&lt;/p&gt;  &lt;p&gt;While playing a game of Boggle I found myself wondering how many total available words are present in a typical game of Boggle, and how many total points are available. It soon dawned on me that I could answer this question using my Boggle solver application and a the &lt;a href="http://en.wikipedia.org/wiki/Monte_Carlo_method"&gt;Monte Carlo method&lt;/a&gt;. My Boggle solving engine has a &lt;strong&gt;GenerateBoard&lt;/strong&gt; method that randomly assembles a legal Boggle board. By generating tens of thousands of random Boggle boards, running them through my solver, and recording the number of words and total points available I could arrive at a good approximation for the average number of words and points in a given game of Boggle. (Scroll to the bottom of this blog entry if all you care about is the average number of words and points per game.)&lt;/p&gt;  &lt;p&gt;I started by creating a new class in my Boggle solving Class Library, which I named &lt;strong&gt;GameLogger&lt;/strong&gt;. This class has a single method, &lt;strong&gt;LogGame&lt;/strong&gt;, which takes an inputs the &lt;strong&gt;BoggleBoard&lt;/strong&gt; object that was used to find the solutions and the &lt;strong&gt;BoggleWorldList&lt;/strong&gt; object that comprises the set of solutions to the accompanying &lt;strong&gt;BoggleBoard&lt;/strong&gt;. This method then inserts a record into a database table (&lt;strong&gt;boggle_Boards&lt;/strong&gt;) that logs:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The &lt;strong&gt;BoardID&lt;/strong&gt;, which is a 16-character string that uniquely identifies the board. Namely, it contains one character for each letter in the board.&lt;/li&gt;    &lt;li&gt;The &lt;strong&gt;NumberOfSolutions&lt;/strong&gt;, which is the number of words on the for the board.&lt;/li&gt;    &lt;li&gt;The &lt;strong&gt;Score&lt;/strong&gt;, which is the cummulative score of all of the words on the board. In Boggle, 3 and 4 letter words score 1 point, 5 letter words score 2, six letter words score 3, seven letter words score 5 and words eight letters or longer score 11.&lt;/li&gt;    &lt;li&gt;The &lt;strong&gt;MinimumWordLength&lt;/strong&gt;, which specifies the minimum number of letters needed to form a valid solution. Boggle’s rules permit words three or more letters in length, but my family often plays a variation that permits only four letter or longer words.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The code for my Monte Carlo simulator is brain-dead simple – create a new Boggle game, solve it, then log it, and do this until I tell you to stop.&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;while (true)
{
    var gt = GameTiles.OfficialBoggleGameTiles();
    var board = new BoggleBoard(3, gt.GenerateBoard());

    var solutions = board.Solve();

    GameLogger.LogGame(board, solutions);
}&lt;/pre&gt;

&lt;p&gt;Let the above code run for 5 minutes and you’ve got tens of thousands of solved, random Boggle boards in the database from which you can now ascertain average number of words and score.&lt;/p&gt;

&lt;p&gt;The following query returns the average number of solutions and score for games allowing words with 3 of more letters:&lt;/p&gt;

&lt;pre class="brush: sql;"&gt;SELECT AVG(CAST(NumberOfSolutions AS decimal)), AVG(CAST(Score AS decimal))
FROM dbo.boggle_Boards
WHERE MinimumWordLength = 3&lt;/pre&gt;

&lt;p&gt;Which comes out to:&lt;/p&gt;

&lt;p align="center"&gt;&lt;font color="#ff0000" size="5"&gt;&lt;strong&gt;Average # of words:&lt;/strong&gt; 66.82

    &lt;br /&gt;&lt;strong&gt;Average score:&lt;/strong&gt; 93.25&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;If we compute the average number of words and points for games requiring four or more letters we get, expectedly, lower results. For such games you can expect, on average, &lt;strong&gt;42.12 words&lt;/strong&gt; and &lt;strong&gt;68.30 points&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So, next time you break out Boggle, keep in mind that, on average, there are nearly 67 words hiding there, ready for you to find. And after time expires, be sure to use &lt;a href="http://fuzzylogicinc.net/Boggle/"&gt;my Boggle solver&lt;/a&gt; to see all the words that were present!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note: &lt;/strong&gt;Of course, these results are based on the dictionary that my Boggle solver uses. My dictionary may permit or deny certain words that you deny or allow, in which case these averages would be skewed. Unfortunately, I am unaware of where I got my dictionary file. I downloaded it from some website many years ago. I know many word-based games use the Enhanced North American Benchmark Lexicon as their dictionary. I am not using this but would like to integrate it at some point in the future…&lt;/em&gt;&lt;/p&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=180959" width="1" height="1"&gt;</description><feedburner:origLink>http://scottonwriting.net/sowblog/archive/2011/03/04/the-average-number-of-words-and-points-in-boggle.aspx</feedburner:origLink></item><item><title>My Latest Articles From Around the Web</title><link>http://feedproxy.google.com/~r/ScottOnWriting/~3/SODAEjx7m5o/my-latest-articles-from-around-the-web.aspx</link><pubDate>Tue, 01 Mar 2011 01:01:00 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:180662</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=180662</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2011/03/01/my-latest-articles-from-around-the-web.aspx#comments</comments><description>&lt;p&gt;In addition to my regular articles on &lt;a href="http://www.4guysfromrolla.com/"&gt;4GuysFromRolla.com&lt;/a&gt;, I’ve recently authored a number of articles that have appeared on other websites:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;&lt;a href="http://dotnetslackers.com/articles/aspnet/Use-ASP-NET-and-DotNetZip-to-Create-and-Extract-ZIP-Files.aspx"&gt;Use ASP.NET and DotNetZip to Create and Extract ZIP Files&lt;/a&gt;&lt;/strong&gt; - This article shows how to use &lt;a href="http://dotnetzip.codeplex.com/"&gt;DotNetZip&lt;/a&gt; to create and extract ZIP files in an ASP.NET application, and covers advanced features like password protection and encryption. (DotNetZip is a free, open source class library for manipulating ZIP files and folders.)      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;a href="http://aspalliance.com/2045_Creating_a_Login_Overlay.all"&gt;Creating a Login Overlay&lt;/a&gt;&lt;/strong&gt; - Traditionally, websites that support user accounts have their visitors sign in by going to a dedicated login page where they enter their username and password. This article shows how to implement a login overlay, which is an alternative user interface for signing into a website.      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://dotnetslackers.com/articles/aspnet/5-Helpful-DateTime-Extension-Methods.aspx"&gt;&lt;strong&gt;5 Helpful DateTime Extension Methods&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&amp;#160;&lt;/strong&gt;- This article presents five DateTime extension methods that I have used in various projects over the years. The complete code, unit tests, and a simple demo application are available for download. Feel free to add these extension methods to your projects!&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;To keep abreast of my latest articles - and to read my many insightful witticisms &lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://nbaweblog.com/images/sowblog/wlEmoticon-smile_5756564C.png" /&gt; - follow me on Twitter &lt;a href="http://twitter.com/ScottOnWriting"&gt;@ScottOnWriting&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=180662" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/ASP.NET+Talk/default.aspx">ASP.NET Talk</category><feedburner:origLink>http://scottonwriting.net/sowblog/archive/2011/03/01/my-latest-articles-from-around-the-web.aspx</feedburner:origLink></item><item><title>Select a textbox’s text on focus using jQuery</title><link>http://feedproxy.google.com/~r/ScottOnWriting/~3/pr_AzzPo0hU/select-a-textbox-s-text-on-focus-using-jquery.aspx</link><pubDate>Tue, 01 Feb 2011 00:23:20 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:177347</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>2</slash:comments><wfw:commentRss>http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=177347</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2011/02/01/select-a-textbox-s-text-on-focus-using-jquery.aspx#comments</comments><description>&lt;p&gt;A fellow ASP.NET developer asked me today how he could have the text in a TextBox control automatically selected whenever the TextBox received focus.&lt;/p&gt;  &lt;p&gt;In short, whenever any textbox on the page receives focus you want to call its &lt;strong&gt;select()&lt;/strong&gt; function. (The JavaScript &lt;strong&gt;select()&lt;/strong&gt; function is the function that actually selects the textbox’s text, if any.) Implementing this functionality requires just one line of JavaScript code, thanks to jQuery:&lt;/p&gt;  &lt;pre class="brush: js;"&gt;$(&amp;quot;input[type=text]&amp;quot;).focus(function() { $(this).select(); });&lt;/pre&gt;

&lt;p&gt;In English, the above line of code says, “For any &lt;strong&gt;&amp;lt;input&amp;gt;&lt;/strong&gt; element with a &lt;strong&gt;type=”text” &lt;/strong&gt;attribute, whenever it is focused call it’s &lt;strong&gt;select()&lt;/strong&gt; function.” If you only wanted certain textboxes on the page to auto-select their text on focus you’d update the selector syntax accordingly. For example, the following modification only auto-selects the text for those textboxes that use a CSS class named &lt;strong&gt;autoselect&lt;/strong&gt;:&lt;/p&gt;

&lt;pre class="brush: js;"&gt;$(&amp;quot;input[type=text].autoselect&amp;quot;).focus(function() { $(this).select(); });&lt;/pre&gt;

&lt;p&gt;That’s all there is to it! You can view the complete script and try a working demo at &lt;a title="http://jsfiddle.net/ScottOnWriting/Kq7A4/2/" href="http://jsfiddle.net/ScottOnWriting/Kq7A4/2/"&gt;http://jsfiddle.net/ScottOnWriting/Kq7A4/2/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One final comment: if one or more of the textboxes you want to auto-select exist within an UpdatePanel control then consider using jQuery’s &lt;a href="http://api.jquery.com/live/"&gt;&lt;strong&gt;live() &lt;/strong&gt;function&lt;/a&gt;. The &lt;strong&gt;live()&lt;/strong&gt; function maintains the event bindings even when the HTML is regenerated due to a partial page postback; for more information, see my article – &lt;a href="http://www.4guysfromrolla.com/articles/090810-1.aspx"&gt;Rebinding Client-Side Events After a Partial Page Postback&lt;/a&gt;. For more information on jQuery, see &lt;a href="http://dotnetslackers.com/articles/ajax/Using-jQuery-with-ASP-NET.aspx"&gt;Using jQuery with ASP.NET&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EDIT [2011-03-29]:&lt;/strong&gt; To get this to work in Safari / Chrome you will need to add a &lt;strong&gt;mouseup&lt;/strong&gt; event handler and disable the default event, as the &lt;strong&gt;onmouseup&lt;/strong&gt; event is causing the textbox to be unselected. For more details, see this Stackoverflow post: &lt;a href="http://stackoverflow.com/questions/1269722/selecting-text-on-focus-using-jquery-not-working-in-safari-and-chrome"&gt;Selecting text on focus using jQuery not working in Safari and Chrome&lt;/a&gt;.&lt;/p&gt;

&lt;pre class="brush: sql;"&gt;$(&amp;quot;input[type=text].autoselect&amp;quot;).focus(
    function() { 
         $(this).select(); 
    }
 )
 .mouseup(
    function(e) {
        e.preventDefault();
    }
 );
    &lt;/pre&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=177347" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/jQuery/default.aspx">jQuery</category><feedburner:origLink>http://scottonwriting.net/sowblog/archive/2011/02/01/select-a-textbox-s-text-on-focus-using-jquery.aspx</feedburner:origLink></item><item><title>Removing Gaps and Duplicates from a Numeric Column in Microsoft SQL Server</title><link>http://feedproxy.google.com/~r/ScottOnWriting/~3/ftu7ARBesbQ/removing-gaps-and-duplicates-in-a-numeric-column-in-microsoft-sql-server.aspx</link><pubDate>Tue, 18 Jan 2011 17:35:28 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:176495</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>1</slash:comments><wfw:commentRss>http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=176495</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2011/01/18/removing-gaps-and-duplicates-in-a-numeric-column-in-microsoft-sql-server.aspx#comments</comments><description>&lt;p&gt;Here’s the scenario: you have a database table with an integral numeric column used for sort order of some other non-identifying purpose. Let’s call this column &lt;strong&gt;SortOrder&lt;/strong&gt;. There are a many rows in this table. Every row &lt;em&gt;should&lt;/em&gt; have a unique, sequentially increasing value in its &lt;strong&gt;SortOrder&lt;/strong&gt; column, but this may not be the case – there may be gaps and/or duplicate values in this column.&lt;/p&gt;  &lt;p&gt;For example, consider a table with the following schema and data:&lt;/p&gt;  &lt;table border="0" cellspacing="0" cellpadding="2" width="400"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="135" align="center"&gt;         &lt;p align="center"&gt;&lt;strong&gt;EmployeeID&lt;/strong&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="131"&gt;         &lt;p align="center"&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="132" align="center"&gt;         &lt;p align="center"&gt;&lt;strong&gt;SortOrder&lt;/strong&gt;&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="136" align="center"&gt;1&lt;/td&gt;        &lt;td valign="top" width="131"&gt;Scott&lt;/td&gt;        &lt;td valign="top" width="132" align="center"&gt;1&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="136" align="center"&gt;2&lt;/td&gt;        &lt;td valign="top" width="131"&gt;Jisun&lt;/td&gt;        &lt;td valign="top" width="132" align="center"&gt;8&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="136" align="center"&gt;3&lt;/td&gt;        &lt;td valign="top" width="131"&gt;Alice&lt;/td&gt;        &lt;td valign="top" width="132" align="center"&gt;7&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="136" align="center"&gt;4&lt;/td&gt;        &lt;td valign="top" width="131"&gt;Sam&lt;/td&gt;        &lt;td valign="top" width="132" align="center"&gt;7&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="136" align="center"&gt;5&lt;/td&gt;        &lt;td valign="top" width="131"&gt;Benjamin&lt;/td&gt;        &lt;td valign="top" width="132" align="center"&gt;3&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="136" align="center"&gt;6&lt;/td&gt;        &lt;td valign="top" width="131"&gt;Aaron&lt;/td&gt;        &lt;td valign="top" width="132" align="center"&gt;9&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="136" align="center"&gt;7&lt;/td&gt;        &lt;td valign="top" width="131"&gt;Alexis&lt;/td&gt;        &lt;td valign="top" width="132" align="center"&gt;4&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="136" align="center"&gt;8&lt;/td&gt;        &lt;td valign="top" width="131"&gt;Barney&lt;/td&gt;        &lt;td valign="top" width="132" align="center"&gt;5&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="136" align="center"&gt;9&lt;/td&gt;        &lt;td valign="top" width="131"&gt;Jim&lt;/td&gt;        &lt;td valign="top" width="132" align="center"&gt;5&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;Note how the &lt;strong&gt;SortOrder &lt;/strong&gt;column has some gaps and duplicates. Ideally, the &lt;strong&gt;SortOrder&lt;/strong&gt; column values for these nine rows would be 1, 2, 3, …, 9, but this isn’t the case. Instead, the current values (in ascending order) are: 1, 3, 4, 5, 5, 7, 7, 8, 9.&lt;/p&gt;  &lt;p&gt;Our task is to take the existing &lt;strong&gt;SortColumn&lt;/strong&gt; values and get them into the ideal format. That is, after our modifications, the table’s data should look like so:&lt;/p&gt;  &lt;table border="0" cellspacing="0" cellpadding="2" width="400"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="135" align="center"&gt;         &lt;p align="center"&gt;&lt;strong&gt;EmployeeID&lt;/strong&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="131"&gt;         &lt;p align="center"&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="132" align="center"&gt;         &lt;p align="center"&gt;&lt;strong&gt;SortOrder&lt;/strong&gt;&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="136" align="center"&gt;1&lt;/td&gt;        &lt;td valign="top" width="131"&gt;Scott&lt;/td&gt;        &lt;td valign="top" width="132" align="center"&gt;1&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="136" align="center"&gt;2&lt;/td&gt;        &lt;td valign="top" width="131"&gt;Jisun&lt;/td&gt;        &lt;td valign="top" width="132" align="center"&gt;8&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="136" align="center"&gt;3&lt;/td&gt;        &lt;td valign="top" width="131"&gt;Alice&lt;/td&gt;        &lt;td valign="top" width="132" align="center"&gt;6&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="136" align="center"&gt;4&lt;/td&gt;        &lt;td valign="top" width="131"&gt;Sam&lt;/td&gt;        &lt;td valign="top" width="132" align="center"&gt;7&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="136" align="center"&gt;5&lt;/td&gt;        &lt;td valign="top" width="131"&gt;Benjamin&lt;/td&gt;        &lt;td valign="top" width="132" align="center"&gt;2&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="136" align="center"&gt;6&lt;/td&gt;        &lt;td valign="top" width="131"&gt;Aaron&lt;/td&gt;        &lt;td valign="top" width="132" align="center"&gt;9&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="136" align="center"&gt;7&lt;/td&gt;        &lt;td valign="top" width="131"&gt;Alexis&lt;/td&gt;        &lt;td valign="top" width="132" align="center"&gt;3&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="136" align="center"&gt;8&lt;/td&gt;        &lt;td valign="top" width="131"&gt;Barney&lt;/td&gt;        &lt;td valign="top" width="132" align="center"&gt;4&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="136" align="center"&gt;9&lt;/td&gt;        &lt;td valign="top" width="131"&gt;Jim&lt;/td&gt;        &lt;td valign="top" width="132" align="center"&gt;5&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;Note how now there are now no gaps or duplicates in &lt;strong&gt;SortOrder&lt;/strong&gt;.&lt;/p&gt;  &lt;h2&gt;The Solution: Ranking Functions, Multi-Table UPDATE Statements and Common Table Expressions (CTEs)&lt;/h2&gt;  &lt;p&gt;Microsoft SQL Server 2005 &lt;a href="http://www.4guysfromrolla.com/webtech/010406-1.shtml"&gt;added a number of ranking functions&lt;/a&gt; that simplify assigning ranks to query results, such as associating a sequentially increasing row number with each record returned from a query or assigning a rank to each result. For example, the following query – which uses SQL Server’s &lt;strong&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms186734.aspx"&gt;ROW_NUMBER() function&lt;/a&gt;&lt;/strong&gt; – returns the records from the &lt;strong&gt;Employees&lt;/strong&gt; table with a sequentially increasing number associated with each record:&lt;/p&gt;  &lt;pre class="brush: sql;"&gt;SELECT Name, 
       SortOrder, 
       ROW_NUMBER() OVER (ORDER BY SortOrder) AS NoGapsNoDupsSortOrder
FROM Employees&lt;/pre&gt;

&lt;p&gt;The above query would return the following results. Note how the data is sorted by &lt;strong&gt;SortOrder&lt;/strong&gt;. There’s also a new, materialized column (&lt;strong&gt;NoGapsNoDupsSortOrder&lt;/strong&gt;) that returns sequentially increasing values.&lt;/p&gt;

&lt;table border="0" cellspacing="0" cellpadding="2" width="403"&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td valign="top" width="102"&gt;
        &lt;p align="center"&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="92" align="center"&gt;
        &lt;p align="center"&gt;&lt;strong&gt;SortOrder&lt;/strong&gt;&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="207" align="center"&gt;
        &lt;p align="center"&gt;&lt;strong&gt;NoGapsNoDupsSortOrder&lt;/strong&gt;&lt;/p&gt;
      &lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="102"&gt;Scott&lt;/td&gt;

      &lt;td valign="top" width="92" align="center"&gt;1&lt;/td&gt;

      &lt;td valign="top" width="208" align="center"&gt;1&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="102"&gt;Benjamin&lt;/td&gt;

      &lt;td valign="top" width="92" align="center"&gt;3&lt;/td&gt;

      &lt;td valign="top" width="209" align="center"&gt;2&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="102"&gt;Alexis&lt;/td&gt;

      &lt;td valign="top" width="92" align="center"&gt;4&lt;/td&gt;

      &lt;td valign="top" width="210" align="center"&gt;3&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="102"&gt;Barney&lt;/td&gt;

      &lt;td valign="top" width="92" align="center"&gt;5&lt;/td&gt;

      &lt;td valign="top" width="210" align="center"&gt;4&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="102"&gt;Jim&lt;/td&gt;

      &lt;td valign="top" width="92" align="center"&gt;5&lt;/td&gt;

      &lt;td valign="top" width="210" align="center"&gt;5&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="102"&gt;Alice&lt;/td&gt;

      &lt;td valign="top" width="92" align="center"&gt;7&lt;/td&gt;

      &lt;td valign="top" width="210" align="center"&gt;6&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="102"&gt;Sam&lt;/td&gt;

      &lt;td valign="top" width="92" align="center"&gt;7&lt;/td&gt;

      &lt;td valign="top" width="210" align="center"&gt;7&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="102"&gt;Jisun&lt;/td&gt;

      &lt;td valign="top" width="92" align="center"&gt;8&lt;/td&gt;

      &lt;td valign="top" width="210" align="center"&gt;8&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="102"&gt;Aaron&lt;/td&gt;

      &lt;td valign="top" width="92" align="center"&gt;9&lt;/td&gt;

      &lt;td valign="top" width="210" align="center"&gt;9&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;What we need to do now is take the value in &lt;strong&gt;NoGapsNoDupsSortOrder&lt;/strong&gt; and assign it to the &lt;strong&gt;SortOrder&lt;/strong&gt; column. If we had the above results in a separate table we could perform such an &lt;strong&gt;UPDATE&lt;/strong&gt;, as SQL Server makes it possible to update records in one database table with data from another table. (See &lt;a href="http://scottonwriting.net/sowblog/archive/2010/07/13/howto-update-records-in-a-database-table-with-data-from-another-table-ms-sql-server.aspx"&gt;HOWTO: Update Records in a Database Table With Data From Another Table&lt;/a&gt;.) &lt;/p&gt;

&lt;p&gt;While the results in the above grid are not in a table (but are rather the results from a query), the good news is that we can treat those results as if they were results in another table using a &lt;strong&gt;&lt;a href="http://www.4guysfromrolla.com/webtech/071906-1.shtml"&gt;Common Table Expression (CTE)&lt;/a&gt;&lt;/strong&gt;. CTEs, which were introduced in SQL Server 2005, can be thought of as a one-off view; that is, a view that is created, defined, and used in a single SQL statement.&lt;/p&gt;

&lt;p&gt;Putting it all together, we end up with the following &lt;strong&gt;UPDATE&lt;/strong&gt; statement:&lt;/p&gt;

&lt;pre class="brush: sql;"&gt;WITH OrderedResults(EmployeeId, NoGapNoDupSortOrder) AS 
(
    SELECT EmployeeId, 
              ROW_NUMBER() OVER (ORDER BY SortOrder) AS NoGapNoDupSortOrder
    FROM Employees
)
UPDATE Employees
    SET SortOrder = OrderedResults.NoGapNoDupSortOrder
FROM OrderedResults
WHERE Employees.EmployeeId = OrderedResults.EmployeeId AND 
       Employees.SortOrder &amp;lt;&amp;gt; OrderedResults.NoGapNoDupSortOrder&lt;/pre&gt;

&lt;p&gt;The above query starts by defining a CTE named &lt;strong&gt;OrderedResults&lt;/strong&gt; that returns two column values: &lt;strong&gt;EmployeeId&lt;/strong&gt; and &lt;strong&gt;NoGapNoDupSortOrder&lt;/strong&gt;. It then updates the &lt;strong&gt;Employees&lt;/strong&gt; table, setting its &lt;strong&gt;SortOrder&lt;/strong&gt; column value to the &lt;strong&gt;NoGapNoDupSortOrder&lt;/strong&gt; value where the &lt;strong&gt;Employees&lt;/strong&gt; table’s &lt;strong&gt;EmployeeId&lt;/strong&gt; value matches the &lt;strong&gt;OrderedResults&lt;/strong&gt; CTEs &lt;strong&gt;EmployeeId&lt;/strong&gt; value (and where the &lt;strong&gt;SortOrder&lt;/strong&gt; does not equal the &lt;strong&gt;NoGapNoDupSortOrder&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;For more information on CTEs, ranked results, and updating one table (&lt;strong&gt;Employees&lt;/strong&gt;) with data from another table or CTE (&lt;strong&gt;OrderedResults&lt;/strong&gt;), check out the following resources:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://www.4guysfromrolla.com/webtech/010406-1.shtml"&gt;Returning Ranked Results with Microsoft SQL Server&lt;/a&gt;&lt;/li&gt;

  &lt;li&gt;&lt;a href="http://www.4guysfromrolla.com/webtech/071906-1.shtml"&gt;Common Table Expressions (CTE) in Microsoft SQL Server&lt;/a&gt;&lt;/li&gt;

  &lt;li&gt;&lt;a href="http://scottonwriting.net/sowblog/archive/2010/07/13/howto-update-records-in-a-database-table-with-data-from-another-table-ms-sql-server.aspx"&gt;HOWTO: Update Records in a Database Table With Data From Another Table (MS SQL Server)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy Programming!&lt;/p&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=176495" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/SQL/default.aspx">SQL</category><feedburner:origLink>http://scottonwriting.net/sowblog/archive/2011/01/18/removing-gaps-and-duplicates-in-a-numeric-column-in-microsoft-sql-server.aspx</feedburner:origLink></item><item><title>Customizing ELMAH’s Error Emails</title><link>http://feedproxy.google.com/~r/ScottOnWriting/~3/4a_3XzUe66g/customizing-elmah-s-error-emails.aspx</link><pubDate>Thu, 06 Jan 2011 19:40:51 GMT</pubDate><guid isPermaLink="false">2814ed8b-42a8-4dfe-b0b1-a7acb3e6d762:175870</guid><dc:creator>Scott Mitchell</dc:creator><slash:comments>3</slash:comments><wfw:commentRss>http://scottonwriting.net/sowblog/rsscomments.aspx?PostID=175870</wfw:commentRss><comments>http://scottonwriting.net/sowblog/archive/2011/01/06/customizing-elmah-s-error-emails.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://code.google.com/p/elmah/"&gt;ELMAH&lt;/a&gt; (Error Logging Modules and Handlers) is my ASP.NET logging facility of choice. It can be added to a new or running ASP.NET site in less than a minute. It’s open source and it’s creator, Atif Aziz, remains actively involved with the project and can be found answering questions about ELMAH, from &lt;a href="http://stackoverflow.com/questions/tagged/elmah"&gt;Stackoverflow&lt;/a&gt; to &lt;a href="http://groups.google.com/group/elmah"&gt;ELMAH’s Google Discussion group&lt;/a&gt;. What’s not to love about it?&lt;/p&gt;  &lt;p&gt;ELMAH’s sole purpose is to log and notify developers of errors that occur in an ASP.NET application. Error details can be logged to any number of log sources – SQL Server, MySQL, XML, Oracle, and so forth. Likewise, when an error occurs ELMAH can notify developers by sending the error details to one or more email addresses.&lt;/p&gt;  &lt;p&gt;The notification email message sent by ELMAH is pretty straightforward: it contains the exception type and message, the date and time the exception was generated, the stack trace, a table of all server variables, and the Yellow Screen of Death that was generated by the error.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://nbaweblog.com/images/sowblog/image_6D5F21B4.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://nbaweblog.com/images/sowblog/image_thumb_3EF5763A.png" width="504" height="483" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Prior to sending the notification email, ELMAH’s &lt;strong&gt;ErrorMailModule&lt;/strong&gt; class raises its &lt;strong&gt;Mailing&lt;/strong&gt; event. If you create an event handler for this event you can inspect details about the error that just occurred and modify the email message that is about to be sent. In this way you can customize the notification email, perhaps setting the priority based on the error or cc’ing certain email addresses if the error has originated from a particular page on the website.&lt;/p&gt;  &lt;p&gt;To create an event handler for the &lt;strong&gt;Mailing&lt;/strong&gt; event, open (or create) the &lt;strong&gt;Global.asax&lt;/strong&gt; file and add the following syntax:&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;void ErrorMailModuleName_Mailing(object sender, Elmah.ErrorMailEventArgs e)
{
    ...
}&lt;/pre&gt;

&lt;p&gt;In the above code snippet, replace &lt;strong&gt;&lt;em&gt;ErrorMailModuleName&lt;/em&gt;&lt;/strong&gt; with the name you assigned the &lt;strong&gt;ErrorMailModule&lt;/strong&gt; HTTP Module. This module may be defined in one or two places: the &lt;strong&gt;&amp;lt;system.web&amp;gt;/&amp;lt;httpModule&amp;gt;&lt;/strong&gt; section and/or the &lt;strong&gt;&amp;lt;system.webServer&amp;gt;/&amp;lt;modules&amp;gt;&lt;/strong&gt; section. The following &lt;strong&gt;Web.config&lt;/strong&gt; snippet shows both sections:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;system.web&amp;gt;
    &amp;lt;httpModules&amp;gt;
        &amp;lt;add name=&amp;quot;ErrorMail&amp;quot; type=&amp;quot;Elmah.ErrorMailModule, Elmah&amp;quot; /&amp;gt;
        ...
    &amp;lt;/httpModules&amp;gt;

    ...    
&amp;lt;/system.web&amp;gt;

&amp;lt;system.webServer&amp;gt;
    &amp;lt;modules&amp;gt;
        &amp;lt;add name=&amp;quot;ErrorMail&amp;quot; type=&amp;quot;Elmah.ErrorMailModule, Elmah&amp;quot; preCondition=&amp;quot;managedHandler&amp;quot; /&amp;gt;
        ...
    &amp;lt;/modules&amp;gt;
    
    ...
&amp;lt;/system.webServer&amp;gt;&lt;/pre&gt;

&lt;p&gt;The &lt;strong&gt;name&lt;/strong&gt; for the module in both sections should be the same - in the above snippet the &lt;strong&gt;name&lt;/strong&gt; is &lt;strong&gt;ErrorMail&lt;/strong&gt;. Consequently, to create an event handler for ELMAH’s &lt;strong&gt;Mailing&lt;/strong&gt; event with the above configuration we would use the syntax:&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;void ErrorMail_Mailing(object sender, Elmah.ErrorMailEventArgs e)
{
    ...
}&lt;/pre&gt;

&lt;h2&gt;&lt;/h2&gt;

&lt;p&gt;Note that the &lt;strong&gt;Mailing &lt;/strong&gt;event handler’s second input parameter is of type &lt;strong&gt;ErrorMailEventArgs&lt;/strong&gt;. This class provides two helpful properties:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Error&lt;/strong&gt; – the error that was just logged by ELMAH. This property is of type &lt;strong&gt;Elmah.Error&lt;/strong&gt; and has properties like &lt;strong&gt;Exception&lt;/strong&gt;, &lt;strong&gt;Message&lt;/strong&gt;, &lt;strong&gt;User&lt;/strong&gt;, &lt;strong&gt;Time&lt;/strong&gt;, and so on.&lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;Mail&lt;/strong&gt; – the &lt;strong&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.net.mail.mailmessage.aspx"&gt;MailMessage object&lt;/a&gt;&lt;/strong&gt; that is about to be sent. This gives you an opportunity to modify the outgoing email.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following &lt;strong&gt;Mailing&lt;/strong&gt; event handler shows how you could adjust the notification email based on the type of exception that occurred. Here, if the error that just occurred was an &lt;strong&gt;ApplicationException&lt;/strong&gt; then the notification email is set to a High priority, it’s subject it changed to “This is a high priority item!”, and &lt;a href="mailto:mitchell@4guysfromrolla.com"&gt;mitchell@4guysfromrolla.com&lt;/a&gt; is cc’d.&lt;/p&gt;

&lt;pre class="brush: csharp;"&gt;void ErrorMail_Mailing(object sender, Elmah.ErrorMailEventArgs e)
{
    if (e.Error.Exception is ApplicationException ||
        (e.Error.Exception is HttpUnhandledException &amp;amp;&amp;amp; 
            e.Error.Exception.InnerException != null &amp;amp;&amp;amp;
            e.Error.Exception.InnerException is ApplicationException))
    {
        e.Mail.Priority = System.Net.Mail.MailPriority.High;
        e.Mail.Subject = &amp;quot;This is a high priority item!&amp;quot;;
        e.Mail.CC.Add(&amp;quot;mitchell@4guysfromrolla.com&amp;quot;);
    }
}&lt;/pre&gt;

&lt;p&gt;Note that if an unhandled &lt;strong&gt;ApplicationException &lt;/strong&gt;is what prompted ELMAH to record the error then by this point the original exception will have been wrapped in an &lt;strong&gt;HttpUnhandledException&lt;/strong&gt;. So in the &lt;strong&gt;if&lt;/strong&gt; statement above I check to see if the error’s &lt;strong&gt;Exception&lt;/strong&gt; property is an &lt;strong&gt;ApplicationException&lt;/strong&gt; or if it is an &lt;strong&gt;HttpUnhandledException &lt;/strong&gt;exception with an &lt;strong&gt;InnerException&lt;/strong&gt; that is an &lt;strong&gt;ApplicationException&lt;/strong&gt;. If either of those conditions hold then I want to customize the notification email.&lt;/p&gt;

&lt;p&gt;Happy Programming!&lt;/p&gt;&lt;img src="http://scottonwriting.net/aggbug.aspx?PostID=175870" width="1" height="1"&gt;</description><category domain="http://scottonwriting.net/sowblog/archive/tags/ASP.NET+Talk/default.aspx">ASP.NET Talk</category><feedburner:origLink>http://scottonwriting.net/sowblog/archive/2011/01/06/customizing-elmah-s-error-emails.aspx</feedburner:origLink></item></channel></rss>

