<?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.stevesmithblog.com/~d/styles/itemcontent.css"?><rss version="2.0"><channel><title>Blog</title><link>http://ardalis.com:80/</link><description>Blog</description><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.stevesmithblog.com/StevenSmith" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="stevensmith" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">StevenSmith</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><item><title>Joining Telerik</title><link>http://ardalis.com:80/joining-telerik</link><description>&lt;p&gt;&lt;a href="http://nimblepros.com/"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 0px 5px 5px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top: 0px; border-right: 0px; padding-top: 0px" border="0" alt="Nimble Software Professionals" align="right" src="http://hudsonsc.com/files/themes/User%20Group/images/sponsors/nimblepros.com.gif"&gt;&lt;/a&gt;Earlier this year, I wrapped up my work with &lt;a href="http://www.codeproject.com/"&gt;The Code Project&lt;/a&gt; and &lt;a href="http://lakequincy.com/"&gt;Lake Quincy Media&lt;/a&gt; and returned to &lt;a href="http://nimblepros.com/"&gt;NimblePros&lt;/a&gt;, the consulting company &lt;a href="https://twitter.com/#!/mickeyme"&gt;Michelle&lt;/a&gt; and I started a few years ago and which she’s run quite successfully the last few years. NimblePros has been doing some great things the last couple of years, with revenues in 2011 doubling those of 2010. At the same time, we’ve been watching &lt;a href="http://telerik.com/"&gt;Telerik&lt;/a&gt; continue to grow by leaps and bounds, entering new markets and attracting a ton of great people to join their team. We’ve had a great relationship with Telerik for almost ten years, as individuals and through several different businesses, and have always found them to be exceptionally good to work with. That’s why when they approached us about joining the NimblePros team with Telerik’s, we were very enthusiastic about the opportunity. Today, I’m excited to announce that the entire &lt;a href="http://nimblepros.com/news-and-events/nimblepros-is-now-part-of-telerik.aspx"&gt;NimblePros organization is now a part of the Telerik team&lt;/a&gt;, and will be providing a variety of services to Telerik clients and partners.  &lt;p&gt;&lt;a href="http://telerik.com/"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 5px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top: 0px; border-right: 0px; padding-top: 0px" title="telerikLogo-web-174x69px-white" border="0" alt="telerikLogo-web-174x69px-white" align="left" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Joining-Telerik_8754/telerikLogo-web-174x69px-white_3.png" width="174" height="69"&gt;&lt;/a&gt;Michelle and I will continue to run our team from our office in Hudson, Ohio. This location is now Telerik’s 5&lt;sup&gt;th&lt;/sup&gt; US office, and the first Ohio office. You can read more details in the &lt;a href="http://www.telerik.com/company/press-center/company-news/telerik-acquires-partner-nimblepros.aspx"&gt;official press release&lt;/a&gt; and on &lt;a href="http://nimblepros.com/"&gt;NimblePros’ home page&lt;/a&gt;, and of course you can learn more about &lt;a href="http://telerik.com/services"&gt;Telerik’s Service Offerings on our web site&lt;/a&gt;.&lt;a name="_GoBack"&gt;&lt;/a&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/YxIgkoOOmSCxRg0sEEDsI8OdIzQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/YxIgkoOOmSCxRg0sEEDsI8OdIzQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/YxIgkoOOmSCxRg0sEEDsI8OdIzQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/YxIgkoOOmSCxRg0sEEDsI8OdIzQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=KaAEglIg1lE:M9QwpjT3Cjw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=KaAEglIg1lE:M9QwpjT3Cjw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=KaAEglIg1lE:M9QwpjT3Cjw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=KaAEglIg1lE:M9QwpjT3Cjw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=KaAEglIg1lE:M9QwpjT3Cjw:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=KaAEglIg1lE:M9QwpjT3Cjw:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StevenSmith/~4/KaAEglIg1lE" height="1" width="1"/&gt;</description><pubDate>Thu, 26 Apr 2012 14:16:53 GMT</pubDate><guid isPermaLink="true">http://ardalis.com:80/joining-telerik</guid></item><item><title>Principles of Product Development Flow Book Review</title><link>http://ardalis.com:80/principles-of-product-development-flow-book-review</link><description>&lt;p&gt;&lt;a href="http://amzn.to/yzqWOR"&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="image" border="0" alt="image" align="right" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Principles-of-Product-Development-Flow-B_11F91/image_3.png" width="240" height="240"&gt;&lt;/a&gt;One of the more advanced books I’ve read relating to the subjects of Software Development and Lean is &lt;a href="http://amzn.to/yzqWOR"&gt;The Principles of Product Development Flow: Second Generation Lean Product Development&lt;/a&gt; by Donald G. Reinertsen.&amp;nbsp; I recently published &lt;a href="http://www.pluralsight-training.net/microsoft/courses/TableOfContents?courseName=kanban-fundamentals"&gt;a Pluralsight course on Kanban Fundamentals&lt;/a&gt;, and as part of my research for that introductory-level course I read a few related titles, including this one.&amp;nbsp; I previously reviewed some of the others:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://ardalis.com/personal-kanban-book-review"&gt;Personal Kanban Book Review&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://ardalis.com/kanban-book-review"&gt;Kanban Book Review&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://ardalis.com/reviewing-scrumban-the-book"&gt;Scrumban Book Review&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;If you were looking into learning more about kanban and lean as it relates to software development projects, I would probably suggest you read them in the order I have listed above, with Principles of Product Development Flow following these.&amp;nbsp; It is certainly the most advanced of the books.&amp;nbsp; It also has the most to offer to any product-oriented business, and does a good job of debunking certain myths about lean as it relates to software development.&amp;nbsp; Unsurprisingly, writing custom software without a script is not entirely analogous to manufacturing known goods using known techniques as quickly as possible.&amp;nbsp; Reinertsen does a good job of demonstrating where and how lean manufacturing principles do not directly apply to software product development, and provides models and principles that can be applied with confidence.&lt;/p&gt; &lt;p&gt;Principles of Product Development Flow is organized into nine sections.&amp;nbsp; The first one, The Principles of Flow, sets up the rest of the book by describing the problems with the current accepted best-practices of product development.&amp;nbsp; It is in this section that the author first mentions that the book is organized into 175 principles.&amp;nbsp; When I first read that, I thought it was a typo, but it is in fact correct.&amp;nbsp; The book’s organization into small, cohesive principles is actually a great feature, as they are easily able to reference one another and they are easy to refer to yourself as needed.&amp;nbsp; In some ways, the author’s organization of the book is akin to well-designed software, with small, focused modules organized into larger, cohesive modules.&lt;/p&gt; &lt;p&gt;If you’re debating whether to buy this book, this section is the one to read, as it will “sell” you on the book’s promise (not in a bad way – it does a good job of demonstrating the need for the book to exist).&amp;nbsp; Just a few of the important points described are a general failure to apply basic economics to decisions relating to product development, a systemic blindness to queues in software and knowledge work development, a worship of efficiency, and a blind hostility toward all sources of variability.&amp;nbsp; These, and eight other, problems are described in the first section, with the remainder of the book dedicated to solutions to these problems.&lt;/p&gt; &lt;p&gt;The second section focuses on the economics of how we control projects.&amp;nbsp; One of the recurring themes in the book is the U-Curve, first introduced in this chapter with principle E6: The U-Curve Principle: Important trade-offs are likely to have U-curve optimizations.&amp;nbsp; That is, when making a decision, it’s unlikely that only a single variable is involved – usually there are at least two worth considering.&amp;nbsp; For example, when considering the optimal batch size for a given process, one should consider, at a minimum, the Holding Cost, which increases as batch sizes (and presumably time) increase, and Transaction Cost, which increases as batch sizes shrink.&amp;nbsp; A typical curve is shown here.&amp;nbsp; &lt;/p&gt; &lt;p&gt;&lt;img style="display: inline" src="http://continuousdelivery.com/wp-content/uploads/2011/12/Fig2-2rev1-Humble.jpg" width="400" height="333"&gt;&lt;/p&gt; &lt;p&gt;Reinertsen suggests that when considering the optimal batch size, one should consider the U-Shaped Total Cost, as opposed to blindly believing that small batches are always better or striving for One Piece Flow (a nirvana of some lean approaches).&amp;nbsp; Note too that these curves are merely examples, and that in order to apply this principle you must first understand the nature of the holding and transaction costs that apply to your process.&amp;nbsp; You can also then work on changing the shape of these curves in order to lower your total cost, perhaps reducing transaction costs through automation.&lt;/p&gt; &lt;p&gt;The next eight sections of the book cover these major themes:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Economics&lt;/li&gt; &lt;li&gt;Queues&lt;/li&gt; &lt;li&gt;Variability&lt;/li&gt; &lt;li&gt;Batch Size&lt;/li&gt; &lt;li&gt;WIP Constraints&lt;/li&gt; &lt;li&gt;Cadence, Synchronization, and Flow Control&lt;/li&gt; &lt;li&gt;Fast Feedback&lt;/li&gt; &lt;li&gt;Decentralized Control&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Again, there are 175 principles covered.&amp;nbsp; A few highlights I noted include:&lt;/p&gt; &lt;p&gt;Principle Q14: Don’t control cycle time, control queue size.&amp;nbsp; Cycle time is a trailing indicator; queue size is a leading indicator.&amp;nbsp; Thus, measure and manage queue size.&lt;/p&gt; &lt;p&gt;Queue size multiplies the cost of delays.&amp;nbsp; When we have 20 jobs in a queue, a 5 minute delay generates 100 minutes of delay time.&amp;nbsp; When there are only two jobs in line, a 5 minute delay generates 10 minutes of delay time.&amp;nbsp; You can apply this same logic to overloaded web servers, for which queued HTTP requests immediately result in massive performance degradation.&lt;/p&gt; &lt;p&gt;On variability: &lt;em&gt;We cannot add value without adding variability, but we can add variability without adding value.&lt;/em&gt;&lt;/p&gt; &lt;p&gt;A key point in the variability chapter and the book as a whole is that small batch sizes and low variability are not universally desirable.&amp;nbsp; Rather, there are economic payoff functions for each and cases where reducing batch size or variability can actually be the wrong decision, economically (which of course should be our basis for decision-making).&amp;nbsp; When we do wish to reduce variability, one way to do so is by using principle V5, Variability Pooling: Overall variation decreases when uncorrelated random tasks are combined.&lt;/p&gt; &lt;p&gt;On WIP constraints, there are several principles that can be used to attack queues as they emerge.&amp;nbsp; W9 suggests that when a queue begins to emerge, adding even inefficient resources to it can have a dramatic effect on throughput.&amp;nbsp; W10 notes that part-time resources that are up-to-speed on the task at hand have great “surge” potential when needed.&amp;nbsp; W11 suggests that the “Big Guns” – the best talent in the organization – be kept available to combat emerging bottlenecks rather than being over-utilized, as is typically the case in most organizations.&amp;nbsp; Finally, W12 introduces the notion of “T-Shaped Resources” – team members who have a wide breadth of skill but are masters of one area, or “jack of all trades, master of ONE.”&amp;nbsp; These offer great flexibility, as they can shift to other assignments as needed to combat queues.&lt;/p&gt; &lt;p&gt;There’s a wealth of additional information on the effects of congestion on highways and how this applies to product teams as well as comparisons of synchronized and unsynchronized batches and adjacent operations.&amp;nbsp; Reinertsen uses telecommunication and Internet routing protocols as models for how to efficiently route and prioritize work packets from a source to a destination, and then shifts gears to explain how the US Marines Corps deftly combines centralization and decentralization to successfully manage warfighting in the face of extreme uncertainty.&amp;nbsp; I found the many principles to be well-founded, interesting, and applicable to software development in general and product development in particular.&lt;/p&gt; &lt;p&gt;Have you read the book?&amp;nbsp; What did you think of it?&amp;nbsp; Let us know.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ka6v5MyDbVaiveaJWEQEVA9mv4k/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ka6v5MyDbVaiveaJWEQEVA9mv4k/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ka6v5MyDbVaiveaJWEQEVA9mv4k/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ka6v5MyDbVaiveaJWEQEVA9mv4k/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=xdPxFgL9ay0:WyGJ7F719So:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=xdPxFgL9ay0:WyGJ7F719So:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=xdPxFgL9ay0:WyGJ7F719So:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=xdPxFgL9ay0:WyGJ7F719So:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=xdPxFgL9ay0:WyGJ7F719So:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=xdPxFgL9ay0:WyGJ7F719So:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StevenSmith/~4/xdPxFgL9ay0" height="1" width="1"/&gt;</description><pubDate>Wed, 25 Apr 2012 13:49:33 GMT</pubDate><guid isPermaLink="true">http://ardalis.com:80/principles-of-product-development-flow-book-review</guid></item><item><title>New is Glue</title><link>http://ardalis.com:80/new-is-glue</link><description>&lt;p&gt;When you’re working in a strongly typed language like C# or Visual Basic, instantiating an object is done with the &lt;strong&gt;new&lt;/strong&gt; keyword.&amp;nbsp; It’s important that we recognize the significance of using this keyword in our code, because I would venture to say that well over 90% of developers don’t give it a second thought.&amp;nbsp; Most developers have, at one time or another, heard the practice of building software applications likened to building something out of LEGO bricks (I’ve even written about &lt;a href="http://ardalis.com/Tight-Coupling,-Legos,-and-Super-Glue"&gt;LEGOs and software&lt;/a&gt; in the past).&amp;nbsp; A few days ago, it occurred to me that I could sum up my thoughts on this topic in three words, which I might hope would be memorable enough to “stick” in developers’ minds:&lt;/p&gt; &lt;h2&gt;New is Glue&lt;/h2&gt; &lt;p&gt;Any time you use the new keyword, you are gluing your code to a particular implementation.&amp;nbsp; You are permanently (short of editing, recompiling, and redeploying) hard-coding your application to work with a particular class’s implementation.&amp;nbsp; &lt;/p&gt; &lt;p&gt;That’s &lt;strong&gt;huge&lt;/strong&gt;.&amp;nbsp; &lt;/p&gt; &lt;p&gt;&lt;a href="http://flic.kr/p/4B6vxi" target="_blank"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px 0px 5px 5px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" border="0" align="right" src="http://farm3.staticflickr.com/2288/2366222595_6c6ac32a24_m.jpg"&gt;&lt;/a&gt;That’s like your code’s getting married, forever and ever, until redeployment do us part.&amp;nbsp; Once you’ve said the words (&lt;em&gt;new&lt;/em&gt;) and exchanged some vows (type metadata) and exited the church (deployed), changing your code’s chosen partner becomes a very expensive endeavor.&amp;nbsp; This is a big decision for you and your application.&amp;nbsp; You need to be very sure that this is the one and only implementation your code will ever need to work with, or else think about calling the whole thing off.&lt;/p&gt; &lt;p&gt;The marriage metaphor is taking things a bit far, I know, but let me add one more bit before we leave it behind us.&amp;nbsp; It’s quite likely that your code is going to need behavior from more than one other class.&amp;nbsp; In fact, it’s quite common that you’ll need to work with other classes in virtually every class within your application.&amp;nbsp; If you go the &lt;em&gt;new&lt;/em&gt; route, that’s a lot of overlapping marriages that all need to stay happy for your application to work effectively.&lt;/p&gt; &lt;p&gt;But what if the behavior or service you need is only found in one place?&amp;nbsp; Maybe it’s not the perfect, now-and-forever class, but it’s the one that has what you need &lt;em&gt;right now&lt;/em&gt;?&amp;nbsp; What am I suggesting, that one forego leveraging any other classes, and just do everything yourself?&amp;nbsp; Not at all, but let’s go with another metaphor now.&lt;/p&gt; &lt;h2&gt;Favor Contractors over Employees&lt;/h2&gt; &lt;p&gt;Your application requires certain services to do its job.&amp;nbsp; Think of your application like a small business.&amp;nbsp; There are things your application does, and things it needs to do its job.&amp;nbsp; A small business might need office space, and beyond that, certain utilities like electricity, phone service, internet service, shipping, etc.&amp;nbsp; In a business, relationships you have with service providers and contractors are relatively easy to change, while relationships you have with employees can be somewhat more difficult (for purposes of this analogy, pretend we’re talking about a country where firing people is very difficult/expensive).&amp;nbsp; Now think about which approach to running a small business makes more sense.&lt;/p&gt; &lt;p&gt;In the first scenario, your business’s needs are each met by a full-time resource.&amp;nbsp; You have Bob, the electrician, who ensures your electricity works, Joan, the telecom expert, who ensures your phone service is connected, and Joe, the truck driver, who takes care of delivering everything you ever need to send.&amp;nbsp; You also need an office to hold all of these people, which of course you leased with a 5 year lease that’s every expensive to get out of.&lt;/p&gt; &lt;p&gt;In the second scenario, your business’s needs are all met by service providers or contractors.&amp;nbsp; You use standard utility companies for electricity, phone, internet, and you can switch from one to another with only a small amount of pain if one fails you.&amp;nbsp; You ship with FedEx, USPS, UPS, etc. based on whichever one fits your needs of the day.&amp;nbsp; Your office space is just big enough for you, and since you’re still growing and aren’t sure how your needs will change, you’re paying month-to-month.&amp;nbsp; &lt;/p&gt; &lt;p&gt;Which of these two scenarios provides the greater degree of freedom for the business to adapt to future needs?&amp;nbsp; Which one is locked into a particular implementation and will be hard-pressed to change when needed?&lt;/p&gt; &lt;h2&gt;Decoupling Services from Providers&lt;/h2&gt; &lt;p&gt;New is Glue.&amp;nbsp; It binds your code to a particular collaborator.&amp;nbsp; If there is any chance you’ll need to be flexible about which implementation your code will need, it’s worth introducing an interface to keep your code loosely coupled.&amp;nbsp; It doesn’t matter what the service is you need – you can always replace it with an interface even if your class is the only one that uses it.&amp;nbsp; Let’s say your code needs send an email, with default code that looks like this:&lt;/p&gt; &lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; (var client = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; SmtpClient())&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; (var message = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; MailMessage(fromEmail, toEmail))&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    message.Subject = subject;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    message.Body = bodyHtml;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    message.IsBodyHtml = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    client.Send(message);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;Note the two new keywords here, gluing whatever else this class is doing to this implementation of message sending.&amp;nbsp; This can be replaced with an interface like this one:&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IEmailClient&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; SendHtmlEmail(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; fromEmail, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; toEmail, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; subject, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; bodyHtml);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Now the code that used to contain the first block of code can be rewritten to simply use the interface:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; SomeService&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; IEmailClient _emailClient;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; SomeService(IEmailClient emailClient)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        _emailClient = emailClient;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; DoStuff(User user)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; subject = &lt;span style="color: #006080"&gt;"Test Subject"&lt;/span&gt;;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; bodyHtml = GetBody(user);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        _emailClient.SendHtmlEmail(&lt;span style="color: #006080"&gt;"noreply@whatever.com"&lt;/span&gt;, &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;user.EmailAddress, subject, bodyHtml);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Edited:&lt;/strong&gt; Please assume that DoStuff() does some useful value-added work, and that sending an email to the user is just something it does as a side effect, perhaps only when it’s successful, and not that it’s the main intent of the method, if that helps you think about the value of removing the dependency on SmtpClient.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;How many new keywords are in this class, now?&amp;nbsp; Run a search in Visual Studio to find how many instances of new you’re using in your solution, and where.&amp;nbsp; Use ctrl-shift-F to find in files, search for “new”, Entire Solution, Match case, Match whole word, and Look at these file types: *.cs.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ardalis.com/Media/Default/Windows-Live-Writer/New-is-Glue_9C51/SNAGHTML2f30b1.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="SNAGHTML2f30b1" border="0" alt="SNAGHTML2f30b1" src="http://ardalis.com/Media/Default/Windows-Live-Writer/New-is-Glue_9C51/SNAGHTML2f30b1_thumb.png" width="270" height="431"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Have a look at the total numbers, the numbers of files, etc.&amp;nbsp; In one very small ASP.NET MVC application I’m working on now, this search yields 280 matching lines in 25 files out of 47 files searched.&amp;nbsp; Four of the files and 28 of the matches are in my tests project.&amp;nbsp; The lion’s share of the rest of the matches are from SqlHelper.cs.&amp;nbsp; My controllers have a total of 7 matching lines, and all of these relate to creating model/viewmodel types, not services.&lt;/p&gt;
&lt;h2&gt;When is it Acceptable to use New?&lt;/h2&gt;
&lt;p&gt;Using new isn’t wrong, it’s a design decision.&amp;nbsp; Like all design decisions, it should be an informed decision, not a de facto one.&amp;nbsp; Use it when you don’t expect you’ll need flexibility in the future.&amp;nbsp; Use it when it won’t adversely affect the usability of your class by its clients.&amp;nbsp; Consider the transitivity of the dependencies you take on within your class – that is, how the things you depend on in turn become dependencies for classes that use your classes.&amp;nbsp; Consider too how your design decisions and considerations today may change in the future.&amp;nbsp; One common example of this is applications that hard-code dependencies on local system resources like the file system, local memory (session, cache, global collections), and local services like email.&amp;nbsp; When the application needs to scale out to multiple front-end machines, problems ensue.&amp;nbsp; Loosely coupling these resources together would make implementing a webfarm- or cloud-optimized version of these services trivial, but thousands of new statements gluing implementations together can take a long time to fix.&lt;/p&gt;
&lt;p&gt;One last thing to think about, if you actually do search your code for new, is how many duplicate lines you find.&amp;nbsp; Remember the &lt;a href="http://deviq.com/most-popular-principles/don-t-repeat-yourself" target="_blank"&gt;Don’t Repeat Yourself&lt;/a&gt; (DRY) and &lt;a href="http://deviq.com/single-responsibility-principle" target="_blank"&gt;Single Responsibility&lt;/a&gt; (SRP) principles.&amp;nbsp; If you’re instantiating the same class in the same way in more than one place in your code (e.g. 10 places where you new up a new SqlConnection), that’s a DRY violation.&amp;nbsp; If you have ten different classes that all do some kind of work, AND need to know how to create a SqlConnection, that’s an SRP violation.&amp;nbsp; Knowledge of how to talk to the database should be in only one location, the responsibility of a single class.&amp;nbsp; The same is true for any other resource that you find you’re commonly instantiating in many different classes.&amp;nbsp; The exceptions here would be low-level intrinsics like strings, datetimes, and things like exceptions that generally are created only in exceptional cases.&lt;/p&gt;
&lt;h2&gt;Moving Forward&lt;/h2&gt;
&lt;p&gt;Learn to look for new in your code and in code reviews.&amp;nbsp; Question whether it’s appropriate when you see it.&amp;nbsp; Work on pushing the responsibility of choosing which classes your code will work with into as few classes as possible, and see if your code doesn’t start to become more loosely coupled and easier to maintain as a result.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/k3Ng6XTZgo8YkFg0SHfcFDmmoVM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/k3Ng6XTZgo8YkFg0SHfcFDmmoVM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/k3Ng6XTZgo8YkFg0SHfcFDmmoVM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/k3Ng6XTZgo8YkFg0SHfcFDmmoVM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=-QCZHFwkW20:BHJgVq2_IN8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=-QCZHFwkW20:BHJgVq2_IN8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=-QCZHFwkW20:BHJgVq2_IN8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=-QCZHFwkW20:BHJgVq2_IN8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=-QCZHFwkW20:BHJgVq2_IN8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=-QCZHFwkW20:BHJgVq2_IN8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StevenSmith/~4/-QCZHFwkW20" height="1" width="1"/&gt;</description><pubDate>Fri, 13 Apr 2012 13:56:32 GMT</pubDate><guid isPermaLink="true">http://ardalis.com:80/new-is-glue</guid></item><item><title>Modifying and Disabling Hyperlinks using jQuery</title><link>http://ardalis.com:80/modifying-and-disabling-hyperlinks-using-jquery</link><description>&lt;p&gt;I have a simple menu in an ASP.NET MVC application allows a user to take one of several actions after first selecting a resource to work with from a drop down list / select box or textbox.&amp;nbsp; In the case where the user hasn’t yet selected anything (or entered any text), I want the links to be disabled, as I’d rather let the user know the issue on the current dashboard page than have them go to a page without a required parameter and &lt;strong&gt;then&lt;/strong&gt; hit them with an error message about the missing parameter.&amp;nbsp; Instead, I’d like to, in the case of the empty textbox, give the textbox focus and flash some color there so the user (usually me) knows they need to enter something there before proceeding.&lt;/p&gt; &lt;p&gt;You can’t just .disable() a hyperlink or anchor tag using jQuery, nor can you .enable() it.&amp;nbsp; There’s also a bit of magic involved in being able to take the contents of a textbox or select list and stick them into the URL in a link, which I’ll also show here.&amp;nbsp; For my menu, it’s organized inside of an unordered list (&amp;lt;ul&amp;gt;) with individual list items (&amp;lt;li&amp;gt;) and anchors (&amp;lt;a&amp;gt;).&amp;nbsp; It’s pretty straightforward to select and work on each such link using a jQuery selector.&lt;/p&gt; &lt;p&gt;Here’s the HTML for one of the two menus I’m working with, the one that requires a textbox.&amp;nbsp; The other one is set up identically except it has a drop down list.&lt;/p&gt; &lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;h2&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;Email Admin Menu&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;h2&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;fieldset&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;label&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;Email Address:&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;label&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;input&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="text"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="email"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;fieldset&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;div&lt;/span&gt; &lt;span style="color: #ff0000"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="menu"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;ul&lt;/span&gt; &lt;span style="color: #ff0000"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="navlist"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="email-menu"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;@Html.ActionLink("Unsubscribe Email from All Lists", "UnsubAll", "EmailAdmin")&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;@Html.ActionLink("Change Email for All Lists", "ChangeEmail", "EmailAdmin")&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;ul&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;div&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2&gt;Getting the Value from the Textbox or DropDownList&lt;/h2&gt;
&lt;p&gt;The first thing I need in either menu is the value the user has provided in the &amp;lt;input type=text&amp;gt; or &amp;lt;select&amp;gt; form field.&amp;nbsp; Here are the two ways to do this – jQuery 101 stuff:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #008000"&gt;// get selected text from &amp;lt;select&amp;gt; list&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;var&lt;/span&gt; selectedList = $(&lt;span style="color: #006080"&gt;'#SelectedListName :selected'&lt;/span&gt;).text();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #008000"&gt;// get text from an &amp;lt;input type='text'&amp;gt; field&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;var&lt;/span&gt; selectedEmail = $(&lt;span style="color: #006080"&gt;'#email'&lt;/span&gt;).val();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;h2&gt;Appending a Value to a Link in an Anchor&lt;/h2&gt;
&lt;div&gt;Next, I’ve set up my routes in ASP.NET MVC so that the last bit of each URL is the resource being worked with – in this case an email address the user enters into a textbox.&amp;nbsp; Whenever the user enters something, I want the value to be automatically tacked onto the end of all of the different links within the corresponding menu.&amp;nbsp; However, I can just append the value to whatever the link is currently, because then the link would continue to grow and grow and grow if the user changed their mind and typed or selected a few different things before clicking a link.&amp;nbsp; Thus, I need to only replace the last section of the link, after a certain number of ‘/’ characters.&amp;nbsp; Here’s the code to update all of the links within a menu, using the .each() function:&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;$(&lt;span style="color: #006080"&gt;'ul#list-menu &amp;gt; li &amp;gt; a'&lt;/span&gt;).each(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; () {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; href = $(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;).attr(&lt;span style="color: #006080"&gt;'href'&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; parts = href.split(&lt;span style="color: #006080"&gt;'/'&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; baseUrl = parts.slice(0, 3).join(&lt;span style="color: #006080"&gt;'/'&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    $(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;).attr(&lt;span style="color: #006080"&gt;'href'&lt;/span&gt;, baseUrl + &lt;span style="color: #006080"&gt;'/'&lt;/span&gt; + selectedList);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;});&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2&gt;Enabling and Disabling Links using jQuery&lt;/h2&gt;
&lt;p&gt;The last step is to make sure that the links don’t work until the user has entered a value into the textbox (for the dropdownlist, it will always have some valid resource selected, so I don’t need to do this).&amp;nbsp; The way you disable clicking on an anchor tag from navigating to the corresponding href URL is by binding the click() event and calling e.preventDefault().&amp;nbsp; This will prevent the default behavior of the click, namely the navigation to the URL.&amp;nbsp; In my case, I’m doing this whenever the textbox has zero length – I could do more advanced validation but this is sufficient for this example – and when this occurs I’m also highlighting the textbox in red and giving it focus.&lt;/p&gt;
&lt;p&gt;Once you’ve added a .click() event handler, you can’t simply add another one to undo the effect, as this will cause both to happen.&amp;nbsp; So, you could wire up the .click() handler to call a named function, and do your validation checking in that function, or you can unbind the .click() handler when it’s not needed, which is the approach I’m showing here.&amp;nbsp; The full function for adjusting the links in the email-based menu is shown below, which includes the code required to modify the URLs similarly to what was shown above.&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; updateEmailLinks() {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; selectedEmail = $(&lt;span style="color: #006080"&gt;'#email'&lt;/span&gt;).val();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    $(&lt;span style="color: #006080"&gt;'ul#email-menu &amp;gt; li &amp;gt; a'&lt;/span&gt;).each(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; () {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; href = $(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;).attr(&lt;span style="color: #006080"&gt;'href'&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; parts = href.split(&lt;span style="color: #006080"&gt;'/'&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; baseUrl = parts.slice(0, 3).join(&lt;span style="color: #006080"&gt;'/'&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        $(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;).attr(&lt;span style="color: #006080"&gt;'href'&lt;/span&gt;, baseUrl + &lt;span style="color: #006080"&gt;'/'&lt;/span&gt; + selectedEmail);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (selectedEmail.length == 0) {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            &lt;span style="color: #008000"&gt;// disable links&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            $(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;).click(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; (e) {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                e.preventDefault();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                $(&lt;span style="color: #006080"&gt;'#email'&lt;/span&gt;).effect(&lt;span style="color: #006080"&gt;"highlight"&lt;/span&gt;, { color: &lt;span style="color: #006080"&gt;'red'&lt;/span&gt; }, 2000);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                $(&lt;span style="color: #006080"&gt;'#email'&lt;/span&gt;).focus();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            });&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            &lt;span style="color: #008000"&gt;// re-enable&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            $(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;).unbind(&lt;span style="color: #006080"&gt;'click'&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    });&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2&gt;Wiring Things Up&lt;/h2&gt;
&lt;p&gt;Once you have these things set up, all that remains is to wire them up when the page loads.&amp;nbsp; In this case, we want the updating of the links to occur any time the corresponding UI element changes.&amp;nbsp; I’m also setting up the textbox to autocomplete based on emails in the system already.&amp;nbsp; In addition to firing when the UI element changes, I need the functions to each run one time when the page loads, so that the URLs are set accordingly and the links are disabled if the textbox is empty.&amp;nbsp; Here’s the on-page-load function:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;$(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; () {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    $(&lt;span style="color: #006080"&gt;'#SelectedListName'&lt;/span&gt;).change(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; () {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        updateListLinks();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    });&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    updateListLinks();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    $(&lt;span style="color: #006080"&gt;"#email"&lt;/span&gt;).autocomplete({&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        source: &lt;span style="color: #006080"&gt;"/Admin/Emails"&lt;/span&gt;,&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        minLength: 2,&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        change: &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;event&lt;/span&gt;, ui) {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            updateEmailLinks();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    });&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    updateEmailLinks();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;});&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;I’m far from being a jQuery expert, but I was able to get all of this working very quickly with some help from &lt;a href="http://jqueryui.com/" target="_blank"&gt;jQueryUI.com&lt;/a&gt; and &lt;a href="http://stackoverflow.com/" target="_blank"&gt;StackOverflow.com&lt;/a&gt;, which has a ton of jQuery questions and answers.&amp;nbsp; I’m not currently using an MVVM style of client-side programming, although I expect to learn to do so in the very near future using frameworks like &lt;a href="http://knockoutjs.com/" target="_blank"&gt;Knockout&lt;/a&gt; and &lt;a href="http://www.kendoui.com/" target="_blank"&gt;KendoUI&lt;/a&gt;, which for this code wouldn’t make a huge difference, but might clean it up some by letting me bind things to a model, rather than to the selected element of some UI element.&amp;nbsp; This would clean up the menu link URL logic significantly, as I could just bind the links to a model with a property for the URL that was dynamically created, for instance.&amp;nbsp; This is left as an exercise for the reader, or perhaps a follow-up article in the future.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/0_UM8p_fGTJNg_4Ru4-ASQRKAag/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0_UM8p_fGTJNg_4Ru4-ASQRKAag/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/0_UM8p_fGTJNg_4Ru4-ASQRKAag/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0_UM8p_fGTJNg_4Ru4-ASQRKAag/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=4vTIPCR5wno:lJMitUZsla0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=4vTIPCR5wno:lJMitUZsla0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=4vTIPCR5wno:lJMitUZsla0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=4vTIPCR5wno:lJMitUZsla0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=4vTIPCR5wno:lJMitUZsla0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=4vTIPCR5wno:lJMitUZsla0:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StevenSmith/~4/4vTIPCR5wno" height="1" width="1"/&gt;</description><pubDate>Fri, 13 Apr 2012 13:41:37 GMT</pubDate><guid isPermaLink="true">http://ardalis.com:80/modifying-and-disabling-hyperlinks-using-jquery</guid></item><item><title>Beyond Role Based Authorization in ASPNET MVC</title><link>http://ardalis.com:80/beyond-role-based-authorization-in-aspnet-mvc</link><description>&lt;p&gt;A fairly frequent requirement in applications is to check for authorization to perform an action.&amp;nbsp; At the most basic level, this might just involve seeing if the user is authenticated (at all) or checking a flag to see if they are an Admin.&amp;nbsp; However, more complex requirements frequently include a variety of roles, and it’s quite common for the notion of ownership to be involved as well, with some actions being allowed if you own the item being worked on, and otherwise not.&amp;nbsp; I’ve written about using the notion of &lt;a href="http://ardalis.com/favor-privileges-over-role-checks" target="_blank"&gt;Privileges over Role Checks&lt;/a&gt; for this exact purpose in the past, as a way to ensure the logic of such decisions is properly encapsulated so that you can follow the &lt;a href="http://deviq.com/most-popular-principles/don-t-repeat-yourself" target="_blank"&gt;Don’t Repeat Yourself&lt;/a&gt; principle.&amp;nbsp; In that article, I describe how you can test privileges, but I don’t get into how to use them at the UI level, specifically in an ASP.NET MVC application.&lt;/p&gt; &lt;h2&gt;ASP.NET MVC Authorization&lt;/h2&gt; &lt;p&gt;You can do basic authorization in ASP.NET MVC by using attributes.&amp;nbsp; Specifically, the Authorize attribute will let you mark a controller or action as requiring authorization, and you can optionally specify certain roles and/or users who are authorized to perform this action.&amp;nbsp; However, this is as far as the attribute will take you, so by itself it won’t handle the case of letting users perform certain actions on things they own, but not on others’ things.&lt;/p&gt; &lt;p&gt;It’s also worth noting that you can apply filters like Authorize to an entire site by using GlobalFilters (in MVC 3+).&amp;nbsp; For instance, in your global.asax you can add a call to RegisterGlobalFilters(GlobalFilters.Filters) in your Application_Start() and then implement this method like so:&lt;/p&gt; &lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; RegisterGlobalFilters(GlobalFilterCollection filters)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    filters.Add(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; HandleErrorAttribute());&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    filters.Add(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; AuthorizeAttribute());&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then if you have only a few actions that don’t require, for instance, authorization (e.g. home page, login page), you can mark these with the AllowAnonymous attribute (in MVC 4+):&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;[System.Web.Mvc.AllowAnonymous]&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult Login()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2&gt;Authorizing Owners&lt;/h2&gt;
&lt;p&gt;In my case, I’m globally authorizing the users as shown, but then within each action I need to verify that the user is either an administrator or they are the owner of the resource they are managing.&amp;nbsp; Originally, each action had some code in it that looked like this:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;var person = _personRepository.Get(_currentUser.UserId);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!_authorizationService.CanAdministerResource(resourceId, person))&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View(&lt;span style="color: #006080"&gt;"NotAuthorized"&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The problem, of course, is that this is boilerplate code that would need to be added to every action.&amp;nbsp; Not very DRY.&amp;nbsp; At first I thought I might just extract this into its own method, but since it involves a return statement, that doesn’t work well and the best I could do is write a boolean method and keep the if statements in every action method.&lt;/p&gt;
&lt;p&gt;After a bit of research, I found out that OnActionExecuting is the best way to ensure every action within a controller runs a particular bit of code, and further, &lt;a href="http://stackoverflow.com/questions/2271346/how-to-return-different-view-but-presererve-viewmodel-in-onactionexecuting" target="_blank"&gt;how to return a particular view from this method&lt;/a&gt;.&amp;nbsp; With this, I was able to override OnActionExecuting in my controller in question (every action of which will include the resource being worked with) like so:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #008000"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #008000"&gt;/// Verify the current user has permission to manage the resource&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #008000"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #008000"&gt;/// &amp;lt;param name="filterContext"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; OnActionExecuting(ActionExecutingContext filterContext)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; resourceId = filterContext.ActionParameters[&lt;span style="color: #006080"&gt;"resourceId"&lt;/span&gt;] &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    var person = _personRepository.Get(_currentUser.UserId);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!_authorizationService.CanAdministerResource(resourceId, person))&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        filterContext.Result = View(&lt;span style="color: #006080"&gt;"NotAuthorized"&lt;/span&gt;);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.OnActionExecuting(filterContext);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What do you think of this approach?&amp;nbsp; In my case, I only have one controller that needs to do this, but if I had several I could always create a common base controller and push up this code into the base class.&amp;nbsp; I’m sure I could also go the custom action filter route but that seemed like overkill for what I’m looking at doing (and you can’t actually change the behavior of the action from within the filter itself, so there would need to be more moving parts).&amp;nbsp; Any suggestions on how to do this better, or does this seem like a good approach?&lt;/p&gt;
&lt;p&gt;The _currentUser class used here is one I picked up somewhere online (not sure where at this point or I would add a link) that makes it easy to avoid a dependency on HttpContext.&amp;nbsp; It looks like this:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; CurrentUser&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; CurrentUser(IIdentity identity)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            &lt;span style="color: #0000ff"&gt;try&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                IsAuthenticated = identity.IsAuthenticated;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                UserId = Guid.Parse(identity.Name);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            &lt;span style="color: #0000ff"&gt;catch&lt;/span&gt; (Exception ex)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                Debug.Print(ex.ToString());&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; IsAuthenticated { get; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; set; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Guid UserId { get; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; set; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;I inject it into the class using my IOC container, in this case StructureMap.&amp;nbsp; I don’t need to tell StructureMap anything about CurrentUser itself, provided it knows what to do with the constructor parameters.&amp;nbsp; Thus, I include one line to tell it how to get an IIdentity:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;x.For&amp;lt;IIdentity&amp;gt;().Use(() =&amp;gt; HttpContext.Current.User.Identity);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Of course, in my tests I can simply pass in a new CurrentUser() and pass in a mock IIdentity if I care about its settings within the context of a given test.&amp;nbsp; These last bits are separate from the main topic of the post, but I’m including them so the code shown is clear and not missing key ingredients, which I know can be frustrating.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/1_ekO21wfcktfTa2WThmPqqZozk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1_ekO21wfcktfTa2WThmPqqZozk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/1_ekO21wfcktfTa2WThmPqqZozk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1_ekO21wfcktfTa2WThmPqqZozk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=vNKlJuFCq50:e5bZRrsmKeY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=vNKlJuFCq50:e5bZRrsmKeY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=vNKlJuFCq50:e5bZRrsmKeY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=vNKlJuFCq50:e5bZRrsmKeY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=vNKlJuFCq50:e5bZRrsmKeY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=vNKlJuFCq50:e5bZRrsmKeY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StevenSmith/~4/vNKlJuFCq50" height="1" width="1"/&gt;</description><pubDate>Wed, 11 Apr 2012 21:06:38 GMT</pubDate><guid isPermaLink="true">http://ardalis.com:80/beyond-role-based-authorization-in-aspnet-mvc</guid></item><item><title>Configuring Web Apps To Behave Like Native Apps on iOS</title><link>http://ardalis.com:80/configuring-web-apps-to-behave-like-native-apps-on-ios</link><description>&lt;p&gt;There are a number of things you can do with your web-based application to have it behave like a native iOS application.&amp;nbsp; One of these I mentioned previously, which is to &lt;a href="http://ardalis.com/how-do-i-disable-zoom-in-an-ipad-iphone-mobile-web-app"&gt;disable the user’s ability to zoom in and out using pinch gestures&lt;/a&gt;.&amp;nbsp; In addition, you can hide the Safari user interface “chrome” so that the user is unaware they’re in a browser.&amp;nbsp; You can also add splash screens and customize the icon that is shown when users add the web application to their device’s home screen.&lt;/p&gt; &lt;h2&gt;Hide Safari Browser UI&lt;/h2&gt; &lt;p&gt;This is referred to as “standalone mode” for your web application, and is accomplished with this meta tag:&lt;/p&gt; &lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;meta&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="apple-mobile-web-app-capable"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;content&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="yes"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;There will still be a status bar at the top of the application.&amp;nbsp; You can further customize the appearance by setting the status bar to be black, allowing your app to utilize the entire screen.&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;meta&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="apple-mobile-web-app-status-bar-style"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;content&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="black"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;


&lt;h2&gt;Customize iPad or iPhone Icons for Web Apps&lt;/h2&gt;
&lt;p&gt;&lt;img style="display: inline; float: right" align="right" src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBhIQEBUPEhQVEBQUFRAUFRcVFRcUFBUQFhQWFxUQFBcZGyYeGBkjGhUUHzIgIycpLCwsFR4xNzAtNSYrLCkBCQoKDgwOFA0OGCkYFBgpKSkuKSkpKSkpKSkpKSkpKSkpKSkpKSkpKikpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKf/AABEIAKIAyQMBIgACEQEDEQH/xAAbAAACAgMBAAAAAAAAAAAAAAAABwQFAQMGAv/EAEQQAAEDAgIFCAcIAAQGAwAAAAEAAgMEERIUBRMhUZIGFjFBU1Rh0hUiYpOU0eEjMlJxgZGh8AdCsbMzcoSissEkNGP/xAAXAQEBAQEAAAAAAAAAAAAAAAAAAQID/8QAGhEBAQEBAQEBAAAAAAAAAAAAABEBEjECIf/aAAwDAQACEQMRAD8Ass8jPLnM+vMmkw0Fx2ALtHN0b6q/Wg1ey11X0egtIzMEsdLZjtrdZK2Nxb1OwkEgfmt/NTSvdo/iW+VZuLNSDVbLXXsVqic1NK92j+Jb5Uc1NK92j+Jb5UuE1LzyM8onNTSvdo/iW+VY5qaV7tH8S3ypcJqW6sC1tq7rRzU0r3aP4lvlRzU0r3aP4lvlS4TUoVQXrPKHzU0r3aP4lvlRzU0r3aP4lvlS4TUzPINconNTSvdo/iW+VHNTSvdo/iW+VLhNbs2bWRmz/StHNTSvdo/iW+VHNTSvdo/iW+VLhNSM31LZnlE5qaV7tH8S3yo5qaV7tH8S3ypcJqXnkOrVE5qaV7tH8S3yo5qaV7tH8S3ypcJrcKsozpWjmppXu0fxLfKs81NK92j+Jb5UuE1ubVm6255QZeTWk2NLjStcALkMna91vBthdVEWlMQuAR0gg7CCOkEdRV/NR0ueRnlzmfRn1YK3WLbRAPqKdjtrTPACD0FuMXBUVbtHn/5NOf8A94f/ADCmh65lGZVNmnf0LGZd/Quba6zKMyqXMv3/AMLOad/QgucyqVnLeA150bd2uDcV7epfDiwXv97Dtsg1bvz/AECW8XJ3SLS2u9TXZs1RhwjW2d9m6MyYsJGr/wAv5oGdpPlXDTujY5wc6SaGANaWlzXyus1z23u1t+tGkuVsMDo2OdidJLHDhYWuc1774S8Xu0bOlLBnJqpE0V6W8jNIsqX1OKO7oDKHb8RsOlttmFFPyaqGyQg0oMkVc6eSpxM+0ic4kdeI2BFwRswopmaf5Wso9UHRyzOmeWMbE0OcXBuI7CR1BY0PyyhqWyu9eAwODZWzgRujcRcYrm1iOu65Ll3o+aoNK5kT52xSuc9sbxE/CWECzsQtt3FUEfJiqEbnag6rOU9RlnyNkkkjY0iTG8mziThIa49SBujS8er1usZq+nHjbgtvxXtb9VEqeVMTHwMvjzL3MjcwhzLtaXElwNrWHUlkeTtSWGXL2iNcKnJ3Z/wQ3Da18F7+thvZaJuSFXM0BjTRtfVVErWtLb08T4cG0A2GI9Ib0XQN12nIQMRljA2m5kbawNib36iQF7ZpWNxLWvY4tALgHNJDT0OIB2DxKVrOTss2UE1KxrYaWricyzCwSnCGOaL7cVi4HqvtUOLkpUwxRGKnZjyE0MoOGz5nOb6klj6xti8Oq6BuR6aic3G2WNzbhuIPaW4jsDbg2v4KJFyrhdO+AOF4445XPu3V4Huc0Wde3S0pTN5JVTmzt1Dmsldo84TqWXET/tPVjOFth+tuu6seUPJSd1UZqeNupijpMMAwiKbVyOJhIvssHXF9l0DaFVfaDdZzKpGVbyAfu7BsIFx4L1mnf0Ii5zKMyqbMu/oWMy/+hBdZlJzlXZukaoNFgXRusPxOiYXH9SSUys07+hK7lQ4mvqCesxf7TFr59TUPWI1i1IW2QsseWua9v3mOa9t+jE03F/2WEEorvqXlvSuaDI/Uu62ua7YfAgEELdzyou3bwyeVL6nhnkbihp6mZv4o4ZHs/QgWXv0dW9zrPhpfKsTFrvueVF27eGTyo55UXbt4ZPKuDGjqzudb8PL5Vn0dWdzrfh5fKkwd3zyou3bwyeVHPKi7dvDJ5Vwno6s7nW/Dy+VHo6s7nW/Dy+VJg7vnlRdu3hk8qOeVF27eGTyrgzo6t7nWfDy+VHoys7pW/Dy+VJg7znlRdu3hk8qOeVF27eGTyrg/Rtb3OtP/AE8vlWfR1Z3Ot+Hl8qTB3fPKi7dvDJ5Uc8qLt28MnlXCejqzudb8PL5Vg6NrO51vw8vlSYO855UXbt4ZPKjnlRdu3hk8q4P0bWd0rfhpfKj0bWd0rfhpfKkwd5zyou3bwyeVHPKi7dvDJ5Vwfo6s7nW/DS+VZ9HVnc634eXypMK7vnlRdu3hk8qOeVF27eGTyrhPR1Z3Ot+Hl8qDo6s7nW/Dy+VJg7vnlRdu3hk8qOeVF27eGTyrg/R9b3Ot+Hl8qx6Pre51vw83lSYO6l5a0YFxLrD1Nax5JO7a0BcJX1RmmfM4YS83tuAADR+dgF5mpapjS6Slqo2Dpc+CVrQN5JbYLUx4IuDcFXMTWUIQtIF7pacSzQxO2tkmhY4b2OeA4fsvC3aONqmnO6eE/wDeE1T1ilaxoY0BrWgBoGwADoAHUF6zSps8d38rGfO7+VyaXWZUPR/KOCodIyGRshidgkA/yv2+qf2P7Kj07p10FNLM1pc5jHFoaC4l/Q0AAbyEutDU1dQO9WDA+opJo8TX6zFWNDpY5n2HqOJcRY/uinM/TMbZm05cBI9r3tb1ljbBzv0uFh+mYxM2nLgJXMdI1vWWNNi78rkJMaNfJrWSUuZdMKCrDnTaw2qyG3DTINjr9Q2XsrDkg4ekIJI8w8CjkbK6fWkCoLml7QXjYei4Gzot1oG0NKM1mqxN1mHHhv62C9sVt19l1uzKU3KRkrdITzQtkEz6B4hILy0zBxuB/lDsG0A9dj0rdyMq3Cr+wM7oMs3X68ykZzEPu6zbitivbYgZLdORGV1OHjWMY17m9YY69nH9is6O01HURiaFwkY6+Fw6DYkH+QUua2jnl0rO+OaWlGVgGKNrSH2LvUu9pH7LmNGOeynp46rMsgbTVGrEWtac5rn/AH9WL4sOGwOxA9syjMpL1TKyVn2zqhsjNFl/qPey9U1ziwuw/efa129a8Vrq2JsohdUHWUdHLIS6R7tYZbTOZ1tdg6m7bXQOvMqlrOXlFDPlpJ2Mlu0FpvZrj0Nc61mk+JXKcgKmQNn9d0kRe3VBwmAb6vrhjpvXc29unoK57T9S6KaqEOua+WXG6llp8xT1TzhtIxwHqg26zs8EDmzKMylJBVvdXONRm2VGYh1LIS7UilwjYbgxmPpxE+soLoqpujzMH1Bc+qc2a75TgpGzP2Ma31g29iS3bY7kDpzKMykfNPVamIGSV1Jr6gk2qW2bgGrYXD7Z0eLFY7+lTaOmqJjFHPJUPaKGpdcGWEueJfssfXiDbdO02CBxZlGaXH8ktJSmhpzLcyapmIuuHF291+tW+eO7+UFzmUkuU1IyGvqYoxhYHscGjoBfG1zgNwuSmoK47v5St5UvvpCoO8xf7TFr59Z1WoQhbZC9RSFj2SAXLHsfbfhINl5QSgaFFpqCZoeyRhB6i4BwO5wO0Fb83H+NnEPmk9LVxXs7AT4tDj/ovGbg3R8H0WI1Tlzcf42cQ+aM3H+NnEPmk1m4N0fB9FkVcG6Pg+iQpyZyP8bOIfNGcj7RnEPmk5moN0fB9EZqDdHwfRIU483H+NnEPmjNx9oziHzSaNVBuj4PojNwbo+D6JCnLm4/xs4h80ZyPtG8Q+aTWbg3R8H0XrNQbo+D6JCnHnI/xs4h80ZyP8bOIfNJzNQbo+D6IzUG6Pg+iQpx5uPtGcQ+aM3H2jeIfNJvNQbo+D6LBq4N0fB9EhTlzcfaN4h80ZuP8bOIfNJsVcG6Pg+izmoN0fB9EhTjzkf42cQ+aM5H+NnEPmk5moN0fB9EZqDdHwfRIU483H+NnEPmjNx/jZxD5pNmqg3R8H0WM3BuZwfRIU4KjScMbS58jGgdZcPntS10pWCeoknAID3DDfpwtaGgn87XVZHVw9WAHfhA/mylXVzE3QhCFpAsw0+tkihuW62WKMkdIa9wBI/QrC36NNqmnO6eA/8AeE1Tr0fommp42xRQxta0WHqNJ/Mki5PipOqi7OP3bPkq0148Vj0gPFcm1g8wNIBZECdgBYwEncNm1AMBcW4IsQ2kYGXA3kWuld/ifKXz0jm3xRCqmbvxxCOQW/RpH6qkpeUOrq6vSQcYzUU0kkbsOMtaalsUdmki+xo6d6B2P1LelkQuQBdjBcnoA2dKywQu2hkR2kbGMO0dI6En28qp5PsZnibVV+jg0vET3Br7lwJZ6mIEbCOjeup/w/rAKebp/wDt1p/eUoO2ZqSLhkRG3aGMI2dPUsxiFwDmsicD0EMYQfyICWvIPlJTx0ToHSxiUzVlmFzcRLpHYRhJubqs0Np6qfFTwRTZZvo+Wc4Ioz9oyRwGEEWaN9kDdtDfDgiva9sDL232svWqi7OP3bPkklJywqBOyqB1Zmo9HiomDQdSwzPxSBh6bk23C67nl1Vl2i6jA9zSIScQsS4AXtfcd4Qdpqouzj92z5LGri7OP3bPklHWcrahjZGtrNSKWkp5YrtjOae5lziv0i4wWb1q95b6SfNoZ8l3QvMUT3AeOEuZt2gXP57EHfAQkkBkRItcYGXF+i+xYbqSSAyIkbCAxhIO47NiTtXpKohlr6qCpIMMOj3k4GO1xEYHrnoAIJ+6pdXylnY6sMLmRPfVUbb/AGcb3MdAC5rHvGHWbi/qQNrVRdnH7tnyWlk1OThAhJ3BsZP7WXK8ieUjqimxPc6R7ZJI3FzGsddp+6cBLXEX+83YVwWg9AyVN3RwwxltfK81WMicNZLcxtaB0W2bT1oHbqouzj92z5I1UXZx+7Z8koqfl/U5prmSmeOU1wEbmxtH2Ub3MDGtJe3a0C7jt3Lzo7l1VB0ThUisMlJVVD4gxg1c7Yy5sXq7bA9R27Cgb+qi7OP3bPkjVRdnH7tnyS05C8qqqabDNK2dj4Gyn1ocbJC4bGtjNxGQT97aC1dznx4oJ09HBI0sfFE5rhYgxt2j9kk9N6NbTVk9NHfBG9uC+0hr2NeG38MVv0Tez48UqOVb8WkKg7zD/tMWvn1nVahCFtkL3Ty4JI5D0Mkjef8Ala4ErwhFNqGVr2h7SHNIBBG0Eb17wpRCYs+657BfoY9zR+wXs17+0m965Y5WmvJTNcQXNa4i4BLQSAdhAJ6LrWdGxWw6plsOC2BtsF74LW+7fq6EqzXv6pJveuWzOSdpN71yclNBmi4m7BFGPunZG0bW/dPR1dW5bY6cNFmtDQSSbADaek7OspVZyTtJveuWHVklv+JN71yclM5uiIQcQhiDr3vq2Xvvva91ujoWNtaNgs0tFmAWYelg2dHglXmpCB9rN71y9Cqk7Wb3rk5KaPo+O1tWyxaGkYG2LB0Mtb7vh0L3qBhwYQW2taww4ejDbot4JUmsk7Sb3r1htZJt+0m965OSmg7REJw3hjOD7l42nB/y7Nn6KRJCHAtcA4HYQRcEbiD0pU5yTtJveuWDWSdpN71yclNFujowC0RsAIAIwNsWjoaRbaBuRJo2JwLXRscHWxAsaQ4jYC4W22SqGkJO0l989ezXyWvrJvevTkpqwUrY2hjGtY0dAaA0D8gF6ip2sFmtDQSTZoAFz0nZ1pSmvk7Sb3rltzknaTe9cnJTOGiYgSWxsY4knE1jQ/ERbGHAXxbelVeiuR7YZhO6SSZzGvazG2NuEP8AvE4GjG42ticuFzknaTe9cjOSdpN71yclNGm0fHHcxxsjxG7sDA253mw2rfhSnzknaTe9cjOSdpN71yclNd2wXOweKV2m6lstVNKw3a5zQDvwtDbjw2KNJO5ws58jhudI4j9QvCuYm6EIQtIEIWmqmwt2dJIA/MoPcq8X/u1ahTRn75c89ZxEfsB0LOUg3HjcpVbOtb7KJlINx43IysO53G5KJdlhw2KLlYdzuNyMrDudxuSjeD4H9l6D/AqNlYdzuNyMrDudxuSiTrPArDAdpso+Vh3O43IysO53G5KJdlgtUXKw7ncbkZWHc7jclGwxncs4T0WK1ZWHc7jcjKw7ncbko2CM7lvsomVh3O43IysO53G5KJdkWUTKw7ncbkZWHc7jclEuyLKJlYdzuNyMrDudxuSiVZCimmj/AMpcw7w4n9wV7pJi4EO6Wmx8fFKN6EIVRi6iaSPqX3EKXdRdJC8Z/vUiqrN+KM34qJq0atREzN+Kxm/FRNWjVoJmc8UZvxUPVo1aCXm/FGc8VE1aNWgYmlJKGikjopKUz3gifJM17hOZJY8YMQvhwi42EbbFRYeRRfRPrWzH1IZKgtdC5rNWwm7BIT6z7C+wEeKrqb/EGqjYwBsLpY4zFHUOjvURxWIwtfe2wEgEi4uvLuXtQYdSWQG9M6kdIYzrXU5BGHFj2EX6QB43UVbVnIkMZIG1IfNFTw1Rj1ZA1UmHZjvbF625eKrkY1szaNlXG+r1kMb4ixzQHSAXLH7ceG+3oVJLyyqHPlkIjvNTspXWadkLA0NLfW2O9Ubf4Umr/wAQKqQteGwxyh8Mj5mRASyviFmGRxJBtuAF0/R1FHyBbDWUokfmIZZZYXtex0LsbInuBDb3LDa4cNyXstVZxF+guH8q3dy4mE8VQyGmhdE+SQCOIta+R7S1z3+tc7CdgIAXNvbck7yT+6YJWb8VnN+Kh6tGrVRMznijOeKh6tGrQTM54oznioerRq0EzOeKsNFvuHHfZUerV3oltmft/wC0E+6Loui6oxdYIvsO0Iui6CC7Q4vsdYbiLrz6H9scJVhdF0gr/Q/tjhKPQ/tjhKsLoukFf6H9scJWfQ3tjhKn3RdIK/0P7Y4Sj0P7Y4SrC6LpBX+h/bHCUeh/bHCVYXRdIIPob2xwlY9D+2OEqfdF0gr/AEP7Y4Sj0P7Y4SrC6LpBA9De2OEo9De2OEqfdF0ggHQ3tjhKx6H9scJVhdF0gr/Q/tjhKyNDe2OEqfdF0ghN0ML7X3/IKaGBuwCwCzjWLpBm6LrF0XQeIT6o/If6L0hCoEIQgEIQgEIQgEIQgEIQgEIQgEIQgEIQgEIQgEIQgEIQgFVa534j+5WEKaY//9k="&gt;Users can easily add links to web pages to their iOS device’s home screen.&amp;nbsp; As a web developer, you’d like to be able to control the appearance of the icon that is used to represent your web site or application on the user’s device.&amp;nbsp; You can do this with a few more meta tags.&amp;nbsp; Incidentally, Apple calls these “Web Clips” though I can’t fathom why.&amp;nbsp; So, if you’re searching for more information on customizing how your web app’s icon appears on a user’s home screen, search for web clips.&lt;/p&gt;
&lt;p&gt;At its simplest, all you need to do is specify an icon.&amp;nbsp; This can be done using this meta tag:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;link&lt;/span&gt; &lt;span style="color: #ff0000"&gt;rel&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="apple-touch-icon"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;href&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="/custom_icon.png"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you don’t want the icon to be messed with at all by iOS, then you need to add –precomposed to it:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;link&lt;/span&gt; &lt;span style="color: #ff0000"&gt;rel&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="apple-touch-icon-precomposed"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;href&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="/custom_icon.png"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;By default, icons should be 57x57 pixels in size.&amp;nbsp; However, some devices use different resolutions for their icons.&amp;nbsp; You can (and should) create icons for each of the supported sizes and specify them using the sizes attribute, like so:&lt;/div&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;link&lt;/span&gt; &lt;span style="color: #ff0000"&gt;rel&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="apple-touch-icon"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;sizes&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="72x72"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;href&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="touch-icon-ipad.png"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;link&lt;/span&gt; &lt;span style="color: #ff0000"&gt;rel&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="apple-touch-icon"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;sizes&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="114x114"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;href&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="touch-icon-iphone4.png"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can also simply add these icons to your web site’s root URL, and if they use a well-known name they will be discovered and used.&amp;nbsp; The most basic filename is simply &lt;strong&gt;apple-touch-icon.png&lt;/strong&gt;, but you can include size information and whether it is precomposed as well (e.g. &lt;strong&gt;apple-touch-icon-57x57-precomposed.png&lt;/strong&gt;).&amp;nbsp; Naturally, you’ll be (slightly) better off from a performance perspective if you tell iOS which icon to use via a &amp;lt;link&amp;gt; than by having it try multiple different convention-based image URLs.&lt;/p&gt;
&lt;h2&gt;Adding a Splash Screen&lt;/h2&gt;
&lt;p&gt;Many native apps on mobile devices like iOS display a splash screen as the application is launching.&amp;nbsp; Web pages and applications, typically, do no such thing.&amp;nbsp; Thus, one more way you can make your web apps behave more like native apps on iOS is to add a splash screen to them.&amp;nbsp; apple calls these Startup Images, and the process is largely the same as for customizing icons – you simply need to add the appropriate tags via &amp;lt;link&amp;gt; elements.&amp;nbsp; As with icons, there are options available to specify different splash screen images for different device sizes.&amp;nbsp; The most basic option is to simply set a single image:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;link&lt;/span&gt; &lt;span style="color: #ff0000"&gt;rel&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="apple-touch-startup-image"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;href&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="/startup.png"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For iPhone and iPod touch, the image needs to be 320x460 pixels.&amp;nbsp; However, if you want to use a higher-resolution image for iPads(1 and 2 in this case), etc. you can achieve this like so:&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;link&lt;/span&gt; &lt;span style="color: #ff0000"&gt;rel&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="apple-touch-startup-image"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;href&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="/startup-748x1024.jpg"&lt;/span&gt; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;  &lt;span style="color: #ff0000"&gt;media&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation:landscape)"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;link&lt;/span&gt; &lt;span style="color: #ff0000"&gt;rel&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="apple-touch-startup-image"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;href&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="/startup-768x1004.jpg"&lt;/span&gt; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;  &lt;span style="color: #ff0000"&gt;media&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation:portrait)"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;Especially as &lt;a href="http://ardalis.com/getting-started-with-single-page-applications-in-asp.net"&gt;Single Page Applications take off in popularity&lt;/a&gt;, the ability to run such applications on iOS devices as if they were actually native apps will be an important feature.&amp;nbsp; Here I’ve shown a few settings that can easily be applied to any such application, or to any web page, to make the user experience of working with the web page nearly indistinguishable from using a native iOS application.&amp;nbsp; You can learn more about &lt;a href="http://developer.apple.com/library/ios/#DOCUMENTATION/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html"&gt;customizing web content for iOS in the iOS Developer Library&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/zYiw3USbpJ08GT-EQhgBAsJLFww/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zYiw3USbpJ08GT-EQhgBAsJLFww/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/zYiw3USbpJ08GT-EQhgBAsJLFww/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zYiw3USbpJ08GT-EQhgBAsJLFww/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=aCO9sUa_6nk:Ht5eYePGHx8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=aCO9sUa_6nk:Ht5eYePGHx8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=aCO9sUa_6nk:Ht5eYePGHx8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=aCO9sUa_6nk:Ht5eYePGHx8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=aCO9sUa_6nk:Ht5eYePGHx8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=aCO9sUa_6nk:Ht5eYePGHx8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StevenSmith/~4/aCO9sUa_6nk" height="1" width="1"/&gt;</description><pubDate>Wed, 28 Mar 2012 19:51:23 GMT</pubDate><guid isPermaLink="true">http://ardalis.com:80/configuring-web-apps-to-behave-like-native-apps-on-ios</guid></item><item><title>How Do I Disable Zoom in an iPad iPhone Mobile Web App?</title><link>http://ardalis.com:80/how-do-i-disable-zoom-in-an-ipad-iphone-mobile-web-app</link><description>&lt;p&gt;If you’re building web-based applications for mobile devices like the iPad/iPhone and you want to mimic native applications’ look and feel and experience, one thing you may want to do is disable the pinch zoom gesture.&amp;nbsp; Most native applications don’t offer support for this, but of course most mobile browsers currently do, so a sure way for users to tell that they’re actually viewing a web page is to let them resize the page easily using these gestures.&amp;nbsp; To disable the pinch zoom, you can simply specify an identical starting and maximum scale.&amp;nbsp; This is achieved by adding a viewport meta tag to the page or site in question, like so:&lt;/p&gt; &lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;meta&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="viewport"&lt;/span&gt; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;   &lt;span style="color: #ff0000"&gt;content&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="width=device-width, initial-scale=1.0, maximum-scale=1.0"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;By adding this viewport tag, you’re forcing the browser to maintain a 100% scale for the page.&amp;nbsp; You can also use the ViewPort meta tag to help optimize how your page or site renders in mobile devices, without limiting users’ ability to zoom in and out.&amp;nbsp; Simply remove the maximum-scale setting in the above meta tag.&lt;/p&gt;
&lt;p&gt;With this setting in place, you’re one step closer to creating a web application that behaves like a native iOS app.&amp;nbsp; You can learn more about ViewPort settings specific to the Safari browser on iOS from the &lt;a href="http://developer.apple.com/library/ios/#DOCUMENTATION/AppleApplications/Reference/SafariWebContent/UsingtheViewport/UsingtheViewport.html#//apple_ref/doc/uid/TP40006509-SW19"&gt;iOS Developer Library article on Configuring the Viewport&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/7XrpdMoKxFEbUOB0bKfV9hrGrF8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7XrpdMoKxFEbUOB0bKfV9hrGrF8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/7XrpdMoKxFEbUOB0bKfV9hrGrF8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7XrpdMoKxFEbUOB0bKfV9hrGrF8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=ewKany87FCA:LrTiqcj9DDs:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=ewKany87FCA:LrTiqcj9DDs:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=ewKany87FCA:LrTiqcj9DDs:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=ewKany87FCA:LrTiqcj9DDs:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=ewKany87FCA:LrTiqcj9DDs:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=ewKany87FCA:LrTiqcj9DDs:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StevenSmith/~4/ewKany87FCA" height="1" width="1"/&gt;</description><pubDate>Wed, 28 Mar 2012 19:16:25 GMT</pubDate><guid isPermaLink="true">http://ardalis.com:80/how-do-i-disable-zoom-in-an-ipad-iphone-mobile-web-app</guid></item><item><title>Asus Zen Ultrabook Revisited</title><link>http://ardalis.com:80/asus-zen-ultrabook-revisited</link><description>&lt;p&gt;A couple of months ago I got an Asus Zen ultrabook, which I &lt;a href="http://ardalis.com/Asus-Zen-Ultrabook-First-Impressions"&gt;posted about when I first got it&lt;/a&gt;, and &lt;a href="http://ardalis.com/asus-zen-ultrabook-one-month-later"&gt;a month or so later&lt;/a&gt;.&amp;nbsp; Now that I’ve had it a while, I thought I’d post one more time with how it’s continued to work for me.&amp;nbsp; I’m still very happy with its look, feel, and speed.&amp;nbsp; It’s very responsive both while up and running and when waking up or shutting down.&amp;nbsp; One thing I wish it came with is an HDMI adapter, but I picked up an &lt;a href="http://www.amazon.com/gp/product/B004I4YPB4/ref=as_li_ss_tl?ie=UTF8&amp;amp;tag=aspalliancecom&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=B004I4YPB4"&gt;HDMI adapter for $2 from Amazon&lt;/a&gt; and it works fine.&amp;nbsp; The machine does come with a VGA adapter, which is more likely to be what you’ll need when projecting, but our conference room has both and the HDMI is a bit sharper so I’m happy to be able to use it now.&lt;/p&gt; &lt;p&gt;In the last month, this machine has traveled with me to Vancouver, Seattle, and Orlando as well as various clients and businesses in Ohio.&amp;nbsp; It’s super-light, the battery lasts and lasts, and it’s small enough to use on an airplane without being either a contortionist or sitting in first class/exit row.&amp;nbsp; I also installed Windows 8 consumer preview on it a few weeks ago when that came out, and it works great as well.&amp;nbsp; I followed &lt;a href="http://www.hanselman.com/blog/GuideToInstallingAndBootingWindows8DeveloperPreviewOffAVHDVirtualHardDisk.aspx"&gt;Scott Hanselman’s boot to VHD instructions&lt;/a&gt;.&amp;nbsp; In Win8, the touchpad is a bit more “touchy” (if your hand rests on it as you type it can move the mouse pointer or click it), but other than that (and the fact that it isn’t a touch screen device) it seems to work fine.&amp;nbsp; The performance and stability of Win 8 seem to be very good, too, so much so that I know several people who run it as their primary work OS.&lt;/p&gt; &lt;p&gt;One of the nice things about having such a portable, powerful laptop is that I find myself using it more often.&amp;nbsp; Of course, it’s now competing with an iPad, at least at home, so for many tasks that are mainly consumption-oriented, the iPad wins.&amp;nbsp; But for actually creating anything, whether it’s a blog post or working on code in Visual Studio, the Zen works great.&amp;nbsp; And of course it’s also a great movie and consumption machine in its own right (and when someone else in my household has dibs on the iPad).&amp;nbsp; And at work, where I don’t currently bring the iPad, its small size makes it ideal to take to meetings or even just to have on the edge of one’s desk as a secondary machine to use for email/twitter/browsing while doing dev work on a full-sized pair programming workstation.&lt;/p&gt; &lt;p&gt;&lt;a href="http://news.cnet.com/8301-17938_105-57404752-1/how-the-pc-industry-killed-the-ultrabook/"&gt;Some pundits are claiming that the ultrabook as a brand is already dead&lt;/a&gt;, because the name and brand are being diluted by forthcoming larger laptops that are thicker and feature spinning-rust hard drives rather than SSDs.&amp;nbsp; I agree this kind of brand extension is a bad thing for the ultrabook brand name, but I’m definitely a fan of ultrabooks in the original sense, and I continue to be very pleased with mine.&amp;nbsp; The one feature of this particular machine that continues to be a minor annoyance to me is the keyboard, which tends to result in missed keys more frequently than other laptops I’ve used and far more than full-sized keyboards.&amp;nbsp; But I’m a fairly proficient touch-typist and it may just be that my style doesn’t jive well with this particular layout or type of keyboard.&amp;nbsp; If you’re concerned it may be an issue for you, see if you can try one out before you buy one, but for me it remains a fairly minor, but notable, concern.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;font size="2"&gt;Obligatory Legalese&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;&lt;font size="2"&gt;Disclosure of Material Connection: I received one or more of the products or services mentioned above for free in the hope that I would mention it on my blog. Regardless, I only recommend products or services I use personally and believe my readers will enjoy. I am disclosing this in accordance with the &lt;/font&gt;&lt;a href="http://www.access.gpo.gov/nara/cfr/waisidx_03/16cfr255_03.html"&gt;&lt;font size="2"&gt;Federal Trade Commission’s 16 CFR, Part 255: “Guides Concerning the Use of Endorsements and Testimonials in Advertising.”&lt;/font&gt;&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/9KtM00bn2SCpYCK_m12JgRXbzoM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/9KtM00bn2SCpYCK_m12JgRXbzoM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/9KtM00bn2SCpYCK_m12JgRXbzoM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/9KtM00bn2SCpYCK_m12JgRXbzoM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=xM8nUCkNVPw:AhKxqwJVQGY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=xM8nUCkNVPw:AhKxqwJVQGY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=xM8nUCkNVPw:AhKxqwJVQGY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=xM8nUCkNVPw:AhKxqwJVQGY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=xM8nUCkNVPw:AhKxqwJVQGY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=xM8nUCkNVPw:AhKxqwJVQGY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StevenSmith/~4/xM8nUCkNVPw" height="1" width="1"/&gt;</description><pubDate>Tue, 27 Mar 2012 18:51:23 GMT</pubDate><guid isPermaLink="true">http://ardalis.com:80/asus-zen-ultrabook-revisited</guid></item><item><title>How to use System.Web in a Console Application</title><link>http://ardalis.com:80/how-to-use-system.web-in-a-console-application</link><description>&lt;p&gt;I’ve been bitten by this and have seen others run into it enough times that I thought I’d blog about it.&amp;nbsp; Let’s say you’re creating a new Console, WPF, or Windows Forms application in .NET 4.&amp;nbsp; You’re using Visual Studio 2010, and everything is going great until you get to the part where you wanted to make an HTTP request.&amp;nbsp; You know you can do this, you’ve done it before, heck, you might even be copying code straight out of MSDN that does what you need.&amp;nbsp; But it doesn’t compile.&amp;nbsp;&amp;nbsp; If you try and add a reference to System.Web, you’ll find it’s not there:&lt;/p&gt; &lt;p&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="SNAGHTML53c449" border="0" alt="SNAGHTML53c449" src="http://ardalis.com/Media/Default/Windows-Live-Writer/How-to-use-.Web-in-a-Console-Application_E53A/SNAGHTML53c449_1.png" width="571" height="484"&gt;&lt;/p&gt; &lt;p&gt;If you look closely, though, you’ll see at the top of the dialog it says “Filtered to: .NET Framework 4 Client Profile”.&amp;nbsp; That’s the issue.&amp;nbsp; Now, if you really are doing HTTP requests in a console application in .NET 4, then I recommend you use the System.Net.HttpWebRequest type that *is* available in the Client profile.&amp;nbsp; But for argument’s sake, if you really do need something in one of the filtered out assemblies, like System.Web, then you simply need to change your project type to use the full .NET 4 Framework.&amp;nbsp; You can do that by going into project properties and changing the Target framework from .NET Framework 4 Client Profile to simply .NET Framework 4.&lt;/p&gt; &lt;p&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="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/How-to-use-.Web-in-a-Console-Application_E53A/image_3.png" width="644" height="461"&gt;&lt;/p&gt; &lt;p&gt;Having done that, you’ll then be able to reference System.Web again in your project.&amp;nbsp; Hope that helps!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://ardalis.com/Media/Default/Windows-Live-Writer/How-to-use-.Web-in-a-Console-Application_E53A/SNAGHTML59c784.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="SNAGHTML59c784" border="0" alt="SNAGHTML59c784" src="http://ardalis.com/Media/Default/Windows-Live-Writer/How-to-use-.Web-in-a-Console-Application_E53A/SNAGHTML59c784_thumb.png" width="644" height="420"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/mzZH7D5I0FJKx-GCf1KSF74XOwQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mzZH7D5I0FJKx-GCf1KSF74XOwQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/mzZH7D5I0FJKx-GCf1KSF74XOwQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mzZH7D5I0FJKx-GCf1KSF74XOwQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=vCkVqGSky3s:ttkfyPUzyfs:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=vCkVqGSky3s:ttkfyPUzyfs:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=vCkVqGSky3s:ttkfyPUzyfs:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=vCkVqGSky3s:ttkfyPUzyfs:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=vCkVqGSky3s:ttkfyPUzyfs:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=vCkVqGSky3s:ttkfyPUzyfs:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StevenSmith/~4/vCkVqGSky3s" height="1" width="1"/&gt;</description><pubDate>Fri, 23 Mar 2012 15:38:42 GMT</pubDate><guid isPermaLink="true">http://ardalis.com:80/how-to-use-system.web-in-a-console-application</guid></item><item><title>Kanban Book Review</title><link>http://ardalis.com:80/kanban-book-review</link><description>&lt;p&gt;&lt;img style="margin: 0px 0px 0px 10px; display: inline; float: right" align="right" src="http://www.rallydev.com/agileblog/wp-content/uploads/2011/03/Kanban-book-image1.jpg"&gt;While researching material for my &lt;a href="http://www.pluralsight-training.net/microsoft/courses/TableOfContents?courseName=kanban-fundamentals&amp;amp;highlight=steve-smith_kanban-fund-m2-personal*10,11,0,2,5,7,8,12,1,3,4,6,9!steve-smith_kanban-fund-m3-team*1,4,6!steve-smith_kanban-fund-m1-basic*1,0,2,8,9,4,3,5,6,7#kanban-fund-m2-personal"&gt;Kanban Fundamentals&lt;/a&gt; video &lt;a href="http://ardalis.com/training-classes"&gt;training course on Pluralsight&lt;/a&gt;, I read &lt;a href="http://amzn.to/wpRfnF"&gt;Kanban: Successful Evolutionary Change for Your Technology Business&lt;/a&gt;, by David J. Anderson.&amp;nbsp; I’ve previously reviewed a couple of other related books, including &lt;a href="http://ardalis.com/personal-kanban-book-review"&gt;Personal Kanban&lt;/a&gt; and &lt;a href="http://ardalis.com/reviewing-scrumban-the-book"&gt;Scrumban&lt;/a&gt;, if you’re interested in learning more about this topic.&amp;nbsp; I would recommend Personal Kanban as the most introductory, followed by Kanban, which goes into greater depth and does a good job of building on Personal Kanban (even though it was written first).&amp;nbsp; Scrumban is more advanced and is a collection of essays/blog posts that are more loosely organized than the other two books.&lt;/p&gt; &lt;p&gt;Getting back to Kanban, the book, I really enjoyed this book for several reasons.&amp;nbsp; I’m a fan of David Anderson’s and have seen some of his presentations on lean and kanban, so I was looking forward to the book.&amp;nbsp; You can &lt;a href="http://www.agilemanagement.net/"&gt;learn more about David here&lt;/a&gt;.&amp;nbsp; Before getting into the book, take a closer look at the image on the cover at right.&amp;nbsp; Notice that the three workers’ statuses are obvious based on the board behind them.&amp;nbsp; One of the beautiful effects of kanban implementation is the easy, visual communication of status to everyone without the need to ask for status reports.&lt;/p&gt; &lt;p&gt;The book is organized into 20 chapters spanning just over 250 pages.&amp;nbsp; Different people will find different parts of the book valuable.&amp;nbsp; Chapters 3-5, representing “Part 2 – Benefits of Kanban,” were my favorite, and in particular the case study presented in chapter 4, “From Worst to Best in 5 Quarters,” is particularly compelling.&amp;nbsp; In it, Anderson describes a dysfunctional team that sees dramatic improvement in lead time and customer satisfaction.&amp;nbsp; To wit:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;the team had reduced the lead time to an average of 14 days against an 11-day engineering time.&amp;nbsp; The due-date performance on the 25-day delivery time target was 98 percent.&amp;nbsp; The throughput of requests had risen more than threefold, while lead times had dropped by more than 90 percent, and reliability improved almost as much.&amp;nbsp; No changes were made to the software development or testing process.&amp;nbsp; The people working [on the team] were unaware of any significant change.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Think about that.&amp;nbsp; This team’s performance (measured in throughput, lead times, quality) was dramatically improved, and the individuals on the team were unaware of any significant change.&amp;nbsp; Chapter 4 alone is enough to merit buying and reading this book if you’re involved in shipping software.&amp;nbsp; I spend some time on this same case study in my Kanban Fundamentals training class, because I think it’s a great testimony to the power of these ideas in practice.&lt;/p&gt; &lt;p&gt;Part Three, chapters 6-15, discusses Implementing Kanban.&amp;nbsp; There’s a ton of great material here for anyone interested in using kanban to improve their organization or team, from creating card walls and describing what to put on each card to negotating and establishing service level agreements with clients.&amp;nbsp; One of the recommended steps to successfully implement kanban is to change the way work is delivered to and from the team implementing kanban, and establishing service level agreements with downstream collaborators is one way to accomplish this.&amp;nbsp; In this section David also discusses some of the theory of queues and the need to limit work in progress, as well as how to scale kanban to larger projects.&lt;/p&gt; &lt;p&gt;Part Four, Making Improvements, looks at how to eliminate waste, reduce variability, keep things flowing through bottlenecks, and introduces economics to the discussion.&amp;nbsp; In the simplest case, lean proponents tend to adhere to certain basic principles, like “reduce variability to increase flow” and “the ideal is one piece flow”, that is, a batch size of one with zero queues.&amp;nbsp; Donald Reinertson, whom Anderson references in this section, does a great job of applying real-world economics and payoff functions to these ideals.&amp;nbsp; He explains how the world of software development has very different economic payoff functions for things like variability and batch size than does a physical factory (where lean and kanban originated) in &lt;a href="http://amzn.to/yzqWOR"&gt;The Principles of Product Development Flow&lt;/a&gt; (review coming).&amp;nbsp; One term Anderson introduces in this section that I found worth noting is&lt;em&gt; failure load&lt;/em&gt;.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;Failure load is demand generated by the customer that might have been avoided through higher quality delivered earlier… Failure load still adds value.&amp;nbsp; But what is important is that it adds value that should have been there already.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;It seems to me that failure load is conceptually related to &lt;a href="http://deviq.com/technical-debt"&gt;technical debt&lt;/a&gt;.&amp;nbsp; When you deliver software that has a large amount of technical debt, there may be resulting defects or extra resources required to modify the system that shouldn’t have been there.&amp;nbsp; Fixing them, paying down the debt, adds value, but it’s value that should have been there already if the &lt;em&gt;quality&lt;/em&gt; of the software had been better.&lt;/p&gt; &lt;p&gt;Each chapter in the book ends with a bulleted list of takeaways that highlight the important ideas covered.&amp;nbsp; Like this:&lt;/p&gt; &lt;h2&gt;Takeaways&lt;/h2&gt; &lt;ul&gt; &lt;li&gt;Kanban is a great book for learning about and implementing kanban for teams&lt;/li&gt; &lt;li&gt;The case study in chapter 4 is, I think, worth the price of the book all by itself&lt;/li&gt; &lt;li&gt;Beyond the mechanics of setting up a visual card wall or board, the book describes how to implement kanban within an organization&lt;/li&gt; &lt;li&gt;Think about how much failure load your team has, and how you could reduce it&lt;/li&gt; &lt;li&gt;Learn more about &lt;a href="http://www.pluralsight-training.net/microsoft/Courses/Find?highlight=true&amp;amp;searchTerm=kanban"&gt;kanban from Pluralsight&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/u2JK3SiHFQWJ0xVz91uT1OfhI7g/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/u2JK3SiHFQWJ0xVz91uT1OfhI7g/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/u2JK3SiHFQWJ0xVz91uT1OfhI7g/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/u2JK3SiHFQWJ0xVz91uT1OfhI7g/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=0VQdKUGnIeA:_ZZA7bZl41c:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=0VQdKUGnIeA:_ZZA7bZl41c:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=0VQdKUGnIeA:_ZZA7bZl41c:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=0VQdKUGnIeA:_ZZA7bZl41c:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=0VQdKUGnIeA:_ZZA7bZl41c:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=0VQdKUGnIeA:_ZZA7bZl41c:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StevenSmith/~4/0VQdKUGnIeA" height="1" width="1"/&gt;</description><pubDate>Wed, 21 Mar 2012 17:05:31 GMT</pubDate><guid isPermaLink="true">http://ardalis.com:80/kanban-book-review</guid></item><item><title>Make IIS Express the Default for VS2010 Web Projects</title><link>http://ardalis.com:80/make-iis-express-the-default-for-vs2010-web-projects</link><description>&lt;p&gt;Here’s a quick tip that will help you leave Cassini in the past where it belongs.&amp;nbsp; If you’re using VS2010 SP1, you can configure your IDE so that it will automatically choose IIS Express out of the box for new web sites and projects.&amp;nbsp; There are a lot of good reasons why you should be using IIS Express instead of Cassini / WebDevServer – you can &lt;a href="http://learn.iis.net/page.aspx/868/iis-express-overview/"&gt;learn more about IIS Express here&lt;/a&gt;.&amp;nbsp; Unfortunately, Cassini remains the default web server for new web projects in VS2010 (unless you change it).&lt;/p&gt; &lt;p&gt;To configure an individual web project to use IIS Express after you’ve created it, simply right click on the project in Solution Explorer and choose the Use IIS Express option.&amp;nbsp; You can also configure it in the Web tab of the project’s properties:&lt;/p&gt; &lt;p&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="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Make-IIS-Express-the-Default-for-VS2010-_CBB4/image_3.png" width="552" height="484"&gt;&lt;/p&gt; &lt;p&gt;That’s great, but it’s annoying to have to do for every new project you create.&amp;nbsp; The good news that it’s pretty easy to make IIS Express the default.&amp;nbsp; Thanks to Damian Edwards for pointing this setting out to me.&amp;nbsp; You can go to Tools-Options-Projects and Solutions-Web Projects and check a box there to make IIS Express the default.&amp;nbsp; Note that this setting will work for web sites as well as web projects, so don’t let the menu’s name throw you off.&lt;/p&gt; &lt;p&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="SNAGHTMLb168417" border="0" alt="SNAGHTMLb168417" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Make-IIS-Express-the-Default-for-VS2010-_CBB4/SNAGHTMLb168417_1.png" width="644" height="376"&gt;&lt;/p&gt; &lt;p&gt;That’s it.&amp;nbsp; Check the box, and enjoy a Cassini-free development environment from this point forward.&amp;nbsp; Except on your other machines, where you’ll have to set this setting again.&amp;nbsp; Oh, and next time you reinstall Visual Studio – you’ll have to set it again then, too.&amp;nbsp; Y’know, wouldn’t it be cool if Visual Studio would remember your settings in the cloud for you?&amp;nbsp; I’ve only been asking for that since like 2003.&amp;nbsp; Maybe now that remember users’ settings is getting baked into Windows 8 it’ll be closer to a reality for Visual Studio.&amp;nbsp; I can dream…&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Y9l9KP3FK8Mqxm0CJ59Bxvxa81A/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Y9l9KP3FK8Mqxm0CJ59Bxvxa81A/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Y9l9KP3FK8Mqxm0CJ59Bxvxa81A/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Y9l9KP3FK8Mqxm0CJ59Bxvxa81A/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=YjPX5JRRFes:Nq2KVO2iopU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=YjPX5JRRFes:Nq2KVO2iopU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=YjPX5JRRFes:Nq2KVO2iopU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=YjPX5JRRFes:Nq2KVO2iopU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=YjPX5JRRFes:Nq2KVO2iopU:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=YjPX5JRRFes:Nq2KVO2iopU:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StevenSmith/~4/YjPX5JRRFes" height="1" width="1"/&gt;</description><pubDate>Mon, 19 Mar 2012 18:37:18 GMT</pubDate><guid isPermaLink="true">http://ardalis.com:80/make-iis-express-the-default-for-vs2010-web-projects</guid></item><item><title>Getting Started with Single Page Applications in ASP.NET</title><link>http://ardalis.com:80/getting-started-with-single-page-applications-in-asp.net</link><description>&lt;p&gt;One of the new features in ASP.NET MVC 4 (Beta) is a new project template for Single Page Applications (SPA).&amp;nbsp; You can download the latest version of MVC4 from &lt;a href="http://asp.net/mvc/mvc4"&gt;http://asp.net/mvc/mvc4&lt;/a&gt;.&amp;nbsp; Once you have that installed, get started by creating a new ASP.NET MVC 4 project:&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="SNAGHTMLb0f130d" border="0" alt="SNAGHTMLb0f130d" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/SNAGHTMLb0f130d_1.png" width="644" height="446"&gt;&lt;/p&gt; &lt;p&gt;You’ll immediately be asked another question about exactly what kind of project you’re looking to create.&amp;nbsp; This is only asked on project creation, but it’s possible in the future you’ll be able to mix and match these kinds of templates and the resources they provide in a more ad hoc manner, after projects are created, in the future.&amp;nbsp; For now, though, to check out Single Page Applications, choose that template.&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="SNAGHTMLb10a75f" border="0" alt="SNAGHTMLb10a75f" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/SNAGHTMLb10a75f_1.png" width="534" height="484"&gt;&lt;/p&gt; &lt;p&gt;Ok, so now we have our new project and in a few seconds our project is fully set up.&amp;nbsp; We see a solution explorer window that looks something like this:&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/image_3.png" width="364" height="339"&gt;&lt;/p&gt; &lt;p&gt;So of course the next step is to hit F5 (or ctrl-F5) so we can check this thing out, right?&amp;nbsp; Doing so yields a pretty standard home page:&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="SNAGHTMLb13e25c" border="0" alt="SNAGHTMLb13e25c" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/SNAGHTMLb13e25c_1.png" width="467" height="484"&gt;&lt;/p&gt; &lt;p&gt;Unfortunately, there’s no SPA goodness going on here.&amp;nbsp; &lt;em&gt;Yet&lt;/em&gt;.&amp;nbsp; Unlike most of the other project templates, this one&lt;strong&gt; actually expects you to do some work&lt;/strong&gt; to get things going.&amp;nbsp; The nerve, right?&amp;nbsp; In fact, if you’d actually read the first page that came up in the solution before quickly hitting F5, you might have noticed these comments:&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/image_6.png" width="644" height="154"&gt;&lt;/p&gt; &lt;p&gt;But admit it, you didn’t read that, you just hit F5, right?&lt;/p&gt; &lt;p&gt;So, let’s go ahead and actually RTFM a bit and see how this SPA stuff works.&amp;nbsp; We’re basically going to follow the instructions shown above.&amp;nbsp; If you *didn’t* hit F5 yet, make sure you do so or Build the project before you try to do the Add –&amp;gt; Controller step.&amp;nbsp; Otherwise, you won’t see the TodoItem as an option for the Model Class.&amp;nbsp; The dialog should look something like this:&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="SNAGHTMLb1c9fe1" border="0" alt="SNAGHTMLb1c9fe1" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/SNAGHTMLb1c9fe1_1.png" width="644" height="420"&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Now&lt;/strong&gt; you can hit F5.&amp;nbsp; And then manually change the URL to /Tasks to see the page in action.&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="SNAGHTMLb1ecd28" border="0" alt="SNAGHTMLb1ecd28" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/SNAGHTMLb1ecd28_1.png" width="644" height="422"&gt;&lt;/p&gt; &lt;p&gt;Pretty exciting, eh?&amp;nbsp; At this point, you can perform standard CRUD (Create-Read-Update-Delete) operations on your TodoItems without ever going to a new page.&amp;nbsp; Watch the address bar and open up F12 developer tools in IE (or Chrome, or Firebug in Firefox) and watch the network activity as you manipulate the data in the list.&amp;nbsp; You should see something like this:&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/image_9.png" width="564" height="484"&gt;&lt;/p&gt; &lt;p&gt;You’ll also notice that you get full back/forward button support in your browser, which is pretty cool considering this is a single web page.&amp;nbsp; So how does this work?&amp;nbsp; Let’s look back at Visual Studio and see how this is all put together, starting with our controller.&amp;nbsp; If this were a traditional ASP.NET MVC application, we would expect our TasksController to include a bunch of methods for things like Index, Update, Delete, etc.&amp;nbsp; Here’s the one we created for the Single Page Application:&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/image_12.png" width="408" height="260"&gt;&lt;/p&gt; &lt;p&gt;Now let’s look at the View.&amp;nbsp; It’s probably a massive mess of indecipherable JavaScript to make all of this stuff work.&amp;nbsp; Or is it?&amp;nbsp; Here’s the Tasks’ Index.cshtml file:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/image_14.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/image_thumb_4.png" width="644" height="367"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Ok, so, 27 lines of text with 4 lines of JavaScript – not bad.&amp;nbsp; I’ve circled the areas that make the magic happen.&amp;nbsp; The two divs on lines 6 and 10 have a data-bind attribute set which is linking their visibility to the state of the page.&amp;nbsp; That is, when the page’s state is not editingTodoItem, the grid is shown.&amp;nbsp; Otherwise, the editor is shown.&amp;nbsp; These bindings will be triggered instantly if the state of the page changes.&lt;/p&gt; &lt;p&gt;Likewise, the success and error divs on lines 14-15 are also making use of the data-bind attribute, in this case to bind the text of the div and specify the duration (in milliseconds) that the div should flash and remain visible.&lt;/p&gt; &lt;p&gt;Finally, there are two script blocks.&amp;nbsp; The first one pulls in the viewmodel for the TodoItems, which was created for us when we created the controller using the Visual Studio tooling.&amp;nbsp; This script file contains about 100 lines of JavaScript code that provides the client-side viewmodel the user will interact with.&amp;nbsp; The constructor for this ViewModel class takes in some parameters, one of which is the URL to the web service/API that will be used for persisting changes to and from the data source.&amp;nbsp; You can see in the code above that we’re passing in a URL of ~/api/GettingStartedWithSPA which is the name of my project.&amp;nbsp; The /api convention is used by Web API by default.&lt;/p&gt; &lt;p&gt;Looking back at our list of Controllers, we now see that one that was added is named the same as our project, and another one for the model class we’re working with (TodoItem).&amp;nbsp; These provide the Web API for performing CRUD operations on our model class, by default using Entity Framework.&amp;nbsp; In addition, the /api/ path is specified in an AreaRegistration class in the first of these controllers:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/image_16.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/image_thumb_5.png" width="644" height="275"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The heavy lifting is all done by the base class, but by default it won’t actually expose any services until you create the methods yourself.&amp;nbsp; That’s why the other controller file is there – it exposes the four methods we need to work with the data.&amp;nbsp; Note that it’s part of the same class as in the other file, not a separate class.&lt;/p&gt; &lt;p&gt;&lt;a href="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/image_18.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/image_thumb_6.png" width="644" height="181"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;That’s pretty much all of the server-side code required for the simple TodoList management application that we have at this point.&amp;nbsp; Let’s look back at the client-side script from the Index.cshtml view.&amp;nbsp; The last bit of script was:&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/image_21.png" width="644" height="135"&gt;&lt;/p&gt; &lt;p&gt;Line 19 simply uses jQuery to run this script when the page has completed loading.&amp;nbsp; Line 20 uses a helper method to define the shape of the data.&amp;nbsp; At runtime, the code emitted by this helper looks like this:&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/image_24.png" width="644" height="55"&gt;&lt;/p&gt; &lt;p&gt;The reference to upshot is referring to a JavaScript library included in the project, upshot.js.&amp;nbsp; Upshot’s main task is to link your client-side code and the changes you make to the client-side model with the backend server-side persistence via web API calls.&lt;/p&gt; &lt;p&gt;Next we create the viewModel, and finally we apply the bindings on line 25 by calling another JavaScript library, &lt;a href="http://knockoutjs.com/"&gt;knockout.js&lt;/a&gt;.&amp;nbsp; Knockout provides the support for data binding, observable properties, and the structure for creating client-side ViewModels that we can interact with at a higher level of abstraction than DOM elements.&lt;/p&gt; &lt;h2&gt;Even Better Updated Templates&lt;/h2&gt; &lt;p&gt;Even better than the default item templates that come with the MVC 4 beta bits, there are &lt;a href="http://blog.stevensanderson.com/2012/03/06/single-page-application-packages-and-samples/"&gt;some updated examples that Steven Sanderson posted about last week that you can get via NuGet&lt;/a&gt;.&amp;nbsp; Start with a new MVC 4 project, and then install the package from the Package Manager Console by running this comment:&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;font face="Consolas"&gt;Install-Package SinglePageApplication.CSharp&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;assuming you’re using C# (.VisualBasic for VB).&amp;nbsp; You should see a bunch of stuff in the console window and perhaps a few security warnings, and maybe even an error referring to a T4 template (SpaIndex.tt).&amp;nbsp; Ignore all of these things and dismiss the various security windows.&lt;/p&gt; &lt;p&gt;When you install this package, it does the following:&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/image_29.png" width="644" height="312"&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: If you run this after already adding a controller using the original MVC4 Beta templates, your _SpaLayout.cshtml file will be messed up.&amp;nbsp; It should look like this (you’re best to start from a new project):&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/image_35.png" width="644" height="179"&gt;&lt;/p&gt; &lt;p&gt;You’ll note that both knockout and upshot were upgraded, along with EF and jQuery.&amp;nbsp; Looking at the new default view, we can see it’s a bit shorter and cleaner now:&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/image_38.png" width="644" height="242"&gt;&lt;/p&gt; &lt;p&gt;The latest version moves the &amp;lt;div&amp;gt; tags and their data-bind attributes into the partials, and uses a new helper method to configure upshot, leaving just one line of raw javascript in the file now.&amp;nbsp; Running the revised template results in this:&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="SNAGHTMLb5382a2" border="0" alt="SNAGHTMLb5382a2" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/SNAGHTMLb5382a2_1.png" width="445" height="484"&gt;&lt;/p&gt; &lt;p&gt;Notice how this version behaves differently.&amp;nbsp; As you add each item, nothing happens on the network.&amp;nbsp; Now click Save all, and you’ll see that all of the values are persisted at once, and the CSS styling of the items goes away (Green was indicating they weren’t yet saved).&amp;nbsp; You can also click Revert all to throw away any unsaved changes you’ve accumulated.&lt;/p&gt; &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Getting-Started-with-Single-Page-App.NET_142CE/image_41.png" width="644" height="383"&gt;&lt;/p&gt; &lt;p&gt;This is some pretty cool stuff, and the coolest part is how easy it is for you to set up and work with.&amp;nbsp; If you find this technique interesting, I strongly recommend you check out &lt;a href="http://channel9.msdn.com/Events/TechDays/Techdays-2012-the-Netherlands/2159"&gt;Steven Sanderson’s talk on Knockout and Upshot&lt;/a&gt; and also look at &lt;a href="http://www.pluralsight-training.net/microsoft/Courses/TableOfContents?courseName=knockout-mvvm"&gt;John Papa’s MVVM and Knockout course on Pluralsight&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;You can &lt;a href="https://bitbucket.org/ardalis/blogsamples/src/541a87671128/GettingStartedWithSPA"&gt;view and download the source code shown here (both projects) here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/2ApJD1170equSCZu0EAVDMLldUs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2ApJD1170equSCZu0EAVDMLldUs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/2ApJD1170equSCZu0EAVDMLldUs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2ApJD1170equSCZu0EAVDMLldUs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=3f47lgkNuAc:N1-ZNJ6sUZ0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=3f47lgkNuAc:N1-ZNJ6sUZ0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=3f47lgkNuAc:N1-ZNJ6sUZ0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=3f47lgkNuAc:N1-ZNJ6sUZ0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=3f47lgkNuAc:N1-ZNJ6sUZ0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=3f47lgkNuAc:N1-ZNJ6sUZ0:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StevenSmith/~4/3f47lgkNuAc" height="1" width="1"/&gt;</description><pubDate>Fri, 16 Mar 2012 13:22:02 GMT</pubDate><guid isPermaLink="true">http://ardalis.com:80/getting-started-with-single-page-applications-in-asp.net</guid></item><item><title>How to Give Feedback on Microsoft Developer Products</title><link>http://ardalis.com:80/how-to-give-feedback-on-microsoft-developer-products</link><description>&lt;p&gt;In the last few years, a number of Microsoft dev teams have started using online tools to manage how the community can offer feedback.&amp;nbsp; If you’re a Microsoft developer, and especially if you’re a web developer, you should know about these tools and offer your feedback through these channels if you’d like Microsoft to respond to your needs.&amp;nbsp; There are several ways you can offer this feedback, and different reasons why you might choose one channel or another.&lt;/p&gt; &lt;h2&gt;UserVoice&lt;/h2&gt; &lt;p&gt;By far the most effective way to get your ideas on the radar of the product teams is through the use of UserVoice forums for the appropriate product or feature.&amp;nbsp; If the group in question has a UserVoice forum set up, then it’s a solid bet they’re looking at it when they are locking in the feature set of a new version of their product.&amp;nbsp; Currently both the ASP.NET and Visual Studio teams have UserVoice forums set up, including separate categories for many of the sub-features of these two groups’ products.&amp;nbsp; Below are some of the areas in which you can leave feedback for the teams:&lt;img style="display: inline; float: right" alt="ASP.NET Future Feature Feedback" align="right" src="http://s3.amazonaws.com/uploads.uservoice.com/logo/design_setting/59732/original/aspnet_4162_0.PNG?1322778502"&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://aspnet.uservoice.com/forums/41199-general"&gt;ASP.NET General Ideas&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://aspnet.uservoice.com/forums/41201-asp-net-mvc"&gt;ASP.NET MVC&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://aspnet.uservoice.com/forums/41202-asp-net-webforms"&gt;ASP.NET Webforms&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://aspnet.uservoice.com/forums/147203-spa-single-page-application-framework-with-javas"&gt;ASP.NET Single Page Applications&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://aspnet.uservoice.com/forums/147206-wcf-web-services-"&gt;WCF and Web Services&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://aspnet.uservoice.com/forums/147201-web-api"&gt;Web API&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://aspnet.uservoice.com/forums/136460-www-asp-net-website-"&gt;The ASP.NET website&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;img style="margin: 15px 0px 0px; display: inline; float: right" alt="Microsoft" align="right" src="http://s3.amazonaws.com/uploads.uservoice.com/logo/design_setting/9445/original/VS_logo.jpg?1310759071"&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;ul&gt; &lt;li&gt;&lt;a href="http://visualstudio.uservoice.com/forums/121579-visual-studio"&gt;Visual Studio General Feedback&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/category/31481-net"&gt;.NET&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/category/35066-ide"&gt;IDE&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/category/30931-languages-c-"&gt;C#&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/category/30935-languages-f-"&gt;F#&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/category/30933-languages-visual-basic"&gt;VB&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/category/30925-team-foundation-server"&gt;Team Foundation Server&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://visualstudio.uservoice.com/forums/127959-visual-studio-lightswitch"&gt;Visual Studio LightSwitch&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://visualstudio.uservoice.com/forums/131389-visual-studio-performance"&gt;Visual Studio Performance&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h2&gt;Connect&lt;/h2&gt; &lt;p&gt;While UserVoice is great for feature requests, bugs are better reported via Connect.&amp;nbsp; The challenge with Connect is finding the right place to log the bug.&amp;nbsp; In the case of developer tools, you’ll find them listed here:&lt;/p&gt; &lt;p&gt;&lt;a href="http://connect.microsoft.com/directory/accepting-bugs/developer-tools/"&gt;Connect – Developer Tools&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Many of the products will also accept suggestions, in addition to bugs, via connect.&amp;nbsp; If you’re really pushing for something, it wouldn’t hurt to post it to both UserVoice and Connect.&amp;nbsp; Some of the specific Connect links for product feedback and bugs include:&lt;a href="http://ardalis.com/Media/Default/Windows-Live-Writer/How-to-Give-Feedback-on-Microsoft-Develo_8D74/image_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 10px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://ardalis.com/Media/Default/Windows-Live-Writer/How-to-Give-Feedback-on-Microsoft-Develo_8D74/image_thumb.png" width="201" height="73"&gt;&lt;/a&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://connect.microsoft.com/site1287"&gt;Blend&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://connect.microsoft.com/site1231"&gt;Visual Studio Lightswitch&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://connect.microsoft.com/wcf"&gt;Windows Communication Foundation (WCF)&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://connect.microsoft.com/VisualStudio"&gt;Visual Studio and .NET Framework&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://connect.microsoft.com/wf"&gt;Windows Workflow Foundation&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Unlike UserVoice, Connect can also grant access to private forums and resources.&amp;nbsp; If you’re in a particular “insiders” or early adopters program, you’ll likely use Connect to get access to documentation and software, as well as to leave feedback on the product(s) you’re using.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h2&gt;Twitter&lt;/h2&gt; &lt;p&gt;Twitter has become a very popular way for software developers to communicate.&amp;nbsp; Microsoft has a large presence on twitter, and you can use this medium as another way to reach our to Microsoft and provide feedback.&amp;nbsp; Most of the actual developers and PMs working on developer tools for Microsoft are on twitter, and the various products have official twitter accounts as well.&amp;nbsp; There are several ways you can have your voice heard, even if you’re completely new to twitter (if you are, the first step is to create an account – the rest of these assume you have one).&lt;/p&gt; &lt;h3&gt;Follow the Conversation&lt;/h3&gt; &lt;p&gt;If you’ve ever been a member of a mailing list or newsgroup, you probably know that it’s often best to “lurk” for a bit to get a feel for how the community interacts, who the main contributors are, etc.&amp;nbsp; You’ll usually get a better reaction from the participants in the discussion if you understand how they interact and follow the often unwritten rules of the medium.&amp;nbsp; Twitter has no private meeting rooms, but this notion of understanding who’s involved in the community still applies.&amp;nbsp; Before you speak, it’s a good idea to listen.&amp;nbsp; There are several ways to find the conversations of interest to you on twitter, including accounts, hash tags, and lists.&lt;/p&gt; &lt;h3&gt;Follow Specific Accounts&lt;/h3&gt; &lt;p&gt;Whatever tools and technology you’re using, there are most likely official twitter accounts for them and certainly individuals who are involved in creating, supporting, and using the technology.&amp;nbsp; Here are some official twitter accounts for various products you might wish to follow.&amp;nbsp; Once you follow them, you’ll be able to see which users they tend to interact with, and twitter itself will suggest other twitter accounts you may wish to follow.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://twitter.com/#!/aspnet"&gt;@aspnet&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://twitter.com/#!/visualstudio"&gt;@visualstudio&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="https://twitter.com/#!/Silverlight"&gt;@silverlight&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="https://twitter.com/#!/MSExpression"&gt;@MSExpression&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="https://twitter.com/#!/windowsphone"&gt;@windowsphone&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="https://twitter.com/#!/WindowsAzure"&gt;@windowsazure&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;In addition to product-specific accounts, which tend to mostly post announcements and occasional responses to tweets that reference them, you can also follow real people.&amp;nbsp; For instance, if you’re interested in ASP.NET and/or Azure, then you’ll want to be sure to follow Scott Guthrie (VP of Azure) and Scott Hanselman (prolific community rep for ASP.NET).&amp;nbsp; You can follow me, too, if you like, though I don’t have nearly the reach and influence of these two Scotts.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="https://twitter.com/#!/scottgu"&gt;@scottgu&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="https://twitter.com/#!/shanselman"&gt;@shanselman&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="https://twitter.com/#!/ardalis"&gt;@ardalis&lt;/a&gt; (me)&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Once you’re following a few of these accounts, you can use Twitter’s “similar to” feature to find additional people you may be interested in following.&amp;nbsp; For instance, &lt;a href="https://twitter.com/#!/similar_to/ardalis"&gt;here’s a list of accounts Twitter thinks are similar to mine&lt;/a&gt;.&lt;/p&gt; &lt;h3&gt;Follow Hash Tags&lt;/h3&gt; &lt;p&gt;In addition to following individuals, you can also follow hash tags.&amp;nbsp; Hash tags are simply words you can include in a tweet to “tag” them as being related to a particular topic, and by convention these are prefixed with a hash (#) symbol.&amp;nbsp; For instance, &lt;a href="https://twitter.com/#!/search/%23aspnet"&gt;#aspnet&lt;/a&gt; would be used to indicate a tweet that maybe didn’t mention ASP.NET/ASPNET by name was related to this technology.&amp;nbsp; Most twitter client applications offer support for saved searches that will let you follow a hash tag, or you can &lt;a href="https://twitter.com/#!/search/%23aspnet"&gt;search for a hashtag on twitter’s web site&lt;/a&gt;.&amp;nbsp; By following the hashtag, you’ll start to see who the major players are in the conversation, and you can add them to your list of people you follow if you find them interesting.&lt;/p&gt; &lt;h3&gt;Follow Lists&lt;/h3&gt; &lt;p&gt;Twitter also has support for Lists, which any user can create.&amp;nbsp; You can subscribe to a list, and viewing a particular list lets you see a stream of just that lists’ members’ tweets.&amp;nbsp; This can be a great way to filter different interests you might have, and gives you a way to pseudo-follow individuals without actually following them and having their tweets in your main stream.&amp;nbsp; There’s &lt;a href="http://mashable.com/2009/11/02/twitter-lists-guide/"&gt;a good write-up on Twitter Lists here&lt;/a&gt;.&amp;nbsp; As an example, you can see a &lt;a href="https://twitter.com/#!/shanselman/programmers"&gt;List of all programmers Scott Hanselman follows (or did when he created the list) here&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h2&gt;Project Hubs&lt;/h2&gt; &lt;p&gt;Many of the projects currently under development for Microsoft&amp;nbsp; developers are built in the open at sites like &lt;a href="http://www.codeplex.com/"&gt;CodePlex&lt;/a&gt; and &lt;a href="https://github.com/"&gt;GitHub&lt;/a&gt;.&amp;nbsp; You can find out more about projects, get access to source code, and report issues.&amp;nbsp; You can even fork the code and submit a pull request for the owner to consider including in the project.&amp;nbsp; Here are a few project hubs you might want to check out:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://json.codeplex.com/"&gt;Json.NET&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://aspnet.codeplex.com/"&gt;ASP.NET&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://nuget.codeplex.com/"&gt;NuGet&lt;/a&gt; (CodePlex)&lt;/li&gt; &lt;li&gt;&lt;a href="https://github.com/NuGet"&gt;NuGet&lt;/a&gt; (GitHub)&lt;/li&gt; &lt;li&gt;&lt;a href="http://orchard.codeplex.com/"&gt;Orchard CMS&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="https://github.com/SignalR/SignalR"&gt;SignalR&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="https://github.com/SteveSanderson/knockout"&gt;Knockout&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="https://github.com/WindowsAzure"&gt;WindowsAzure&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="https://github.com/WindowsAzure/iisnode"&gt;Node for IIS&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="https://github.com/WindowsAzure/azure-sdk-for-node"&gt;Node for Azure&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;If you’re serious about getting your idea implemented, you can always create your own implementation of it, either from scratch or by forking an existing project.&amp;nbsp; This can provide a great way to explain how you would approach the problem and what your idea of the solution looks like.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h2&gt;Your Blog&lt;/h2&gt; &lt;p&gt;Don’t underestimate the power of your blog to express your ideas and get them heard by the community.&amp;nbsp; Even if, like most of us, your blog doesn’t get inundated with traffic, it can provide you with a place to explain your thoughts in whatever way makes sense to you.&amp;nbsp; Your blog can be a great way to support your feedback via other means, as you can link to a post that elaborates on an idea you couldn’t fully describe in 140 characters on twitter.&amp;nbsp; The best ideas and feedback offer constructive criticism and reasons why the status quo causes you pain or slows you down.&amp;nbsp; Try to avoid rants or simply complaining that a particular product of feature “sucks” if you’re hoping for someone to actually take action.&amp;nbsp; You’ll also find that while sensational titles can work well as “link bait”, &lt;a href="http://www.hanselman.com/blog/LinkbaitHackerSlashNewsDotConsideredCancerousRequestForCallToAction.aspx"&gt;they’re also cliché enough at this point that whole articles have been written making fun of them&lt;/a&gt;.&amp;nbsp; Try to craft a compelling and honest title, but try to avoid over-sensationalizing if you want to have a reasonable conversation with your readers.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h2&gt;Personal Contacts&lt;/h2&gt; &lt;p&gt;Just like in real life, often the best way to explain yourself is through personal connections with real people.&amp;nbsp; When you have the opportunity, go to a conference or user group and listen to the folks in your community of choice.&amp;nbsp; Introduce yourself.&amp;nbsp; Have a conversation.&amp;nbsp; Ask questions and listen to what they’re working on right now, and let them know what you’re doing and how you could be doing it better.&amp;nbsp; Shockingly this kind of interaction can be much higher value than any virtual electronic system, so don’t underestimate it.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h2&gt;What Works For You?&lt;/h2&gt; &lt;p&gt;Hopefully you’ve found this useful, now it’s time to give something back.&amp;nbsp; What have you found to be the most effective way to provide feedback on Microsoft developer tools?&amp;nbsp; Post a comment with your story, and let us know.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/lh3XYxPVYTiLGQQtqWDJb4iySA8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lh3XYxPVYTiLGQQtqWDJb4iySA8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/lh3XYxPVYTiLGQQtqWDJb4iySA8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lh3XYxPVYTiLGQQtqWDJb4iySA8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=ycavq0-B9z0:edy0XbvmJfk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=ycavq0-B9z0:edy0XbvmJfk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=ycavq0-B9z0:edy0XbvmJfk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=ycavq0-B9z0:edy0XbvmJfk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=ycavq0-B9z0:edy0XbvmJfk:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=ycavq0-B9z0:edy0XbvmJfk:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StevenSmith/~4/ycavq0-B9z0" height="1" width="1"/&gt;</description><pubDate>Mon, 12 Mar 2012 16:12:51 GMT</pubDate><guid isPermaLink="true">http://ardalis.com:80/how-to-give-feedback-on-microsoft-developer-products</guid></item><item><title>Personal Kanban Book Review</title><link>http://ardalis.com:80/personal-kanban-book-review</link><description>&lt;p&gt;&lt;a href="http://amzn.to/wuqtnL"&gt;&lt;img style="margin: 0px 0px 5px 5px; display: inline; float: right" align="right" src="http://ourfounder.typepad.com/.a/6a00d8341cdbc253ef0147e24dd46c970b-320wi" width="160" height="240"&gt;&lt;/a&gt;Not long ago, while preparing my &lt;a href="http://www.pluralsight-training.net/microsoft/Courses/TableOfContents?courseName=kanban-fundamentals"&gt;Kanban Fundamentals video training class for Pluralsight&lt;/a&gt;, I read &lt;a href="http://amzn.to/wuqtnL"&gt;Personal Kanban&lt;/a&gt;, by Jim Benson and Tonianne DeMaria Barry.&amp;nbsp; If you’re new to the concept of &lt;em&gt;&lt;a href="http://en.wikipedia.org/wiki/Kanban"&gt;kanban&lt;/a&gt;&lt;/em&gt;, this book is a good place to get started (along with my course, which is about 90 minutes long, and &lt;a href="http://lostechies.com/sharoncichelli/2012/03/05/pluralsight-videos-how-to-change-the-playback-speed/"&gt;shorter if you speed it up&lt;/a&gt;).&amp;nbsp; I read the kindle edition of Personal Kanban, even though I don’t own a Kindle.&amp;nbsp; It allowed me to read it at my PC, on my iPad, and on my Windows Phone, depending on where I found the time.&amp;nbsp; Whether you pick up the book for $10 electronically or $25 on paper, it’s very reasonably priced and is a fairly quick read at just 216 pages (paper).&lt;/p&gt; &lt;h2&gt;What’s To Like&lt;/h2&gt; &lt;p&gt;I really enjoyed the book’s narrative and simple, straightforward style.&amp;nbsp; The authors do a great job of presenting the material in a very approachable manner.&amp;nbsp; The use of cartoons and photographs help to explain important points.&amp;nbsp; I also liked that the book jumps into the material in the first chapter, explaining why Personal Kanban is needed, what the rules are, and why they work.&amp;nbsp; By the second chapter, you’re already creating your own personal kanban using easily available and inexpensive materials.&lt;/p&gt; &lt;p&gt;The book’s system has only two rules: Visualize Your Work and Limit Work in Progress (or Process).&amp;nbsp; These two rules drive the process, and the details of how an particular system is implemented can vary based on what works for the individual.&amp;nbsp; The rest of the book explains how these rules help to maximize flow and effectiveness over utilization and efficiency.&lt;/p&gt; &lt;p&gt;The authors also have a blog and continue to post valuable material related to the book’s topic at &lt;a href="http://www.personalkanban.com/pk/"&gt;PersonalKanban.com&lt;/a&gt;.&lt;/p&gt; &lt;h2&gt;What to Improve&lt;/h2&gt; &lt;p&gt;One reviewer on Amazon describes the book as “A good idea sold in too many pages.”&amp;nbsp; I can relate somewhat to this reviewer, as the book, even at just over 200 pages, is at its core describing a very simple idea with a very simple implementation.&amp;nbsp; This is both its blessing and its curse.&amp;nbsp; The authors do not waste the reader’s time with fluff, in my opinion, but I certainly agree that the greatest value in the book comes from the first couple of chapters and the rest is supporting material.&lt;/p&gt; &lt;p&gt;In the kindle edition, at least, some of the illustrations/cartoons are not terribly high resolution, making some of the small text difficult to make out.&amp;nbsp; The main points of the cartoons are completely legible, though, so this is a very minor concern, and probably out of the authors’ control.&lt;/p&gt; &lt;h2&gt;Summary&lt;/h2&gt; &lt;p&gt;I’ve reviewed the book with four stars on Amazon.&amp;nbsp; I found it to be valuable and integrated many of its ideas into my course.&amp;nbsp; If you’re looking to learn more about how to use kanban and lean concepts in software development, this book can be a good primer.&amp;nbsp; Once you’ve finished it, I would recommend you read &lt;a href="http://amzn.to/wpRfnF"&gt;Kanban&lt;/a&gt;, &lt;a href="http://amzn.to/ytEne8"&gt;Lean Software Development&lt;/a&gt; (&lt;a href="http://ardalis.com/slack-and-constraints-and-optimizing-throughput"&gt;related post&lt;/a&gt;), &lt;a href="http://amzn.to/w076PK"&gt;Scrumban&lt;/a&gt; (&lt;a href="http://ardalis.com/reviewing-scrumban-the-book"&gt;review&lt;/a&gt;), and finally &lt;a href="http://amzn.to/yzqWOR"&gt;Principles of Product Development Flow&lt;/a&gt;, in order from least to most advanced.&amp;nbsp; My &lt;a href="http://www.pluralsight-training.net/microsoft/Courses/TableOfContents?courseName=kanban-fundamentals"&gt;Kanban Fundamentals course&lt;/a&gt; is meant to cover the basics described in Personal Kanban and Kanban, primarily.&amp;nbsp; I hope to produce a follow-up course that gets into more advanced lean/kanban principles and practices described in the latter titles and my own experience.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/astW-vzQ0KUrj-Csvi4Dje3NaAk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/astW-vzQ0KUrj-Csvi4Dje3NaAk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/astW-vzQ0KUrj-Csvi4Dje3NaAk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/astW-vzQ0KUrj-Csvi4Dje3NaAk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=c4F_AzUmvkU:f3pChxdTF6M:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=c4F_AzUmvkU:f3pChxdTF6M:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=c4F_AzUmvkU:f3pChxdTF6M:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=c4F_AzUmvkU:f3pChxdTF6M:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=c4F_AzUmvkU:f3pChxdTF6M:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=c4F_AzUmvkU:f3pChxdTF6M:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StevenSmith/~4/c4F_AzUmvkU" height="1" width="1"/&gt;</description><pubDate>Fri, 09 Mar 2012 14:29:53 GMT</pubDate><guid isPermaLink="true">http://ardalis.com:80/personal-kanban-book-review</guid></item><item><title>Sending Email from a Sitefinity Module with Attachments</title><link>http://ardalis.com:80/sending-email-from-a-sitefinity-module-with-attachments</link><description>&lt;p&gt;A fairly common use case in web applications is the need to send an email, and applications built on top of Telerik Sitefinity are no different.&amp;nbsp; Since modules are simply .NET DLLs, you’re free to write whatever code you like, so it’s certainly possible for you to write a module that sends emails in a way that knows nothing about Sitefinity.&amp;nbsp; However, if you want to interact with Sitefinity, for instance making sure that you use the same SMTP server that is configured in the Sitefinity settings, or attaching a file from a Sitefinity library, then this post will show you how to do so.&amp;nbsp; I strongly recommend that you allow the user to configure the way emails are sent via the Sitefinity UI if your module will be sending emails, as it will be confusing and annoying to users if this isn’t the case.&lt;/p&gt; &lt;h2&gt;Sitefinity Email Settings&lt;/h2&gt; &lt;p&gt;You can find your Sitefinity email settings by going to Administration – Settings – Advanced – System – SMTP (Email Settings).&amp;nbsp; You’ll also find a separate location with settings for sending Newsletters under Administration – Settings&amp;nbsp; Advanced – Newsletters.&amp;nbsp; You can use either one for your custom module’s settings – which one you choose really depends on what you’re doing.&amp;nbsp; If you’re sending some kind of administrator alert, then the System one probably makes more sense.&amp;nbsp; If you’re letting users sign up for notifications about updates to your site, then perhaps the Newsleters section is the more logical choice.&amp;nbsp; You can see where to set them in the UI here:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ardalis.com/Media/Default/Windows-Live-Writer/Sending-Email-from-a-Sitefinity-Module_5FE1/image_4.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Sending-Email-from-a-Sitefinity-Module_5FE1/image_thumb_1.png" width="230" height="244"&gt;&lt;/a&gt;&lt;a href="http://ardalis.com/Media/Default/Windows-Live-Writer/Sending-Email-from-a-Sitefinity-Module_5FE1/image_2.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="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Sending-Email-from-a-Sitefinity-Module_5FE1/image_thumb.png" width="244" height="172"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;In my example, I’m going to use the Newsletters section, but I’ve included the code for the System setting in a comment.&lt;/p&gt; &lt;h3&gt;Sending Email in Sitefinity&lt;/h3&gt; &lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; SendEmail(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; toEmail, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; fromEmail, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; subject, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; body)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;       var manager = ConfigManager.GetManager();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;       &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; smtpHost = manager.GetSection&amp;lt;NewslettersConfig&amp;gt;().SmtpHost;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;       &lt;span style="color: #008000"&gt;//string smtpHost = manager.GetSection&amp;lt;SystemConfig&amp;gt;().SmtpSettings.Host;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;       var smtpClient = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; SmtpClient(smtpHost);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;       var message =&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;           &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; MailMessage(fromEmail, toEmail)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;           {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;               Subject = subject,&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;               Body = body&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;           };&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;       smtpClient.Send(message);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;   }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2&gt;Adding an Attachment&lt;/h2&gt;
&lt;p&gt;In Sitefinity, you can use the Fluent API to work with most of the content in a site.&amp;nbsp; For instance, to work with the documents in the site, you can simply write App.WorkWith().Documents() and follow this up with whatever commands you wish to send.&amp;nbsp; If you need to get an instance of a document, you can call Get().&amp;nbsp; If you need to pull in the document’s raw data as a stream, you can use the DownloadContent(out stream) method.&amp;nbsp; You can chain all of these things together into a single statement that gets a given document and its stream of data.&amp;nbsp; One you have this, it’s easy to use the stream to add a file attachment to an email.&amp;nbsp; In this example, we are simply attaching the first document that we find in the site’s document library – in the real world you would pick a particular document by its id or perhaps title.&lt;/p&gt;
&lt;h3&gt;Sending Email with Attachment in Sitefinity&lt;/h3&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; SendEmail(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; toEmail, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; fromEmail, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; subject, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; body)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    var manager = ConfigManager.GetManager();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; smtpHost = manager.GetSection&amp;lt;NewslettersConfig&amp;gt;().SmtpHost;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #008000"&gt;//string smtpHost = manager.GetSection&amp;lt;SystemConfig&amp;gt;().SmtpSettings.Host;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    var smtpClient = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; SmtpClient(smtpHost);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    var message =&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; MailMessage(fromEmail, toEmail)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            Subject = subject,&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            Body = body&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        };&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #008000"&gt;// attach a document from a sitefinity document library&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #008000"&gt;// this example just gets the first document it finds&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    System.IO.Stream stream;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    var doc = App.WorkWith()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        .Documents()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        .First()&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        .DownloadContent(&lt;span style="color: #0000ff"&gt;out&lt;/span&gt; stream)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        .Get();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    var fileAttachment =&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Attachment(stream, doc.MimeType);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    message.Attachments.Add(fileAttachment);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    smtpClient.Send(message);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;





&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;As you can see, it’s pretty easy to work with email from within a Sitefinity module or widget, leveraging the existing settings and document libraries of the site.&amp;nbsp; The Sitefinity API is quite extensive, and the Fluent API can provide a very intuitive and flexible way to interact with the system.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/2ROXFqKoTFdlF0tEj1VxdggLEsM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2ROXFqKoTFdlF0tEj1VxdggLEsM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/2ROXFqKoTFdlF0tEj1VxdggLEsM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2ROXFqKoTFdlF0tEj1VxdggLEsM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=FWSPGjdI0EU:yAs5G6NAnS8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=FWSPGjdI0EU:yAs5G6NAnS8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=FWSPGjdI0EU:yAs5G6NAnS8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=FWSPGjdI0EU:yAs5G6NAnS8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=FWSPGjdI0EU:yAs5G6NAnS8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=FWSPGjdI0EU:yAs5G6NAnS8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StevenSmith/~4/FWSPGjdI0EU" height="1" width="1"/&gt;</description><pubDate>Fri, 24 Feb 2012 21:42:06 GMT</pubDate><guid isPermaLink="true">http://ardalis.com:80/sending-email-from-a-sitefinity-module-with-attachments</guid></item><item><title>Reviewing Scrumban the Book</title><link>http://ardalis.com:80/reviewing-scrumban-the-book</link><description>&lt;p&gt;&lt;a href="http://amzn.to/wJJMBR"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Reviewing-Scrumban-the-Book_E09F/image_3.png" width="240" height="240"&gt;&lt;/a&gt;I’ve been reading a bunch of kanban and lean books recently as I work on my &lt;a href="http://ardalis.com/training-classes"&gt;Pluralsight course&lt;/a&gt; on &lt;a href="http://www.pluralsight-training.net/microsoft/courses/TableOfContents?courseName=kanban-fundamentals"&gt;Introducing Kanban&lt;/a&gt;.&amp;nbsp; The most recent one I’ve finished is &lt;em&gt;&lt;a href="http://amzn.to/wJJMBR"&gt;Scrumban, Essays on Kanban Systems for Lean Software Development&lt;/a&gt;&lt;/em&gt;, by Corey Ladas (I’m doing the reviews in LIFO order).&amp;nbsp; I made a bunch of notes while reading this book, and it has a great deal of useful information.&amp;nbsp; I read &lt;a href="http://amzn.to/zlzuKg"&gt;David Anderson’s Kanban book&lt;/a&gt; first, followed by &lt;a href="http://amzn.to/zmlnVg"&gt;Benson and Barry’s Personal Kanban&lt;/a&gt;.&amp;nbsp; I think reading Scrumban last was definitely the right choice, though if I were recommending these books today I would most likely suggest someone start with Personal Kanban, as it’s the lightest weight of the three.&lt;/p&gt; &lt;p&gt;One thing that sets Scrumban apart from the other books is the narrative style and organization of the book.&amp;nbsp; As it says in the title’s byline, this book is a collection of essays – there isn’t a great deal of cohesion or a consistent narrative guiding you through the book.&amp;nbsp; It also tends to assume a fair bit of of knowledge on the part of the reader, which is one reason why I wouldn’t start off with this book if you’re just starting to learn about kanban and lean software development.&amp;nbsp; I also don’t think the title is particularly fitting, since there is only one essay that deals with scrum and mentions the term scrumban in the whole book.&amp;nbsp; I have a feeling the title was chosen mainly because it was short and would leverage the popularity of scrum to drive up book sales – whether this was the case or was successful I can’t say.&lt;/p&gt; &lt;p&gt;I found a great deal of value in the book, and it is certainly no rehash of the other two kanban titles listed above.&amp;nbsp; There are some very important, basic concepts covered here such as the analogy of kanban tokens to money in one of the first essays.&amp;nbsp; Corey does a great job of examining multiple different approaches to processes and showing their pros and cons.&amp;nbsp; Things like methods for synchronizing different handoffs between related up- and downstream collaborators in a process are explained clearly and are honestly things I’d never given much thought previously.&amp;nbsp; The book also does a great job of reinforcing the notion that time-boxed iterations are a stepping stone to an even more streamlined process.&amp;nbsp; If you’ve ever considered the logical progression of moving from infrequent software builds, to having a daily build, to having continuous integration, you can see the same logic being applied to moving from large project phases and handoffs (e.g. &lt;a href="http://deviq.com/waterfall"&gt;waterfall&lt;/a&gt;) to many smaller and iterative iterations (sprints), to continuous software delivery and one piece flow (ideal).&lt;/p&gt; &lt;p&gt;One criticism I do have of the book is that it often didn’t define new terms and acronyms as they were introduced.&amp;nbsp; I noted a bunch of them:&lt;/p&gt; &lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Analytic_Hierarchy_Process"&gt;AHP prioritization&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Takt_time"&gt;takt time&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;&lt;a href="http://en.wikipedia.org/wiki/Heijunka"&gt;heijunka board&lt;/a&gt;&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.signalguys.com/c/Andon_Lights.html"&gt;andon lights&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Axiomatic_design"&gt;axiomatic design&lt;/a&gt;&lt;/p&gt; &lt;p&gt;There were probably more that I missed because I was already familiar with the term, and of course it’s possible some of these were covered somewhere in the book and I missed them, but these were my “google these later” notes.&amp;nbsp; The links above are the result of my google-fu after-the-fact.&lt;/p&gt; &lt;p&gt;The latter 2/3 of the book shows a bunch of different ways to model processes using task boards, and the effects of each of these designs.&amp;nbsp; The analysis from these areas of the book are easily worth the price of the whole book, considering how much time they’ll save you if you’re just getting started.&amp;nbsp; The book doesn’t propose one right way to go about implementing such systems, but it does a very good job of showing the pros and cons of a number of approaches.&lt;/p&gt; &lt;p&gt;Overall, I thought the book had some great information, but could have been organized better.&amp;nbsp; I would give it 3 or 4 stars on Amazon and would recommend other books first, but if you’ve read the others and still want to learn more, there’s some great information here.&lt;/p&gt; &lt;p&gt;If you’re looking for a quick introduction to kanban for personal or team use, check out my &lt;a href="http://www.pluralsight-training.net/microsoft/courses/TableOfContents?courseName=kanban-fundamentals"&gt;Kanban Fundamentals course on Pluralsight.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/OP17J278xCbTkmQKRRmzSaf_PjU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/OP17J278xCbTkmQKRRmzSaf_PjU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/OP17J278xCbTkmQKRRmzSaf_PjU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/OP17J278xCbTkmQKRRmzSaf_PjU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=3VnQgsWzwhI:Wk4yUJfsaLg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=3VnQgsWzwhI:Wk4yUJfsaLg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=3VnQgsWzwhI:Wk4yUJfsaLg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=3VnQgsWzwhI:Wk4yUJfsaLg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=3VnQgsWzwhI:Wk4yUJfsaLg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=3VnQgsWzwhI:Wk4yUJfsaLg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StevenSmith/~4/3VnQgsWzwhI" height="1" width="1"/&gt;</description><pubDate>Fri, 24 Feb 2012 14:10:56 GMT</pubDate><guid isPermaLink="true">http://ardalis.com:80/reviewing-scrumban-the-book</guid></item><item><title>Asus Zen Ultrabook One Month Later</title><link>http://ardalis.com:80/asus-zen-ultrabook-one-month-later</link><description>&lt;p&gt;I &lt;a href="http://ardalis.com/Asus-Zen-Ultrabook-First-Impressions"&gt;wrote a few weeks ago about my new Asus Zen Ultrabook&lt;/a&gt; computer.&amp;nbsp; I’ve&amp;nbsp; been using it as my primary laptop computer since then, and thought I’d write up a follow-up on how it’s been.&amp;nbsp; Overall, I’m quite pleased with it.&amp;nbsp; The performance is great, the battery life is quite good, and the instant on/off experience makes it almost as quick and easy to use as my phone or iPad.&amp;nbsp; In fact, I’ve just spent the last three days on the road at a client conducting training, and driving as many as four concurrent Visual Studio 2010 instances along with three browsers, SQL Server, and PowerPoint, and everything ran great.&amp;nbsp; So, the short version is, it’s a nice piece of kit and you probably won’t be disappointed with one if you pick one up.&amp;nbsp; &lt;/p&gt; &lt;p&gt;Here are some more thoughts, broken out into a few categories.&lt;/p&gt; &lt;h2&gt;Physical Features&lt;/h2&gt; &lt;p&gt;The Zen Ultrabook has a smooth metal finish that makes it very solid.&amp;nbsp; In fact, it’s downright dangerous looking, it’s so thin.&amp;nbsp; I’ve joked to a few people that you could use the Asus Zenbook to hack apart zombies, and it would probably keep working afterward.&amp;nbsp; It’s that thin, sharp, and solid.&amp;nbsp; If you think thin is sexy, you’ll want to check this machine out.&amp;nbsp; Its metal case also makes it very rigid.&amp;nbsp; I can hold it with two fingers, open, from one corner, at arm’s length, easily.&lt;/p&gt; &lt;p&gt;Being a super-thin laptop, it doesn’t have some of the things fatter laptops have, like DVD drives or VGA ports.&amp;nbsp; Instead it has mini-ports for video, and only two USB ports.&amp;nbsp; It does have an integrated MMC/SD card reader, though, which is handy, and it comes with a USB-to-Ethernet dongle that I’ve used all of twice in the last month when I needed a hardwired connection.&amp;nbsp; Otherwise, wireless works great.&lt;/p&gt; &lt;p&gt;The keyboard takes some getting used to.&amp;nbsp; It’s not like any other I’ve used in the past, and new users including me tend to make a lot more typing errors on it than typical.&amp;nbsp; It can be rather frustrating, but I’m starting to get the hang of it.&amp;nbsp; The fact that the Home/End/PageUp/PageDown keys are all accessed via the Fn+Arrow keys is annoying, since I’m accustomed t having those as actual keys, but hardly a show-stopper.&lt;/p&gt; &lt;p&gt;The touchpad takes some getting used to, as well.&amp;nbsp; It’s very big and sensitive, and supports both tap-to-click like most touchpads as well as push-in to click, which is somewhat novel&amp;nbsp; Also, the buttons are not separate, but are part of the touchpad, which means that when you think you’re putting your finger on the button area to click, you can still be moving the pointer, so you have to get used to that as well.&amp;nbsp; Once you do, it’s all good.&lt;/p&gt; &lt;p&gt;One minor issue I ran into at one client had to do with the tight placement of the ports on the right side.&amp;nbsp; The mini-video port is so close to the USB port that some USB devices won’t fit into the space while you’re using the video port (e.g. presenting via a projector).&amp;nbsp; It’s only been an issue once, and it’s more a failing on the part of the USB device than the laptop, since there’s generally no reason why the USB device needs to be so fat where it’s connecting to the USB port.&lt;/p&gt; &lt;p&gt;it’s super-light.&amp;nbsp; It plus its power adapter are less than half the weight of my previous laptop.&lt;/p&gt; &lt;h2&gt;Running Programs&lt;/h2&gt; &lt;p&gt;I mentioned at the outset that the performance of the machine has been great.&amp;nbsp; The screen is big enough to develop productively on – yeah, I’d prefer my desktop workstation with 2 or 3 big monitors, but for a portable computer, this one has been great.&amp;nbsp; And it’s small enough to open comfortably on an airplane, as well, with enough battery to last 5-6 hours.&amp;nbsp; Here’s the specs on the OS and system:&lt;/p&gt; &lt;p&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="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/a90c4fcb9d25_F605/image_8.png" width="610" height="484"&gt;&lt;/p&gt; &lt;p&gt;And here’s the Windows Performance Index:&lt;/p&gt; &lt;p&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="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/a90c4fcb9d25_F605/image_7.png" width="644" height="165"&gt;&lt;/p&gt; &lt;p&gt;Even with VS, Skype, several browsers, etc. all running, the system is extremely responsive.&amp;nbsp; Here’s what it looks like literally as I’m writing this:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ardalis.com/Media/Default/Windows-Live-Writer/a90c4fcb9d25_F605/image_6.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="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/a90c4fcb9d25_F605/image_thumb_2.png" width="644" height="364"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;I haven’t installed or played any games on the machine, so I can’t tell you how well it plays Starcraft II or Call of Duty.&amp;nbsp; For work purposes, though, including building large software solutions while on the go, it’s quite good.&amp;nbsp; Here’s a final screenshot of Visual Studio, showing how much space you have:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ardalis.com/Media/Default/Windows-Live-Writer/a90c4fcb9d25_F605/SNAGHTML912ee44.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="SNAGHTML912ee44" border="0" alt="SNAGHTML912ee44" src="http://ardalis.com/Media/Default/Windows-Live-Writer/a90c4fcb9d25_F605/SNAGHTML912ee44_thumb.png" width="644" height="348"&gt;&lt;/a&gt;&lt;/p&gt; &lt;h2&gt;Summary&lt;/h2&gt; &lt;p&gt;I’m very happy with this machine.&amp;nbsp; More ports, infinite battery life, and a keyboard that is a bit more like ones I’m used to are things I might ask for to improve it.&amp;nbsp; But overall, it’s an awesome machine packed into a super-thin, super-light chassis.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;em&gt;Disclosure of Material Connection: I received one or more of the products or services mentioned above for free in the hope that I would mention it on my blog. Regardless, I only recommend products or services I use personally and believe my readers will enjoy. I am disclosing this in accordance with the &lt;a href="http://www.access.gpo.gov/nara/cfr/waisidx_03/16cfr255_03.html"&gt;Federal Trade Commission’s 16 CFR, Part 255: “Guides Concerning the Use of Endorsements and Testimonials in Advertising.”&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/LbjTH_g79nJ4ZSIo3Ci8UF7a9lU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LbjTH_g79nJ4ZSIo3Ci8UF7a9lU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/LbjTH_g79nJ4ZSIo3Ci8UF7a9lU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LbjTH_g79nJ4ZSIo3Ci8UF7a9lU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=Lnt2tjxhp1o:q2BaENZtPy8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=Lnt2tjxhp1o:q2BaENZtPy8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=Lnt2tjxhp1o:q2BaENZtPy8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=Lnt2tjxhp1o:q2BaENZtPy8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=Lnt2tjxhp1o:q2BaENZtPy8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=Lnt2tjxhp1o:q2BaENZtPy8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StevenSmith/~4/Lnt2tjxhp1o" height="1" width="1"/&gt;</description><pubDate>Thu, 23 Feb 2012 02:26:27 GMT</pubDate><guid isPermaLink="true">http://ardalis.com:80/asus-zen-ultrabook-one-month-later</guid></item><item><title>Excel Cumulative Flow Diagram</title><link>http://ardalis.com:80/excel-cumulative-flow-diagram</link><description>&lt;p&gt;&lt;a href="http://stevesmithblog.s3.amazonaws.com/SampleCumulativeFlowDiagram.zip"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 0px 5px 5px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Excel-Cumulative-Flow-Diagram_967B/image_5.png" width="378" height="277"&gt;&lt;/a&gt;I’m working on a Kanban Fundamentals course that should go live soon on &lt;a href="http://pluralsight.com/"&gt;Pluralsight&lt;/a&gt;.&amp;nbsp; One of the topics I’m touching on is Cumulative Flow Diagrams, and how these can be used to analyze flow of a process.&amp;nbsp; Some electronic kanban tools like AgileZen have some built-in support for CFD-style reports, but for instructional purposes it’s nice to be able to create one on-the-fly with whatever data one needs to illustrate a point.&amp;nbsp; And of course, if you’re not using any fancy tools but would still like to benefit from the insights a cumulative flow diagram can provide, it’s nice to know how easily one can create one using Excel.&lt;/p&gt; &lt;p&gt;I’ve created a sample you can download and modify for your needs.&amp;nbsp; This will of course be the fastest way to get started:&lt;/p&gt; &lt;p&gt;&lt;a href="http://stevesmithblog.s3.amazonaws.com/SampleCumulativeFlowDiagram.zip"&gt;Sample Excel Cumulative Flow Diagram Worksheet and Chart&lt;/a&gt;&lt;/p&gt; &lt;h2&gt;Creating a Cumulative Flow Diagram in Excel&lt;/h2&gt;  &lt;p&gt;To create your own cumulative flow diagram in Excel, simply create a worksheet with a column for the date, and columns for each of the states in the process you are modeling.&amp;nbsp; For example, if your software development team’s process has tasks moving through states of Ready, Develop, Test, and Deployed, then you might create an Excel worksheet with columns like this:&lt;/p&gt; &lt;p&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="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Excel-Cumulative-Flow-Diagram_967B/image_8.png" width="395" height="248"&gt;&lt;/p&gt; &lt;p&gt;Next, begin collecting data.&amp;nbsp; At a particular time each day, and at the same time each day, not how many stories, cards, tasks, or whatever you’re using in your system to represent active work items are currently in your system.&amp;nbsp; Record how many are in each state.&amp;nbsp; Pay no attention to which ones, specifically, are in each state – a CFD is an aggregate tool and doesn’t focus on individual work items.&amp;nbsp; After a few days, you should have some data like what’s shown above.&lt;/p&gt; &lt;p&gt;Once you have some data, you can create a cumulative flow diagram in Excel using Excel’s built-in charting capabilities.&amp;nbsp; Simply highlight all of your data and the headings, and select Insert – Charts – Area – Stacked Area as shown here using Excel 2010:&lt;/p&gt; &lt;p&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="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Excel-Cumulative-Flow-Diagram_967B/image_14.png" width="644" height="300"&gt;&lt;/p&gt; &lt;p&gt;By default, you’ll most likely get a chart that puts Ready on the bottom and Deployed on the top:&lt;/p&gt; &lt;p&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="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Excel-Cumulative-Flow-Diagram_967B/image_17.png" width="644" height="390"&gt;&lt;/p&gt; &lt;p&gt;By convention, CFDs are set up so that time flows from left to right, and we achieve this by ensuring that the order of the states is such that the earliest states appear at the top and the final state appears at the bottom.&amp;nbsp; You can rearrange the order of the data in your chart by right-clicking on it and choosing Select Data.&amp;nbsp; Then use the arrow keys in the Legend Entries (Series) box to reverse the default ordering of the data series:&lt;/p&gt; &lt;p&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="SNAGHTML80c02e84" border="0" alt="SNAGHTML80c02e84" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Excel-Cumulative-Flow-Diagram_967B/SNAGHTML80c02e84_1.png" width="644" height="353"&gt;&lt;/p&gt; &lt;p&gt;When you’re done, the data in the Legend Entries should be ordered Deployed, Test, Dev, Ready, and your chart should look something like this:&lt;/p&gt; &lt;p&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="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Excel-Cumulative-Flow-Diagram_967B/image_20.png" width="644" height="389"&gt;&lt;/p&gt; &lt;p&gt;You can analyze your flow using a CFD by measuring vertical and horizontal distances within the chart.&amp;nbsp; For instance, in the chart above, if we look at the vertical distance of our activity states (Dev and Test) on 3 February, we can see that we have only 3 work items in process (work-in-process, or WIP).&amp;nbsp; We can also see that our Test activity is outpacing our Dev activity later in the month, with 0 WIP items on the 5th, 7th, and 8th of the month, while the Dev WIP has grown to as high as 4 items.&amp;nbsp; This is identifying a bottleneck in our flow, which at this point is the Dev process.&lt;/p&gt; &lt;p&gt;If we analyze the diagram by measuring horizontal distance, we can determine how long it takes for a work item, on average, to make it through our process.&amp;nbsp; Depending on what you’re trying to do, you may start the clock when an item enters the Backlog, or your Ready queue, or when you actually begin work on the item.&amp;nbsp; For simplicity given the small dataset I’m showing here, let’s say we’re only concerned with the time it takes an item to make it through our Dev and Test activities.&amp;nbsp; Once more if we look at 2 February and measure from the top of the red Dev area horizontally to the right to the top of the purple Deployed area, this will tell us approximately how long items are taking to be deployed that were begun on 2 February.&amp;nbsp; &lt;/p&gt; &lt;p&gt;&lt;a href="http://ardalis.com/Media/Default/Windows-Live-Writer/Excel-Cumulative-Flow-Diagram_967B/image_22.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="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Excel-Cumulative-Flow-Diagram_967B/image_thumb_7.png" width="644" height="389"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;In this case, we see the cycle time is just 1 day.&amp;nbsp; However, if we do the same thing for items which were begun on 3 February, we find that these were not completed until 7 February, or 4 days.&amp;nbsp; Since this is just the beginning of our project and we’re still ramping up, this most likely isn’t a huge area for concern, but if you find a 300% increase in your cycle time in a mature process, it’s definitely worth investigation.&lt;/p&gt; &lt;h2&gt;Summary&lt;/h2&gt; &lt;p&gt;Cumulative Flow Diagrams can be a useful tool to use when analyzing flow of work through a system or process.&amp;nbsp; While there are tools that can produce these charts for you, you can easily create them yourself using Excel, as shown here.&amp;nbsp; Feel free to download and modify the &lt;a href="http://stevesmithblog.s3.amazonaws.com/SampleCumulativeFlowDiagram.zip"&gt;sample Excel cumulative flow diagram file&lt;/a&gt;.&amp;nbsp; If you found this helpful, you may wish to watch my Kanban Fundamentals course on &lt;a href="http://pluralsight.com"&gt;Pluralsight&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/D0AWTMjfugOxP4DAllHcRvWeR7Q/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/D0AWTMjfugOxP4DAllHcRvWeR7Q/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/D0AWTMjfugOxP4DAllHcRvWeR7Q/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/D0AWTMjfugOxP4DAllHcRvWeR7Q/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=VWlxYCdbPAc:x9_mIXBFv3s:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=VWlxYCdbPAc:x9_mIXBFv3s:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=VWlxYCdbPAc:x9_mIXBFv3s:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=VWlxYCdbPAc:x9_mIXBFv3s:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=VWlxYCdbPAc:x9_mIXBFv3s:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=VWlxYCdbPAc:x9_mIXBFv3s:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StevenSmith/~4/VWlxYCdbPAc" height="1" width="1"/&gt;</description><pubDate>Sun, 12 Feb 2012 16:16:42 GMT</pubDate><guid isPermaLink="true">http://ardalis.com:80/excel-cumulative-flow-diagram</guid></item><item><title>Fixing Floating Rectangles in ASP.NET StackedBar Chart</title><link>http://ardalis.com:80/fixing-floating-rectangles-in-asp.net-stackedbar-chart</link><description>&lt;p&gt;In working on a client’s reporting system, I ran across some StackedBar charts that were using the System.Web.DataVisualization.Chart control that were having some problems.&amp;nbsp; The biggest one was that the rendered bars had gaps and floating rectangles in it.&amp;nbsp; This turned out to take about an hour to solve, using my best Google-fu, so I’m posting my solution and notes here, in case I run into it again and to save some other poor soul an hour’s time.&lt;/p&gt; &lt;h2&gt;The Problem&lt;/h2&gt; &lt;p&gt;Here’s what the chart looked like, originally.&amp;nbsp; &lt;/p&gt; &lt;p&gt;&lt;a href="http://ardalis.com/Media/Default/Windows-Live-Writer/Fixing-Floating-Rec.NET-StackedBar-Chart_C4DF/image_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Fixing-Floating-Rec.NET-StackedBar-Chart_C4DF/image_thumb.png" width="244" height="200"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;I’ll spare you the original code, as it was a total rat’s nest, but I was able to dramatically simplify it before proceeding to fix the actual issue.&amp;nbsp; A bit of searching led me to believe that the problem stemmed from not having the same number of datapoints for each X value.&amp;nbsp; You can actually dump the values of the chart data into an XML format pretty easily, using this command:&lt;/p&gt; &lt;p&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="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Fixing-Floating-Rec.NET-StackedBar-Chart_C4DF/image_5.png" width="489" height="53"&gt;&lt;/p&gt; &lt;p&gt;The resulting XML looked something like this:&lt;/p&gt; &lt;p&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="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Fixing-Floating-Rec.NET-StackedBar-Chart_C4DF/image_8.png" width="644" height="332"&gt;&lt;/p&gt;   &lt;p&gt;Clearly, there are two problems here.&amp;nbsp; The first one is that each series has a different number of data points.&amp;nbsp; The second is that the points are not in order by year.&amp;nbsp; You need to fix both of these problems in order to get the correct chart behavior.&lt;/p&gt; &lt;h2&gt;Adding Empty Data Points&lt;/h2&gt; &lt;p&gt;My first stab at adding empty data points was to use a method that seemed well-suited to the task:&lt;/p&gt; &lt;p&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="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Fixing-Floating-Rec.NET-StackedBar-Chart_C4DF/image_11.png" width="945" height="98"&gt;&lt;/p&gt; &lt;p&gt;Unfortunately, this didn’t fix the chart, and upon looking at my chart.xml data, it also didn’t add in any empty points.&amp;nbsp; I tried a few variations but couldn’t get it to work with my data.&amp;nbsp; Eventually I found a newsgroup posting with some code to do this by hand, which I ended up adapting to my needs:&lt;/p&gt; &lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #008000"&gt;//// now fix empty data points&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;var xVals = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; List&amp;lt;&lt;span style="color: #0000ff"&gt;double&lt;/span&gt;&amp;gt;();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (var series &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; Chart1.Series)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; series.Points.Count; i++)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; currentXValue = series.Points[i].XValue;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!xVals.Contains(currentXValue))&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            xVals.Add(currentXValue);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (var xVal &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; xVals)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (var series &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; Chart1.Series)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;try&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (series.Points.FindByValue(xVal, &lt;span style="color: #006080"&gt;"X"&lt;/span&gt;) == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;                series.Points.AddXY(xVal, 0);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;catch&lt;/span&gt; (Exception)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            series.Points.AddXY(xVal, 0);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&amp;nbsp;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (var series &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; Chart1.Series)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (var point &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; series.Points)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (point.YValues[0] == 0)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;            point.IsEmpty = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;        }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;br&gt;I’ll probably clean up this code further and move it into its own method (perhaps an extension method on Chart) in the future.&amp;nbsp; It’s not pretty, but it does the job.&amp;nbsp; With this in place, the resulting XML code looks like this:&lt;/p&gt;
&lt;p&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="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Fixing-Floating-Rec.NET-StackedBar-Chart_C4DF/image_14.png" width="644" height="386"&gt;&lt;/p&gt;
&lt;p&gt;The chart, however, is still broken.&lt;/p&gt;
&lt;h2&gt;Sorting the Points&lt;/h2&gt;
&lt;p&gt;The last step is to sort the points.&amp;nbsp; This is actually quite easy to do with the following bit of code:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (var series &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; Chart1.Series)&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;{&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    Chart1.DataManipulator.Sort(PointSortOrder.Ascending, &lt;span style="color: #006080"&gt;"X"&lt;/span&gt;, series);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;}&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;br&gt;With this in place, the resulting XML code looks like this:&lt;/p&gt;
&lt;p&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="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Fixing-Floating-Rec.NET-StackedBar-Chart_C4DF/image_17.png" width="644" height="383"&gt;&lt;/p&gt;
&lt;p&gt;and the chart looks like this:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ardalis.com/Media/Default/Windows-Live-Writer/Fixing-Floating-Rec.NET-StackedBar-Chart_C4DF/image_19.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Fixing-Floating-Rec.NET-StackedBar-Chart_C4DF/image_thumb_6.png" width="244" height="197"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;The charting controls available in the DataVisualization namespace are very powerful.&amp;nbsp; I hope this will help some folks who are trying to get their StackedColumn chart to display propertly.&amp;nbsp; Unfortunately, the documentation available from Microsoft directly on these controls is rather sparse.&amp;nbsp; Hopefully this will help others who are trying to use these charts (which, by the way, can certainly be used outside of ASP.NET – in my case they are being used to generate image files that are then merged into Word and PDF reports, not for display on web pages).&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/w2hgMySAPtcexBtS8NBvCK4VCfY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/w2hgMySAPtcexBtS8NBvCK4VCfY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/w2hgMySAPtcexBtS8NBvCK4VCfY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/w2hgMySAPtcexBtS8NBvCK4VCfY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=ZtS9XwwGD10:ojduSmE7Y-E:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=ZtS9XwwGD10:ojduSmE7Y-E:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=ZtS9XwwGD10:ojduSmE7Y-E:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=ZtS9XwwGD10:ojduSmE7Y-E:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=ZtS9XwwGD10:ojduSmE7Y-E:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=ZtS9XwwGD10:ojduSmE7Y-E:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StevenSmith/~4/ZtS9XwwGD10" height="1" width="1"/&gt;</description><pubDate>Thu, 09 Feb 2012 19:19:47 GMT</pubDate><guid isPermaLink="true">http://ardalis.com:80/fixing-floating-rectangles-in-asp.net-stackedbar-chart</guid></item><item><title>Team Workspace Reflections</title><link>http://ardalis.com:80/team-workspace-reflections</link><description>&lt;p&gt;&lt;a href="http://flic.kr/p/9igAWS"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 0px 5px 5px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" align="right" src="http://ardalis.com/Media/Default/Windows-Live-Writer/Team-Workspaces_8ACF/image_3.png" width="359" height="269"&gt;&lt;/a&gt;We’ve been fans of team rooms and collaborative work environments at &lt;a href="http://nimblepros.com/"&gt;NimblePros&lt;/a&gt; for some time.&amp;nbsp; In building out our new building, we took care to create several large open spaces to be used as team rooms, with plenty of room in the middle for workstations (configured for pair programming) and lots of open wall space around the outside for whiteboards and &lt;a href="http://alistair.cockburn.us/Information+radiator"&gt;information radiators&lt;/a&gt;.&amp;nbsp; You can see one of our team workspaces, before the furniture and whiteboards went in, on the right.&amp;nbsp; The idea was to follow the &lt;a href="http://c2.com/cgi/wiki?CaveAndCommons"&gt;Caves and Commons&lt;/a&gt; approach first recommended by Extreme Programming, and it’s worked very well.&amp;nbsp; We gave some of our senior staff their own office spaces and we set up a group “cave” with several desks in it where folks could go to take a phone call or work individually on a task, but almost a year after our move, some of the senior staff’s offices have been emptied out as they now spend their days in one of the team rooms, and the one “cave” room very rarely sees use (but it is nice to have when it is needed, so we consider it worthwhile space).&lt;/p&gt; &lt;p&gt;Today there’s been &lt;a href="http://tech.groups.yahoo.com/group/extremeprogramming/message/156931"&gt;a great thread on the Extreme Programming mailing list on this topic&lt;/a&gt;, and I thought a few of the quotes were worth sharing here:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;When I created my software R&amp;amp;D space some years ago, I ensured that every programmer had a private office with a window.&lt;br&gt;When we did some of our really difficult projects, we created a "war room" to work in. It went better.&lt;br&gt;&lt;br&gt;When XP was invented, we worked with everyone in a big room. No one on the team wanted to go back: we were all certain that it was the most productive and enjoyable project we had ever been on.&lt;br&gt;&lt;br&gt;I have worked with many teams since then, and the results have been the same. Except for a very few individuals -- who have never been considered to be key team members anyway -- teams have been more productive by their own measure, in a team room.&lt;br&gt;&lt;br&gt;I don't know what kind of rooms or projects these articles refer to, but I would never do a software project without the team in its own common space if I had any choice at all.&lt;br&gt;&lt;/em&gt;&lt;br&gt;&lt;a href="http://twitter.com/ronjeffries"&gt;Ron Jeffries&lt;/a&gt;&lt;br&gt;&lt;a href="http://www.XProgramming.com"&gt;www.XProgramming.com&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;This has been my experience as well.&amp;nbsp; Team rooms are simply more fun, more productive, and more energizing, provided everybody is working on the same project and is motivated.&amp;nbsp; As with anything, there can be problems, such as off-topic conversations distracting the team, but generally the team is able to self-police such things, at least in my experience.&amp;nbsp; Another quote from this thread, in response to Ron’s above: &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;My experience has been basically the same. Everyone wanted their private office until they tried the common space. Then they voted to give the offices to someone else. They had more fun, got more done, and in my opinion came up with far more creative answers...&lt;/em&gt; &lt;p&gt;Steve Ropa&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Now, if you’ve read &lt;a href="http://www.amazon.com/gp/product/0932633439/ref=as_li_ss_tl?ie=UTF8&amp;amp;tag=aspalliancecom&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=0932633439"&gt;Peopleware&lt;/a&gt;, it suggests that one of the biggest barriers to productivity is distracting sound, and that the best way to lower the amount of noise each worker has to put up with is to provide more space (and ideally, separate offices with doors) to each employee.&amp;nbsp; I’ve worked in organizations who had open floorplans larger than football fields filled with rows and rows of cubicles, and it’s precisely this arrangement that comes to mind when I think about the advice in Peopleware.&amp;nbsp; But I think there is a difference between legions of workers in cubicles working individually and small teams working collaboratively on a specific project.&amp;nbsp; When you’re pairing with someone in a team room, you’re able to focus on your work and what your partner is saying to the exclusion of the rest of the room.&amp;nbsp; However, you’re still half-listening to the conversation, so when someone else in the room says your name, or wonders why such-and-such class that you just checked in yesterday isn’t working, you hear it.&amp;nbsp; You can share vital information, instantly, that might otherwise have blocked your teammate until the next stand-up meeting (assuming you hold them). &lt;p&gt;Last year, at one of the &lt;a href="http://hudsonsc.com/"&gt;Hudson Software Craftsmanship group meetings&lt;/a&gt;, we had a discussion in which we talked about moving a team to agile.&amp;nbsp; To kick off that discussion, I asked the group to describe what an agile team would look like to an observer.&amp;nbsp; One of the first things that was mentioned was that they were working in a team room.&amp;nbsp; Now, I don’t think team rooms are strictly necessary in order for an agile team to be successful, but I do think they’re certainly helpful. &lt;p&gt;Have you had the opportunity to work on a project in a team room?&amp;nbsp; Do you agree with the ideas expressed above, or has your experience been different?&amp;nbsp; I’d love to hear from some people who have had negative experiences working in team rooms.&amp;nbsp; Please leave a comment if you have some experience to share.
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/lDayxuwSVGJ-AcRJseiH-SUdPp4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lDayxuwSVGJ-AcRJseiH-SUdPp4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/lDayxuwSVGJ-AcRJseiH-SUdPp4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lDayxuwSVGJ-AcRJseiH-SUdPp4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=BMAS3t1AtgQ:F7SN4JFvB_c:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=BMAS3t1AtgQ:F7SN4JFvB_c:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=BMAS3t1AtgQ:F7SN4JFvB_c:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=BMAS3t1AtgQ:F7SN4JFvB_c:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stevesmithblog.com/~ff/StevenSmith?a=BMAS3t1AtgQ:F7SN4JFvB_c:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StevenSmith?i=BMAS3t1AtgQ:F7SN4JFvB_c:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StevenSmith/~4/BMAS3t1AtgQ" height="1" width="1"/&gt;</description><pubDate>Wed, 08 Feb 2012 15:15:04 GMT</pubDate><guid isPermaLink="true">http://ardalis.com:80/team-workspace-reflections</guid></item></channel></rss>

