Jekyll2021-04-30T15:57:30+00:00https://matthidinger.com/feed.xmlMatt HidingerSailing and making.Matt HidingerVideo and code from my Build talk on Sharing Code between Platforms2013-07-02T00:00:00+00:002013-07-02T00:00:00+00:00https://matthidinger.com/archive/2013/07/02/video-and-code-from-my-build-talk-on-sharing-code<p><img src="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/b630e246904a_9C6D/buildconf_thumb.png" alt="buildconf" title="buildconf" /></p>
<p>Last week I had another incredible time at Microsoft’s annual <a href="https://www.buildwindows.com/">Build conference</a>. This year was particularly exciting for me, as I was invited to speak about some real-world experience on <a href="https://channel9.msdn.com/Events/Build/2013/2-215">Building Apps for both Windows and Windows Phone</a>.</p>
<blockquote>
<p>This talk is all about cutting to the chase: cross-platform development is challenging. It’s also increasingly a reality we must accept, embrace, and learn to take advantage of. By demonstrating a “real-world” app designed for Windows and Windows Phone, you will learn six battle-tested techniques for maximizing both code and skill reuse between multiple platforms.</p>
</blockquote>
<h2 id="get-the-code">Get the code</h2>
<p>If you enjoyed the talk and would like to check out the code for the Real-world Stocks apps that were built on stage, use the following Github link:</p>
<h4 id="httpsgithubcommatthidingerbuild2013realworldstocks"><a href="https://github.com/matthidinger/Build2013RealWorldStocks">https://github.com/matthidinger/Build2013RealWorldStocks</a></h4>
<p> </p>
<h2 id="introspective">Introspective</h2>
<p>This was my first talk at a major conference. It’s funny watching yourself on video for the first time; you certainly observe some habits to work on. I quickly realized that I was pacing a lot in the beginning, but thankfully my clicker started to die early on which virtually tethered me to the podium!</p>
<p>That said, any other feedback on the presentation would be greatly appreciated! Was the pace ok? I’ve already received feedback that I was both too fast, and too slow, so this will definitely vary depending on one’s own comfort level with the technologies discussed, but I’d love any additional comments.</p>
<p>Thanks for watching!</p>
<p> </p>Matt HidingerA Windows Phone Developer’s take on Xamarin2013-04-21T00:00:00+00:002013-04-21T00:00:00+00:00https://matthidinger.com/archive/2013/04/21/a-windows-phone-developerrsquos-take-on-xamarin<h2><a href="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/378d9bf4981b_91E1/WP_20130416_002_2.jpg"><img src="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/378d9bf4981b_91E1/WP_20130416_002_thumb.jpg" alt="WP_20130416_002" title="WP_20130416_002" /></a></h2>
<p><a href="https://xamarin.com/">Xamarin</a> is all the rage in mobile development right now. They just threw an <a href="https://xamarin.com/evolve">amazing conference</a> in Austin and started trending on Twitter during the opening keynote.</p>
<p>But I’ve identified myself as a Microsoft platform dev for years now, and Xamarin is all about iOS and Android. Why am I, and more importantly Microsoft, seemingly so interested in this product?</p>
<h2 id="xamarin">Xamarin</h2>
<p>If you haven’t been following along, Xamarin is a company that is now 22 months old, founded by <a href="https://twitter.com/migueldeicaza">Miguel de Icaza</a> and <a href="https://twitter.com/natfriedman">Nat Friedman</a>. Their product allows you to develop native iOS and Android apps using the most wonderful language of all time: C#.</p>
<p>Their toolset, among other things, lets you use Visual Studio to build these apps, offering rich designer experiences, and even let you compile iOS apps using Windows thanks to some neat remoting technology.</p>
<h2 id="evolve-conference">Evolve Conference</h2>
<p>Last week they threw their very first conference, and it was a truly impressive feat. A giant stage, exciting keynotes, new product announcements, live recordings of all sessions, and amazing one-on-one support with Xamarin engineers. Oh and one of the most friendly and helpful communities I’ve ever been a part of.</p>
<p>What more could you ask for? <a href="https://twitter.com/MattHidinger/status/324305594494373888">Parties</a>? <a href="https://twitter.com/MattHidinger/status/324380618714644481">After-parties</a>? They had those too.</p>
<h2 id="the-windows-angle">The Windows angle</h2>
<p>Ok so they throw a great conference and have some impressive tooling for building iOS and Android apps. But Microsoft was a platinum sponsor of the Evolve conference. I also ran into 8 or 9 Microsoft employees while there. This puzzled a lot of people.</p>
<p>Why would Microsoft show interest in a platform designed to sell licenses for developing software on competing platforms?</p>
<h3 id="an-analogy-is-in-order">An analogy is in order.</h3>
<p><a href="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/378d9bf4981b_91E1/WP_20130416_010_4.jpg"><img src="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/378d9bf4981b_91E1/WP_20130416_010_thumb_1.jpg" alt="WP_20130416_010" title="WP_20130416_010" /></a></p>
<p>Take the image to the left. The bar at the conference was serving cocktails named iOS, Android, and Windows. The drinks were colored according to the platform. It was a fun idea.</p>
<p>What’s the primary ingredient in all of these drinks? Vodka.</p>
<h3 id="the-vodka-is-xamarin-the-shared-language-the-shared-tools-the-shared-core">The Vodka is Xamarin. The shared language, the shared tools, the shared core.</h3>
<p>The rest of the drink-specific ingredients? Those are the UX, animations, and native platform APIs.</p>
<p>If architected properly, as described by a few talks at the conference, these other ingredients can be quite small comparatively. And these ingredients are focused on delighting the user, not porting all of your HTTP interfaces, models, logging, and generic business logic. The fun stuff; not the laborious, time consuming monotony.</p>
<h3 id="windows-phone-needs-a-genuine-app-infusion">Windows Phone needs a genuine app infusion.</h3>
<p>Microsoft has made decent headway getting the “top 50” apps onto the platform. But what about the top 500? What about getting them in a timely manner relative to other platforms?</p>
<p>The chain reaction the platform needs will start with <em>genuine developer interest</em>, and without market-share numbers the only business drive to supporting Windows Phone will come from <em>lowering cost and effort</em>.</p>
<h3 id="xamarin-offers-that-lower-costeffort">Xamarin offers that lower cost/effort.</h3>
<p>In my humble opinion, Microsoft should be promoting Xamarin developers every chance it gets.</p>
<p>The more iOS apps written in C#, the more apps can be ported to Windows at a significantly lower cost. The developers will already know the language, they know the IDE, they know the .NET BCL. They most likely just need to learn XAML, and the Windows application lifecycle, which is very similar to the other platforms anyway.</p>
<h2 id="its-a-cross-platform-world">It’s a cross-platform world</h2>
<p>This is obvious to anyone working in the mobile space, but the idea of 95% market-share of a single client-platform is a thing of the past. Rocky Lhotka had a great article on the <a href="https://www.lhotka.net/weblog/FutureOfTheSmartClient.aspx">future of the smart client</a> and what this means for developers, although we may differ on which language could take us to that future.</p>
<p>The one thing we all agree on: this is going to be a fun ride.</p>
<h3 id="so-lets-all-enjoy-a-xammy-whammy">So let’s all enjoy a xammy whammy</h3>
<p>I’d like to wrap-up with a special thanks the entire Xamarin community, I met a ton of great people and definitely look forward to seeing everyone next year! And of course a huge thanks to <a href="https://twitter.com/she_travels">Stephanie Schatz</a>, <a href="https://twitter.com/epolzin">Erik Polzin</a>, and <a href="https://twitter.com/anooj">Anuj Bhatia</a> for the warm welcome and great conversations throughout the week.</p>
<p>See you all at BUILD 2013!</p>
<p> </p>Matt HidingerSharing Code: Windows 8 and Windows Phone2012-12-05T00:00:00+00:002012-12-05T00:00:00+00:00https://matthidinger.com/archive/2012/12/05/sharing-code-windows-8-and-windows-phone<p>I recently had the opportunity to speak at Microsoft’s <a href="https://www.microsoft.com/enterprise/events/theneweraofwork3/#fbid=7bLqKFFM2kc">New Era of Work</a> conference in Chicago. Below you’ll find the presentation material, the Real-World Stocks project which demonstrates the principles, and a high-level recap of the lessons learned while practicing the following techniques in actual apps.</p>
<p><img src="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/Sharing-Code-Windows-8-and-Windows-Phone_83EC/image_thumb_3.png" alt="" />
<img src="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/Sharing-Code-Windows-8-and-Windows-Phone_83EC/screenshot_12052012_110659_thumb.png" alt="" /></p>
<hr />
<h2 id="slides">Slides</h2>
<p>A number of slides were provided by Microsoft, and many specifically from <a href="https://twitter.com/matthiasshap">Matthias Shapiro</a>. Be sure to check out <a href="https://matthiasshapiro.com/">his blog</a> for more excellent Windows Phone articles!</p>
<table>
<thead>
<tr>
<th> </th>
<th> </th>
</tr>
</thead>
<tbody>
<tr>
<td><img src="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/Sharing-Code-Windows-8-and-Windows-Phone_83EC/WP_20121128_001_thumb.jpg" alt="" /></td>
<td> </td>
</tr>
<tr>
<td> </td>
<td> </td>
</tr>
</tbody>
</table>
<p> </p>
<h2 id="source">source</h2>
<table>
<colgroup>
<col width="50%" />
<col width="50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><a href="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/Sharing-Code-Windows-8-and-Windows-Phone_83EC/image_6.png"><img src="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/Sharing-Code-Windows-8-and-Windows-Phone_83EC/image_thumb_2.png" title="image" alt="image" width="202" height="354" /></a></td>
<td><p>For this talk I started with my <a href="https://www.matthidinger.com/archive/2011/10/16/RealWorldWPDev-Part-1-Introduction-and-Outline.aspx">Real-World Stocks Windows Phone</a> project, extracted the central logic into a Portable Class Library, and used File-Linking to share Controls and Converters between the two projects.</p>
<p>The full source code for Real-World Stocks can be downloaded at the following link, inside a new folder named <strong>CodeSharingSample</strong>.</p>
<a href="https://realworldstocks.codeplex.com/" title="https://realworldstocks.codeplex.com/"><br />
https://realworldstocks.codeplex.com/</a><br />
<br />
<p><br />
For my mercurial fans…</p>
<br />
hg clone https://hg.codeplex.com/realworldstocks</td>
</tr>
</tbody>
</table>
<h2 id="recap-the-six-techniques-of-sharing">Recap: the six techniques of sharing</h2>
<p>Sharing code is getting easier, but like all things, there is no silver bullet. Below are six techniques I’ve used in every app I’ve shared code between – you will very likely use a combination of all of them in a single solution.</p>
<h4> </h4>
<h4 id="ctrl-c-ctrl-v">Ctrl-C, Ctrl-V</h4>
<p>The tried and true technique for sharing code. Simple, elegant, and a potential maintenance nightmare.</p>
<p>Copy/pasting files is still very useful for sharing some XAML across platforms. It will let you copy the XAML as a starting point, and tweak it to look best on the alternate platform. The obvious trade-off being that these files are no way associated, so any tweaks to the XAML in the future will need to be made in both places.</p>
<h4 id="-1"> </h4>
<h4 id="linked-files">Linked Files</h4>
<p>Sometimes you need to share a raw .cs file between projects. You can copy/paste the file or use <em>Add Existing Item,</em> but this will create a duplicate file on disk, so any changes made in the future will need to be copy/pasted again. **</p>
<p><em>Linking</em> source files between projects will come in very handy when you want to share a custom Control, or maybe a handful of custom Converters. Since Linked Files are still the same file on disk, any change made in one will be persisted between all projects.</p>
<p><strong>Pro tip:</strong> Finally in VS 2012, you can hold the Left-Alt key and drag entire folders between projects… It will Add a Link for every file inside the folder!</p>
<p><img src="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/Sharing-Code-Windows-8-and-Windows-Phone_83EC/image_thumb_1.png" alt="" /></p>
<h4 id="-2"> </h4>
<h4 id="linked-files-enhanced-with-if-blocks">Linked Files enhanced with #if blocks</h4>
<p>Sometimes your Linked Files won’t immediately compile on both platforms.</p>
<p>A very common nuisance is when accessibility modifier are different. For example, sharing a custom Control I wrote for Real-World Stocks: in Silverlight the method signature for <em>OnApplyTemplate</em> <em>**</em> is <em>public;</em> in Windows it’s marked <em>protected</em>. To work around this I had to write a rather silly #if block to tweak how this code will be compiled, depending on which platform it’s compiling on.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">namespace</span> <span class="nn">RealWorldStocks.UI.Phone.Controls</span>
<span class="p">{</span>
<span class="p">[</span><span class="nf">TemplateVisualState</span><span class="p">(</span><span class="n">Name</span> <span class="p">=</span> <span class="s">"Positive"</span><span class="p">,</span> <span class="n">GroupName</span> <span class="p">=</span> <span class="s">"PriceStates"</span><span class="p">)]</span>
<span class="p">[</span><span class="nf">TemplateVisualState</span><span class="p">(</span><span class="n">Name</span> <span class="p">=</span> <span class="s">"Negative"</span><span class="p">,</span> <span class="n">GroupName</span> <span class="p">=</span> <span class="s">"PriceStates"</span><span class="p">)]</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">PriceChangeArrow</span> <span class="p">:</span> <span class="n">Control</span>
<span class="p">{</span>
<span class="k">public</span> <span class="nf">PriceChangeArrow</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">DefaultStyleKey</span> <span class="p">=</span> <span class="k">typeof</span> <span class="p">(</span><span class="n">PriceChangeArrow</span><span class="p">);</span>
<span class="p">}</span>
<span class="cp">#if NETFX_CORE
</span> <span class="k">protected</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">OnApplyTemplate</span><span class="p">()</span>
<span class="cp">#else
</span> <span class="k">public</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">OnApplyTemplate</span><span class="p">()</span>
<span class="cp">#endif
</span> <span class="p">{</span>
<span class="n">LayoutUpdated</span> <span class="p">+=</span> <span class="n">PriceChangeArrow_LayoutUpdated</span><span class="p">;</span>
<span class="k">base</span><span class="p">.</span><span class="nf">OnApplyTemplate</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<h4 id="-3"> </h4>
<h4 id="portable-class-libraries-pcls">Portable Class Libraries (PCLs)</h4>
<p>When you want to move away from sharing raw source assets you will want to check out PCLs.</p>
<p>When you Add –> New Project and select a Portable Class Library, you will see the following dialog, allowing you to specify exactly which platforms you’d like to target. IntelliSense and the tooling will only surface APIs which are common across all chosen platforms.</p>
<p>Your end result is a single project, with a single codebase, <em>outputting a single assembly</em> (.dll) that is able to be referenced by any of the targeted platforms.</p>
<p><img src="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/Sharing-Code-Windows-8-and-Windows-Phone_83EC/image_thumb_5.png" alt="" /></p>
<p> </p>
<h4 id="a-platform-adapter-abstraction">A Platform Adapter Abstraction</h4>
<p>PCLs are excellent tools, but not all .NET APIs are currently available to them.</p>
<p>Suppose you want to write a shared HTTP stack in your PCL, which will certainly need the ability to do GZip decompression. Unfortunately you realize the PCL has no GZipStream type. To solve this, I create an abstract class named <em>PlatformAdapter</em>, which has a static property to access the <em>Current</em> instance. Each platform is then responsible for implementing a concrete platform adapter to provide the implementation <strong>and</strong> initialize the Current property on startup.</p>
<p><em>Download the full sample project to see how these pieces fit together.</em></p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">namespace</span> <span class="nn">RealWorldStocks.Core</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">abstract</span> <span class="k">class</span> <span class="nc">PlatformAdapter</span>
<span class="p">{</span>
<span class="c1">/// <summary></span>
<span class="c1">/// Provides acess to the current platform adapter</span>
<span class="c1">/// </summary></span>
<span class="k">public</span> <span class="k">static</span> <span class="n">PlatformAdapter</span> <span class="n">Current</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="k">abstract</span> <span class="kt">string</span> <span class="nf">ReadCompressedResponseStream</span><span class="p">(</span><span class="n">HttpWebResponse</span> <span class="n">response</span><span class="p">);</span>
<span class="k">public</span> <span class="k">abstract</span> <span class="k">void</span> <span class="nf">BeginInvoke</span><span class="p">(</span><span class="n">Action</span> <span class="n">actionToInvoke</span><span class="p">);</span>
<span class="k">public</span> <span class="k">abstract</span> <span class="n">ISettingsStore</span> <span class="n">Settings</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>####
Your skills – it’s not always about sharing raw assets</p>
<p>Lastly, and arguably the biggest thing worth sharing: your skills.</p>
<p>You know C#. You know .NET. You know (and love) XAML. These skills will you get a huge head-start, specifically on the XAML stacks. They aren’t 100% identical, as seen above, but the overarching concepts are exactly the same.</p>
<p>###</p>
<h1 id="finally-above-all-else">Finally, above all else…</h1>
<h2 id="make-a-great-user-experience">Make a great user experience!</h2>
<p>Sharing code, assets, and skills are all great tools for more efficient software delivery. Just don’t forget that you are creating software for different platforms, and the user should always have the optimal experience on each. Not every screen is going to show the same data, in the same way.</p>
<p><img src="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/Sharing-Code-Windows-8-and-Windows-Phone_83EC/image_thumb_6.png" alt="" /></p>
<p> </p>Matt HidingerI recently had the opportunity to speak at Microsoft’s New Era of Work conference in Chicago. Below you’ll find the presentation material, the Real-World Stocks project which demonstrates the principles, and a high-level recap of the lessons learned while practicing the following techniques in actual apps.How to get the Windows Phone user agent string2012-07-05T00:00:00+00:002012-07-05T00:00:00+00:00https://matthidinger.com/archive/2012/07/05/how-to-get-the-windows-phone-user-agent-string<p><img src="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/45d9f34867d2_B652/IE_thumb.png" alt="" /></p>
<p>On a recent project I needed to extract the <a href="https://windowsteamblog.com/windows_phone/b/wpdev/archive/2011/08/29/introducing-the-ie9-on-windows-phone-mango-user-agent-string.aspx">windows phone user-agent string</a> for our usage analytics, and it had to be the same user-agent as the IE requests. While this didn’t end up being as straight forward and I had hoped, the code below involves a few simple steps. First we have to insert a collapsed browser onto the page, then we can navigate it to specifically crafted HTML/JavaScript, which will in-turn notify the WebBrowser control of it’s user-agent. All you need to do is store it somewhere; in my case, I put it into a custom ApplicationSettings class, but you can store it anywhere you want.</p>
<h3 id="usage">Usage</h3>
<p>Since this code requires adding a WebBrowser control to a page, it’s probably easier to do in code-behind as opposed to a view model.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">partial</span> <span class="k">class</span> <span class="nc">HomeView</span> <span class="p">:</span> <span class="n">PhoneApplicationPage</span>
<span class="p">{</span>
<span class="k">public</span> <span class="nf">HomeView</span><span class="p">()</span>
<span class="p">{</span>
<span class="nf">InitializeComponent</span><span class="p">();</span>
<span class="n">Loaded</span> <span class="p">+=</span> <span class="n">HomeView_Loaded</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">private</span> <span class="k">void</span> <span class="nf">HomeView_Loaded</span><span class="p">(</span><span class="kt">object</span> <span class="n">sender</span><span class="p">,</span> <span class="n">RoutedEventArgs</span> <span class="n">e</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">UserAgentHelper</span><span class="p">.</span><span class="nf">GetUserAgent</span><span class="p">(</span>
<span class="n">LayoutRoot</span><span class="p">,</span>
<span class="n">userAgent</span> <span class="p">=></span>
<span class="p">{</span>
<span class="c1">// TODO: Store this wherever you want</span>
<span class="n">ApplicationSettings</span><span class="p">.</span><span class="n">Current</span><span class="p">.</span><span class="n">UserAgent</span> <span class="p">=</span> <span class="n">userAgent</span><span class="p">;</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="the-helper">The Helper</h3>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">UserAgentHelper</span>
<span class="p">{</span>
<span class="k">private</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">Html</span> <span class="p">=</span>
<span class="s">@"<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.01 Transitional//EN"">
<html>
<head>
<script language=""javascript"" type=""text/javascript"">
function notifyUA() {
window.external.notify(navigator.userAgent);
}
</script>
</head>
<body onload=""notifyUA();""></body>
</html>"</span><span class="p">;</span>
<span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">GetUserAgent</span><span class="p">(</span><span class="n">Panel</span> <span class="n">rootElement</span><span class="p">,</span> <span class="n">Action</span><span class="p"><</span><span class="kt">string</span><span class="p">></span> <span class="n">callback</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">browser</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Microsoft</span><span class="p">.</span><span class="n">Phone</span><span class="p">.</span><span class="n">Controls</span><span class="p">.</span><span class="nf">WebBrowser</span><span class="p">();</span>
<span class="n">browser</span><span class="p">.</span><span class="n">IsScriptEnabled</span> <span class="p">=</span> <span class="k">true</span><span class="p">;</span>
<span class="n">browser</span><span class="p">.</span><span class="n">Visibility</span> <span class="p">=</span> <span class="n">Visibility</span><span class="p">.</span><span class="n">Collapsed</span><span class="p">;</span>
<span class="n">browser</span><span class="p">.</span><span class="n">Loaded</span> <span class="p">+=</span> <span class="p">(</span><span class="n">sender</span><span class="p">,</span> <span class="n">args</span><span class="p">)</span> <span class="p">=></span> <span class="n">browser</span><span class="p">.</span><span class="nf">NavigateToString</span><span class="p">(</span><span class="n">Html</span><span class="p">);</span>
<span class="n">browser</span><span class="p">.</span><span class="n">ScriptNotify</span> <span class="p">+=</span> <span class="p">(</span><span class="n">sender</span><span class="p">,</span> <span class="n">args</span><span class="p">)</span> <span class="p">=></span>
<span class="p">{</span>
<span class="kt">string</span> <span class="n">userAgent</span> <span class="p">=</span> <span class="n">args</span><span class="p">.</span><span class="n">Value</span><span class="p">;</span>
<span class="n">rootElement</span><span class="p">.</span><span class="n">Children</span><span class="p">.</span><span class="nf">Remove</span><span class="p">(</span><span class="n">browser</span><span class="p">);</span>
<span class="nf">callback</span><span class="p">(</span><span class="n">userAgent</span><span class="p">);</span>
<span class="p">};</span>
<span class="n">rootElement</span><span class="p">.</span><span class="n">Children</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">browser</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p> </p>Matt HidingerA simple IndexingObservableCollection for zebra-striping rows2012-07-02T00:00:00+00:002012-07-02T00:00:00+00:00https://matthidinger.com/archive/2012/07/02/a-simple-indexingobservablecollection-for-zebra-striping-rows<p><img src="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/58c4cfa70f46_956D/zebra-camo_thumb.jpg" alt="" /></p>
<p>I’m currently wrapping up a Windows Phone project and thought this would be a good time to share some of the more reusable stuff we needed.</p>
<h3 id="zebra-striping-alternate-rows">Zebra-striping alternate rows</h3>
<p>This particular app displays a lot of tabular data, so we wanted to zebra-stripe the rows to make them easier to discern. At first we tried using a ValueConverter to get the index of the current container, but this method didn’t end up working with the <a href="https://www.telerik.com/products/windows-phone/overview/all-controls.aspx#databoundlistbox">Telerik DataBoundListBox</a>.</p>
<p>Instead, we wrote a simple IndexingObservableCollection that will automatically populate the Index of each item as it’s added to the collection. This method also works with the <a href="https://www.telerik.com/help/windows-phone/raddataboundlistbox-features-datavirtualization-overview.html">infinite scrolling feature of Telerik’s listbox</a> – which we actually needed anyway.</p>
<h3 id="indexingobservablecollection">IndexingObservableCollection</h3>
<p>To use it, you have to implement the IIndexable interface which ensure an Index property on your model. Then simply replace the ObservableCollection property on your view-model with the following IndexingObservableCollection.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">IndexingObservableCollection</span><span class="p"><</span><span class="n">T</span><span class="p">></span> <span class="p">:</span> <span class="n">ObservableCollection</span><span class="p"><</span><span class="n">T</span><span class="p">></span> <span class="k">where</span> <span class="n">T</span> <span class="p">:</span> <span class="n">IIndexable</span>
<span class="p">{</span>
<span class="k">protected</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">InsertItem</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">,</span> <span class="n">T</span> <span class="n">item</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">item</span><span class="p">.</span><span class="n">Index</span> <span class="p">=</span> <span class="n">index</span><span class="p">;</span>
<span class="k">base</span><span class="p">.</span><span class="nf">InsertItem</span><span class="p">(</span><span class="n">index</span><span class="p">,</span> <span class="n">item</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">protected</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">SetItem</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">,</span> <span class="n">T</span> <span class="n">item</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">item</span><span class="p">.</span><span class="n">Index</span> <span class="p">=</span> <span class="n">index</span><span class="p">;</span>
<span class="k">base</span><span class="p">.</span><span class="nf">SetItem</span><span class="p">(</span><span class="n">index</span><span class="p">,</span> <span class="n">item</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">interface</span> <span class="nc">IIndexable</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">Index</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p> </p>
<h3 id="tweaking-your-model">Tweaking your model</h3>
<p>Below is a sample model that could be used for displaying a list of products. In this case I’m returning a specific Brush for odd-numbered rows, and the XAML Grid simply binds Background=”{Binding Background}”</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err"> </span>
</code></pre></div></div>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">ProductRow</span> <span class="p">:</span> <span class="n">IIndexable</span>
<span class="p">{</span>
<span class="k">public</span> <span class="kt">int</span> <span class="n">Index</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">ProductName</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Price</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="n">Brush</span> <span class="n">Background</span>
<span class="p">{</span>
<span class="k">get</span>
<span class="p">{</span>
<span class="k">return</span> <span class="n">Index</span> <span class="p">%</span> <span class="m">2</span> <span class="p">==</span> <span class="m">1</span>
<span class="p">?</span> <span class="k">new</span> <span class="nf">SolidColorBrush</span><span class="p">(</span><span class="n">Colors</span><span class="p">.</span><span class="n">DarkGray</span><span class="p">)</span>
<span class="p">:</span> <span class="k">new</span> <span class="nf">SolidColorBrush</span><span class="p">(</span><span class="n">Colors</span><span class="p">.</span><span class="n">White</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p> </p>Matt HidingerWindyCityGo, StirTrek, Windows 8 Anchor2012-05-06T00:00:00+00:002012-05-06T00:00:00+00:00https://matthidinger.com/archive/2012/05/06/windycitygo-stirtrek-windows-8-anchor<h3 id="this-blog-is-quiet-too-quiet">This blog is quiet… too quiet.</h3>
<p>It’s been a busy couple of months since starting at <a href="https://claritycon.com/">Clarity</a> in January. PowerPoint, for better or worse, became my after-hours IDE. Below you will find some of the recent talks accompanied by their slides and code. Hopefully I didn’t forget anything, but please shoot me a comment if I did!</p>
<h3 id="windycitygo">WindyCityGo</h3>
<h4 id="apr-5--6-2012">Apr 5 – 6, 2012</h4>
<p><a href="https://windycitygo.org/">WindyCityGo</a> is a two-day conference in Chicago that covers all things mobile.</p>
<p>This year they added Windows Phone to their lineup and I was invited to speak on “Real World Windows Phone Development.” My talk covered an intro to metro and supports my <a href="https://www.matthidinger.com/archive/2011/10/16/RealWorldWPDev-Part-1-Introduction-and-Outline.aspx">tutorial series on building a polished Stocks app for windows phone</a>.</p>
<p>And now that my speaking gigs are winding down I can finally get back to that series!</p>
<h4 id="get-the-code"><a href="https://realworldstocks.codeplex.com/">GET THE CODE</a></h4>
<table>
<colgroup>
<col width="50%" />
<col width="50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><p></p></td>
<td><a href="https://windycitygo.org/"><img src="https://lh4.googleusercontent.com/-PQvNSqMlV8s/T4_NVSoBhrI/AAAAAAAAORk/twmdX24iHG4/s839/2012_WindyCityGo_0170.jpg" width="486" height="325" /></a></td>
</tr>
</tbody>
</table>
<p> </p>
<h3 id="windows-8-anchor-at-navy-pier">Windows 8 Anchor at Navy Pier</h3>
<h4 id="apr-26-2012">Apr 26, 2012</h4>
<p>This event was put on by Microsoft to help get our excellent mid-west developers ready for Windows 8.</p>
<p>Since Clarity had been using the consumer preview tools to build a few metro-style apps already, <a href="https://twitter.com/#!/eklimcz">Erik Klimczak</a> and I were invited to talk about “Windows 8 from the Trenches.” We really wanted to cover our experience from three perspectives: business, design, and development.</p>
<p>Overall this was a very exciting event with nearly 400 people eager to see what’s coming with windows 8 and this new metro design language.</p>
<table>
<thead>
<tr>
<th> </th>
<th> </th>
</tr>
</thead>
<tbody>
<tr>
<td> </td>
<td><img src="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/9e7703fc2670_A43F/eventPics3_thumb.png" alt="" /></td>
</tr>
<tr>
<td> </td>
<td> </td>
</tr>
</tbody>
</table>
<h3> </h3>
<h3 id="stirtrek">StirTrek</h3>
<h4 id="may-4-2012">May 4, 2012</h4>
<p><a href="https://stirtrek.com/">StirTrek</a> is one of the coolest conferences I’ve been to so far. My buddy <a href="https://csell.net">Clark Sell</a> and I flew out to Columbus for the one-day event that takes place at a movie theater. This was StirTrek’s fourth year and they impressively sold out 1,000 tickets in under 10 minutes.</p>
<p>My talk was on “WinJS for C# Developers” where I gave a crash course into JavaScript development from a C# perspective. I ended up building a Stocks app on stage, on one of the worst market days in recent memory. It always makes for a good demo to show people how much money they are losing!</p>
<p>That said, thankfully I did not have to compete with Scott Hansleman in my time slot. My condolences for those who did!</p>
<h4 id="get-the-code-1"><a href="https://realworldstocks.codeplex.com/">GET THE CODE</a></h4>
<table>
<thead>
<tr>
<th> </th>
<th> </th>
</tr>
</thead>
<tbody>
<tr>
<td> </td>
<td><img src="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/9e7703fc2670_A43F/389594_10150889640849224_546684223_11989723_2067556539_n%5B1%5D_thumb.jpg" alt="" /></td>
</tr>
<tr>
<td> </td>
<td> </td>
</tr>
</tbody>
</table>
<h3 id="-1"> </h3>
<h3 id="thatconference">ThatConference</h3>
<h4 id="aug-13--15-2012">Aug 13 – 15, 2012</h4>
<p><img src="https://www.thatconference.com/Images/SiteBadges/440w.jpg?s=badge" alt="" />
This one is coming up soon and I’m really pumped for it. Be sure to check it out, registration should open soon!</p>
<blockquote>
<p>Spend <strong>3</strong> days, with <strong>1000</strong> of your fellow campers in <strong>125</strong> sessions geeking out on everything <strong>Mobile, Web</strong> and <strong>Cloud</strong> at a giant waterpark.</p>
</blockquote>
<p>With over <a href="https://thatconference.com/Sessions">125 sessions</a> to choose from, your head will eventually start to overheat. Cool off in one of the many nearby pools, because unlike your traditional technology conference, you will be camping at a giant indoor waterpark. Be sure to follow us on <a href="https://twitter.com/thatConference/">twitter</a> and check us out on <a href="https://facebook.com/thatconference/">facebook</a>. Then start practicing your cannon balls.</p>
<p> </p>Matt HidingerThis blog is quiet… too quiet.A Smarter Infrastructure: Automatically filtering an EF 4.1 DbSet2012-01-25T00:00:00+00:002012-01-25T00:00:00+00:00https://matthidinger.com/archive/2012/01/25/a-smarter-infrastructure-automatically-filtering-an-ef-4-1-dbset<p>If you <del>drink from the fire hose</del> read <a href="https://ayende.com/blog">Ayende’s blog</a> you would notice a lot of <a href="https://ayende.com/blog/search?q=repository+pattern">Anti-Repository talk</a> over the past couple years – which I fully agree with.</p>
<p>Back in 2009 he declared <a href="https://ayende.com/blog/3955/repository-is-the-new-singleton">repository is the new singleton</a>, stating:</p>
<blockquote>
<p>My current approach for data access now is:</p>
<ul>
<li>When using a database, use NHibernate’s ISession directly</li>
<li>Encapsulate complex queries into query objects that construct an ICriteria query that I can get and manipulate further</li>
<li>When using something other than a database, create a DAO for that, respecting the underlying storage implementation</li>
<li>Don’t try to <a href="https://davybrion.com/blog/2009/04/educate-developers-instead-of-protecting-them/">protect developers</a></li>
</ul>
</blockquote>
<p>Naturally he gets a slew of comments asking how he handles certain scenarios without using the repository abstraction. One such question, <a href="https://ayende.com/blog/153702/ask-ayende-handling-filtering">asked just today is</a>:</p>
<blockquote>
<p>With regards to my queries against repositories, Matt <a href="https://ayende.com/blog/153058/northwind-starter-kit-review-data-access-review-thoughts?key=852c1fa5de554460b9a8b4fbc2e2843a#comment4">asks</a>:</p>
<p>…if my aggregate root query should exclude entities that have, for example, and IsActive = false flag, I also don’t want to repeatedly exclude the IsActive = false entities. Using the repository pattern I can expose my Get method where internally it ALWAYS does this.</p>
</blockquote>
<p>Ayende responds by stating that the additional abstraction is not necessary; one can simply rely on making a smarter infrastructure. Since he briefly describes how he would solve it using NHibernate, I figured I would also explain how I solve it using EF 4.1 code-first.</p>
<h2 id="a-life-without-repositories">A life without repositories</h2>
<p>Like Ayende, I prefer to access my ORM abstraction directly (NHibernate has <strong>ISession</strong>; I create a single <strong>IDataContext</strong>). Rather than having separate Repositories for each aggregate root I am able to access all of them directly from the IDataContext.</p>
<h3 id="using-the-idatacontext">Using the IDataContext</h3>
<p>Here is a typical controller with constructor injection to obtain an IDataContext.</p>
<p>The Categories table has 3 rows in it, but one of them has IsDeleted set to true. If you were to execute the following query, you would see that only 2 of the rows are returned.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">EFController</span> <span class="p">:</span> <span class="n">Controller</span>
<span class="p">{</span>
<span class="k">private</span> <span class="k">readonly</span> <span class="n">IDataContext</span> <span class="n">_db</span><span class="p">;</span>
<span class="k">public</span> <span class="nf">EFController</span><span class="p">(</span><span class="n">IDataContext</span> <span class="n">db</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">_db</span> <span class="p">=</span> <span class="n">db</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="n">ActionResult</span> <span class="nf">Index</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">// _db.Categories will only return categories where IsDeleted == false</span>
<span class="kt">var</span> <span class="n">categories</span> <span class="p">=</span> <span class="n">_db</span><span class="p">.</span><span class="n">Categories</span><span class="p">;</span>
<span class="k">return</span> <span class="nf">Content</span><span class="p">(</span><span class="kt">string</span><span class="p">.</span><span class="nf">Format</span><span class="p">(</span><span class="s">"Found {0} active categories"</span><span class="p">,</span> <span class="n">categories</span><span class="p">.</span><span class="nf">Count</span><span class="p">()));</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>To prove it, here is the SQL Profiler output when I hit the controller from a browser.</p>
<p><img src="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/Smarter-Infrastructure-Autom.1-DbContext_AA28/SNAGHTML3d115fad_thumb.png" alt="" /></p>
<h3 id="creating-the-idatacontext">Creating the IDataContext</h3>
<p>Now let me show you what the IDataContext looks like. It’s pretty simple. Each of the properties are of type IDbSet<T> and not IList<T>, which would commonly be found in a repository abstraction.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">interface</span> <span class="nc">IDataContext</span>
<span class="p">{</span>
<span class="n">IDbSet</span><span class="p"><</span><span class="n">Category</span><span class="p">></span> <span class="n">Categories</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="n">IDbSet</span><span class="p"><</span><span class="n">Product</span><span class="p">></span> <span class="n">Products</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<h4 id="omg-youre-spreading-ef-throughout-your-entire-app">“OMG you’re spreading EF throughout your entire app!”</h4>
<p>IDbSet comes from EntityFramework.dll. This means that anyone who uses the IDataContext will have some (small) knowledge of Entity Framework. Some developers are very concerned over this architectural dependency.</p>
<p>My argument is that Entity Framework, like any popular ORM, is <strong>already</strong> an abstraction over your database. It will take care of translating your needs into the appropriate SQL depending on the underlying store (MSSQL, Oracle, etc). As a firm believer in YAGNI, I highly doubt I will need to swap out my entire data access layer some day down the road, so why should I introduce architectural complexity for something that will very likely never come up? And even if it somehow does, I don’t know of a single instance where an application has been able to seamlessly swap completely different data stores (like going from SQL Server to RavebDB), without redesign, significant code re-write, and re-testing.</p>
<h3 id="implementing-the-idatacontext-and-adding-filtering-into-our-infrastructure">Implementing the IDataContext (and adding filtering into our infrastructure)</h3>
<p>Below is our concrete data context. It inherits from DbContext (From EF) and implements the interface we created. EF will automatically initialize the DbSet properties for us (as in the case of Products below), but we could also initialize it ourselves (as in the case of Categories).</p>
<p>Using this <a href="https://stackoverflow.com/questions/5676280/can-a-dbcontext-enforce-a-filter-policy">answer from StackOverflow</a> I found a great implementation of IDbSet called <strong>FilteredDbSet</strong>, which takes an Expression in the constructor to represent a WHERE clause. This WHERE clause will be automatically added to every query against the Categories property (and of course, translated all the way to SQL).</p>
<p>Since consumers of the IDataContext are only ever working with IDbSet, they have no idea that this automatic filtering is taking place behind the scenes. Hooray: a smarter infrastructure.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">ECommerceDb</span> <span class="p">:</span> <span class="n">DbContext</span><span class="p">,</span> <span class="n">IDataContext</span>
<span class="p">{</span>
<span class="k">public</span> <span class="nf">ECommerceDb</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">// Automatically filter out Categories where IsDeleted == false</span>
<span class="n">Categories</span> <span class="p">=</span> <span class="k">new</span> <span class="n">FilteredDbSet</span><span class="p"><</span><span class="n">Category</span><span class="p">>(</span><span class="k">this</span><span class="p">,</span> <span class="n">c</span> <span class="p">=></span> <span class="n">c</span><span class="p">.</span><span class="n">IsDeleted</span> <span class="p">==</span> <span class="k">false</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">public</span> <span class="n">IDbSet</span><span class="p"><</span><span class="n">Category</span><span class="p">></span> <span class="n">Categories</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="n">IDbSet</span><span class="p"><</span><span class="n">Product</span><span class="p">></span> <span class="n">Products</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="what-about-unit-testing">What about Unit Testing?</h2>
<p>Repositories offer a great unit testing abstraction. And so does this design. IDataContext exposes properties of type IDbSet – which is an interface just like IList, and ripe for the mocking!</p>
<p>Someone has even created a great <strong>InMemoryDbSet</strong> and added it to NuGet for our consuming pleasure.</p>
<p><a href="https://nuget.org/packages/FakeDbSet">https://nuget.org/packages/FakeDbSet</a></p>
<p>Now it becomes painlessly simple to create a fake IDataContext instance and populate it with InMemoryDbSets just like an in-memory repository would offer.</p>
<h2 id="what-about-accessing-the-unfiltered-set">What about accessing the unfiltered set?</h2>
<p><a href="https://twitter.com/klabranche">Kevin LaBranche</a> asked below how I might handle a scenario where I needed to bypass the filter, such as for reporting. One way to solve this would be to create an Unfiltered extension method which could check if the IDbSet is a FilteredDbSet, and if so, return underlying set instead of the filtered one.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">DbSetHelper</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">static</span> <span class="n">IQueryable</span><span class="p"><</span><span class="n">TEntity</span><span class="p">></span> <span class="n">Unfiltered</span><span class="p"><</span><span class="n">TEntity</span><span class="p">>(</span><span class="k">this</span> <span class="n">IDbSet</span><span class="p"><</span><span class="n">TEntity</span><span class="p">></span> <span class="k">set</span><span class="p">)</span> <span class="k">where</span> <span class="n">TEntity</span> <span class="p">:</span> <span class="k">class</span>
<span class="err">{</span>
<span class="nc">var</span> <span class="n">filteredDbSet</span> <span class="p">=</span> <span class="k">set</span> <span class="k">as</span> <span class="n">FilteredDbSet</span><span class="p"><</span><span class="n">TEntity</span><span class="p">>;</span>
<span class="k">return</span> <span class="n">filteredDbSet</span> <span class="p">!=</span> <span class="k">null</span> <span class="p">?</span> <span class="n">filteredDbSet</span><span class="p">.</span><span class="nf">Unfiltered</span><span class="p">()</span> <span class="p">:</span> <span class="k">set</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p><strong>Note:</strong> I also had to add the following method to the FilteredDbSet class</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="n">IQueryable</span><span class="p"><</span><span class="n">TEntity</span><span class="p">></span> <span class="nf">Unfiltered</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="n">_set</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h4 id="which-could-then-be-used-as-follows">Which could then be used as follows:</h4>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="n">ActionResult</span> <span class="nf">Index</span><span class="p">()</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">categories</span> <span class="p">=</span> <span class="n">_db</span><span class="p">.</span><span class="n">Categories</span><span class="p">;</span>
<span class="kt">var</span> <span class="n">unfiltered</span> <span class="p">=</span> <span class="n">_db</span><span class="p">.</span><span class="n">Categories</span><span class="p">.</span><span class="nf">Unfiltered</span><span class="p">();</span>
<span class="k">return</span> <span class="nf">Content</span><span class="p">(</span><span class="kt">string</span><span class="p">.</span><span class="nf">Format</span><span class="p">(</span><span class="s">"Found {0} active categories. Found {1} total."</span><span class="p">,</span> <span class="n">categories</span><span class="p">.</span><span class="nf">Count</span><span class="p">(),</span> <span class="n">unfiltered</span><span class="p">.</span><span class="nf">Count</span><span class="p">()));</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="summary">Summary</h2>
<p>Like the saying goes: complexity is easy; simplicity is hard.</p>
<p>Striving for a clean and simple architecture, without needless layers of complexity, is a goal we should all have. Sometimes it makes sense to try and make your infrastructure smarter, instead of adding yet another layer of indirection.</p>
<p> </p>Matt HidingerIf you drink from the fire hose read Ayende’s blog you would notice a lot of Anti-Repository talk over the past couple years – which I fully agree with.Adding rich Selector support for MVC2012-01-23T00:00:00+00:002012-01-23T00:00:00+00:00https://matthidinger.com/archive/2012/01/23/adding-rich-selector-support-for-mvc<p><img src="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/Adding-really-rich-Selector-support-for-_8379/image_thumb_2.png" alt="" /></p>
<p>By using the the simple <strong>SelectorAttribute</strong> and <strong>EditorTemplate</strong> described in this post, you will get rich support the following very common scenarios (and flip between the various modes with ease):</p>
<ol>
<li><strong>Single</strong> selection from a <strong>Drop Down</strong></li>
<li><strong>Single</strong> selection from <strong>Radio Buttons</strong></li>
<li><strong>Multiple</strong> selection from <strong>Check Boxes</strong></li>
<li><strong>Multiple</strong> selection from a <strong>List Box</strong></li>
<li><strong>Read-only</strong> mode combines multiple values into a comma-delimited string</li>
</ol>
<h2 id="the-canonical-example">The Canonical example</h2>
<p>Say you’re inserting a new Product and need to set the <strong>CategoryId</strong> property. You make a simple input Model wanting to use EditorFor, but <strong>CategoryId</strong> gets rendered as a useless textbox. The challenge is:</p>
<ol>
<li>Retrieving the list of categories to present to the user</li>
<li>Keeping the selected item(s) in sync with the list of choices</li>
</ol>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">Product</span>
<span class="p">{</span>
<span class="p">[</span><span class="n">Required</span><span class="p">]</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Name</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">[</span><span class="n">Required</span><span class="p">]</span>
<span class="p">[</span><span class="nf">Display</span><span class="p">(</span><span class="n">Name</span> <span class="p">=</span> <span class="s">"Category"</span><span class="p">)]</span>
<span class="k">public</span> <span class="kt">int</span><span class="p">?</span> <span class="n">CategoryId</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="enter-the-selectorattribute">Enter the SelectorAttribute</h3>
<p><strong>The only change from the model above is the new [CategorySelector] attribute on the property.</strong></p>
<h4 id="single-selection-vs-multiple-selection">Single Selection vs. Multiple Selection</h4>
<p>Since the [CategorySelector] was placed on an int? property, the selector will render in Single-select mode (only one int can be stored into the property). If however, it were a List<int?> property, the selector would render in Multi-select mode, allowing the user to choose more than one int value. I personally find this automatic behavior pretty cool and very helpful!</p>
<h4 id="the-full-model">The full model</h4>
<p>The screenshot you saw easier is rendered simply by using following Model and EditorFor. The magic lies in the <strong>[CategorySelector]</strong> and <strong>[DisplayModeSelector]</strong> attributes.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">DisplayModeOptions</span>
<span class="p">{</span>
<span class="k">public</span> <span class="nf">DisplayModeOptions</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">ReadOnly</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p"><</span><span class="n">DisplayMode</span><span class="p">></span> <span class="p">{</span> <span class="n">DisplayMode</span><span class="p">.</span><span class="n">HomePage</span><span class="p">,</span> <span class="n">DisplayMode</span><span class="p">.</span><span class="n">BrowseOnly</span><span class="p">};</span>
<span class="p">}</span>
<span class="p">[</span><span class="n">Required</span><span class="p">]</span>
<span class="p">[</span><span class="nf">Display</span><span class="p">(</span><span class="n">Name</span> <span class="p">=</span> <span class="s">"Category"</span><span class="p">)]</span>
<span class="p">[</span><span class="n">CategorySelector</span><span class="p">]</span>
<span class="k">public</span> <span class="kt">int</span><span class="p">?</span> <span class="n">CategoryId</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">[</span><span class="n">Required</span><span class="p">]</span>
<span class="p">[</span><span class="nf">DisplayModeSelector</span><span class="p">(</span><span class="n">BulkSelectionThreshold</span> <span class="p">=</span> <span class="m">0</span><span class="p">)]</span>
<span class="k">public</span> <span class="n">DisplayMode</span><span class="p">?</span> <span class="n">DropDown</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">[</span><span class="n">Required</span><span class="p">]</span>
<span class="p">[</span><span class="n">DisplayModeSelector</span><span class="p">]</span>
<span class="k">public</span> <span class="n">DisplayMode</span><span class="p">?</span> <span class="n">RadioButtons</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">[</span><span class="n">Required</span><span class="p">]</span>
<span class="p">[</span><span class="nf">DisplayModeSelector</span><span class="p">(</span><span class="n">BulkSelectionThreshold</span> <span class="p">=</span> <span class="m">0</span><span class="p">)]</span>
<span class="k">public</span> <span class="n">List</span><span class="p"><</span><span class="n">DisplayMode</span><span class="p">></span> <span class="n">ListBox</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">[</span><span class="n">Required</span><span class="p">]</span>
<span class="p">[</span><span class="n">DisplayModeSelector</span><span class="p">]</span>
<span class="k">public</span> <span class="n">List</span><span class="p"><</span><span class="n">DisplayMode</span><span class="p">></span> <span class="n">CheckBoxes</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">[</span><span class="nf">ReadOnly</span><span class="p">(</span><span class="k">true</span><span class="p">)]</span>
<span class="p">[</span><span class="n">DisplayModeSelector</span><span class="p">]</span>
<span class="k">public</span> <span class="n">List</span><span class="p"><</span><span class="n">DisplayMode</span><span class="p">></span> <span class="n">ReadOnly</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<h4 id="the-view-is-nothing-more-than">The View is nothing more than</h4>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p"><</span><span class="n">form</span> <span class="n">action</span><span class="p">=</span><span class="s">""</span> <span class="n">method</span><span class="p">=</span><span class="s">"post"</span><span class="p">></span>
<span class="p"><</span><span class="n">div</span> <span class="k">class</span><span class="err">="</span><span class="nc">two</span><span class="p">-</span><span class="n">column</span><span class="s">">
</span> <span class="p"><</span><span class="n">div</span> <span class="k">class</span><span class="err">="</span><span class="nc">field</span><span class="p">-</span><span class="k">group</span><span class="s">">
</span> <span class="p"><</span><span class="n">h4</span><span class="p">></span><span class="n">Single</span> <span class="n">Selection</span><span class="p"></</span><span class="n">h4</span><span class="p">></span>
<span class="n">@Html</span><span class="p">.</span><span class="nf">FullFieldEditor</span><span class="p">(</span><span class="n">m</span> <span class="p">=></span> <span class="n">m</span><span class="p">.</span><span class="n">RadioButtons</span><span class="p">)</span>
<span class="n">@Html</span><span class="p">.</span><span class="nf">FullFieldEditor</span><span class="p">(</span><span class="n">m</span> <span class="p">=></span> <span class="n">m</span><span class="p">.</span><span class="n">DropDown</span><span class="p">)</span>
<span class="n">@Html</span><span class="p">.</span><span class="nf">FullFieldEditor</span><span class="p">(</span><span class="n">m</span> <span class="p">=></span> <span class="n">m</span><span class="p">.</span><span class="n">CategoryId</span><span class="p">)</span>
<span class="p"></</span><span class="n">div</span><span class="p">></span>
<span class="p"><</span><span class="n">div</span> <span class="k">class</span><span class="err">="</span><span class="nc">field</span><span class="p">-</span><span class="k">group</span><span class="s">">
</span> <span class="p"><</span><span class="n">h4</span><span class="p">></span><span class="n">Multiple</span> <span class="n">Selection</span><span class="p"></</span><span class="n">h4</span><span class="p">></span>
<span class="n">@Html</span><span class="p">.</span><span class="nf">FullFieldEditor</span><span class="p">(</span><span class="n">m</span> <span class="p">=></span> <span class="n">m</span><span class="p">.</span><span class="n">CheckBoxes</span><span class="p">)</span>
<span class="n">@Html</span><span class="p">.</span><span class="nf">FullFieldEditor</span><span class="p">(</span><span class="n">m</span> <span class="p">=></span> <span class="n">m</span><span class="p">.</span><span class="n">ListBox</span><span class="p">)</span>
<span class="p"></</span><span class="n">div</span><span class="p">></span>
<span class="p"></</span><span class="n">div</span><span class="p">></span>
<span class="p"><</span><span class="n">input</span> <span class="n">type</span><span class="p">=</span><span class="s">"submit"</span> <span class="k">value</span><span class="p">=</span><span class="s">"Save"</span><span class="p">/></span>
<span class="p"></</span><span class="n">form</span><span class="p">></span>
</code></pre></div></div>
<h3 id="other-helpful-features">Other helpful features</h3>
<ol>
<li>Respects existing validators like <strong>[Required]</strong> and shows a nice custom validation UI on failure</li>
<li>Customizable <strong>OptionLabel</strong> (or don’t show one at all)</li>
<li>If the <strong>SelectorAttribute</strong> is placed on an <strong>IEnumerable</strong> Property it will <strong>automatically</strong> render in multi-selection mode <em>(notice the difference between the RadioButtons and CheckBoxes property above)</em></li>
<li>Automatically converts to <strong>bulk items mode</strong> if the number of choices exceeds your specified threshold. (You wouldn’t really want to show a user 50 checkboxes would you?)</li>
<li>A handy enum helper displays the enum values as the choices in the UI <em>(seen below in the DisplayModeSelectorAttribute code)</em></li>
<li>Of course it retains all user selected values on posts, very common in validation failures</li>
</ol>
<h3 id="creating-your-own-selectorattributes">Creating your own SelectorAttributes</h3>
<p>You’ll need to create your own SelectorAttributes in order to specify the list of choices that should be displayed to the user.</p>
<p>The DisplayModeSelector displays all possible choices within an enum.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">DisplayModeSelectorAttribute</span> <span class="p">:</span> <span class="n">SelectorAttribute</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">override</span> <span class="n">IEnumerable</span><span class="p"><</span><span class="n">SelectListItem</span><span class="p">></span> <span class="nf">GetItems</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="n">Selector</span><span class="p">.</span><span class="n">GetItemsFromEnum</span><span class="p"><</span><span class="n">DisplayMode</span><span class="p">>();</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>The CategorySelector demonstrates how you might access a database to get a list of items dynamically.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">CategorySelectorAttribute</span> <span class="p">:</span> <span class="n">SelectorAttribute</span>
<span class="p">{</span>
<span class="k">public</span> <span class="nf">CategorySelectorAttribute</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">// The Category selector should always be rendered as a drop down</span>
<span class="n">BulkSelectionThreshold</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">override</span> <span class="n">IEnumerable</span><span class="p"><</span><span class="n">SelectListItem</span><span class="p">></span> <span class="nf">GetItems</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">// You could of course get these values from a database, similar to:</span>
<span class="c1">// var dataContext = DependencyResolver.Current.GetService<IDataContext>();</span>
<span class="kt">var</span> <span class="n">categories</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p"><</span><span class="n">Category</span><span class="p">></span>
<span class="p">{</span>
<span class="k">new</span> <span class="n">Category</span> <span class="p">{</span><span class="n">Id</span> <span class="p">=</span> <span class="m">1</span><span class="p">,</span> <span class="n">Name</span> <span class="p">=</span> <span class="s">"Beverages"</span><span class="p">},</span>
<span class="k">new</span> <span class="n">Category</span> <span class="p">{</span><span class="n">Id</span> <span class="p">=</span> <span class="m">2</span><span class="p">,</span> <span class="n">Name</span> <span class="p">=</span> <span class="s">"Tools"</span><span class="p">},</span>
<span class="k">new</span> <span class="n">Category</span> <span class="p">{</span><span class="n">Id</span> <span class="p">=</span> <span class="m">3</span><span class="p">,</span> <span class="n">Name</span> <span class="p">=</span> <span class="s">"Soup"</span><span class="p">},</span>
<span class="p">};</span>
<span class="k">return</span> <span class="n">Selector</span><span class="p">.</span><span class="nf">GetItems</span><span class="p">(</span><span class="n">categories</span><span class="p">,</span> <span class="n">m</span> <span class="p">=></span> <span class="n">m</span><span class="p">.</span><span class="n">Id</span><span class="p">,</span> <span class="n">m</span> <span class="p">=></span> <span class="n">m</span><span class="p">.</span><span class="n">Name</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="get-the-code">Get the Code!</h2>
<p>Rather than pasting the full source here, I will be publishing it along with a sample project at <a href="https://mvcgrabbag.codeplex.com"><strong>https://mvcgrabbag.codeplex.com</strong></a></p>
<h4 id="what-you-need-for-selector-support">What you need for Selector support</h4>
<ol>
<li>Selectors\Selector.cs</li>
<li>Selectors\SelectorAttribute.cs</li>
<li>Views\Shared\EditorTemplates\Selector.cshtml</li>
</ol>
<h4 id="pull-it-down-locally">Pull it down locally</h4>
<p>Using <a href="https://tortoisehg.bitbucket.org/"><strong>TortoiseHg</strong></a> simply clone the URL: <a href="https://hg01.codeplex.com/mvcgrabbag"><strong>https://hg01.codeplex.com/mvcgrabbag</strong></a></p>
<p><img src="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/Adding-really-rich-Selector-support-for-_8379/image_thumb_3.png" alt="" /></p>
<h4 id="browse-the-code">Browse the code</h4>
<p><a href="https://mvcgrabbag.codeplex.com/SourceControl/changeset/view/2ea3da6732a6#MvcGrabBag.Web%2fSelectors%2fSelectorAttribute.cs"><strong>Browse the Selector code, MvcGrabBag.Web/Selectors folder</strong></a></p>
<p> </p>Matt HidingerSimplifying application caching2012-01-13T00:00:00+00:002012-01-13T00:00:00+00:00https://matthidinger.com/archive/2012/01/13/simplifying-application-caching<p><img src="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/11fa22879ac6_B1E4/image_thumb%5B4%5D_thumb.png" alt="" /></p>
<p>Many ASP.NET applications utilize the <strong>System.Web.Caching.Cache</strong> in some way. While it offers a pretty simple Dictionary-like API that your app can start using immediately, I typically create a combined “tell-don’t-ask” wrapper around it – which has some additional architectural benefits as well.</p>
<h3 id="out-of-the-box-concerns">Out of the box concerns</h3>
<p>A very common usage of the Cache API can be seen below, but there are a few initial problems I have with it:</p>
<ol>
<li>Ugly, non-generic casting</li>
<li>Manual null checks</li>
<li>Duplicating the string for the key</li>
<li>Lots of implementation details sprinkled around</li>
<li>No out of box way to scope the cache. For example, cache a unique copy of the item for each User</li>
</ol>
<p> </p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="n">ActionResult</span> <span class="nf">Bad</span><span class="p">()</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">firstVisit</span> <span class="p">=</span> <span class="n">HttpContext</span><span class="p">.</span><span class="n">Cache</span><span class="p">.</span><span class="nf">Get</span><span class="p">(</span><span class="s">"FirstVisit"</span><span class="p">)</span> <span class="k">as</span> <span class="n">DateTime</span><span class="p">?;</span>
<span class="k">if</span><span class="p">(</span><span class="n">firstVisit</span> <span class="p">==</span> <span class="k">null</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">firstVisit</span> <span class="p">=</span> <span class="n">DateTime</span><span class="p">.</span><span class="n">Now</span><span class="p">;</span>
<span class="n">HttpContext</span><span class="p">.</span><span class="n">Cache</span><span class="p">.</span><span class="nf">Insert</span><span class="p">(</span><span class="s">"FirstVisit"</span><span class="p">,</span> <span class="n">firstVisit</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="n">DateTime</span><span class="p">.</span><span class="n">Now</span><span class="p">.</span><span class="nf">AddMinutes</span><span class="p">(</span><span class="m">1</span><span class="p">),</span> <span class="n">TimeSpan</span><span class="p">.</span><span class="n">Zero</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nf">View</span><span class="p">(</span><span class="s">"Index"</span><span class="p">,</span> <span class="n">firstVisit</span><span class="p">.</span><span class="n">Value</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p> </p>
<h3 id="a-simple-icachehttpcache-wrapper">A simple ICache/HttpCache wrapper</h3>
<p>The wrapper I create is used below. It’s nothing revolutionary, but does try to cut down on the redundancy, while adding a few features as well. The following code functions exactly the same as the code above.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="n">ActionResult</span> <span class="nf">Index</span><span class="p">()</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">firstVisit</span> <span class="p">=</span> <span class="n">_cache</span><span class="p">.</span><span class="nf">Get</span><span class="p">(</span><span class="n">CacheScope</span><span class="p">.</span><span class="n">User</span><span class="p">,</span> <span class="s">"FirstVisit"</span><span class="p">,</span> <span class="n">TimeSpan</span><span class="p">.</span><span class="nf">FromMinutes</span><span class="p">(</span><span class="m">1</span><span class="p">),</span> <span class="p">()</span> <span class="p">=></span> <span class="n">DateTime</span><span class="p">.</span><span class="n">Now</span><span class="p">);</span>
<span class="k">return</span> <span class="nf">View</span><span class="p">(</span><span class="n">firstVisit</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>The three biggest changes are:</p>
<ol>
<li>Implicit generic casting (the Get() method is automatically returning a nice, typed DateTime object because the Func<T> at the end became a Func<DateTime>)</li>
<li>Tell-don’t-ask. Instead of asking the cache if it already contains something by checking for null, then creating and adding the new item into the cache, I’d rather just combine these 2 functions and have the cache figure out what it needs to do. The last method parameter is a Func<T> which will be invoked if the item is not already in the cache.</li>
<li>Added a CacheScope which allows the developer to cache something application-wide, or for each user individually.</li>
</ol>
<h3 id="architectural-advantages">Architectural advantages</h3>
<p>Aside from these API usage changes we also get 2 big architectural advantages:</p>
<ol>
<li>The application can rely on a new ICache interface, which means you can access the cache from a lower, non-web layer without having to reference System.Web</li>
<li>The provided implementation of ICache is an HttpCache, which by default uses HttpContext.Current, but provides a nice testability hook to plug in your own mocked HttpContextBase if you want to do some integration testing</li>
</ol>
<h3 id="going-the-extra-mile">Going the extra mile</h3>
<p>You may notice that our controller still has intimate knowledge of our caching strategy: duration, scope, the string-based key, etc. This code-duplication lightning-rod could easily be copy-pasted around. One possible way to solve this would be to create something like the following AppCache.</p>
<h4 id="a-central-appcache">A central AppCache</h4>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">/// <summary></span>
<span class="c1">/// This class demonstrates fully abstracting the details of your caching strategy and could serve as the single entry point for cached data</span>
<span class="c1">/// </summary></span>
<span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">AppCache</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">static</span> <span class="n">ICache</span> <span class="n">InternalCache</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">HttpCache</span><span class="p">();</span>
<span class="k">public</span> <span class="k">static</span> <span class="n">DateTime</span> <span class="n">UsersFirstVisit</span> <span class="p">=</span> <span class="n">InternalCache</span><span class="p">.</span><span class="nf">Get</span><span class="p">(</span><span class="n">CacheScope</span><span class="p">.</span><span class="n">User</span><span class="p">,</span> <span class="s">"FirstVisit"</span><span class="p">,</span> <span class="n">TimeSpan</span><span class="p">.</span><span class="nf">FromMinutes</span><span class="p">(</span><span class="m">1</span><span class="p">),</span> <span class="p">()</span> <span class="p">=></span> <span class="n">DateTime</span><span class="p">.</span><span class="n">Now</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<h4 id="usage-in-a-controller">Usage in a Controller</h4>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="n">ActionResult</span> <span class="nf">FullyAbstracted</span><span class="p">()</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">firstVisit</span> <span class="p">=</span> <span class="n">AppCache</span><span class="p">.</span><span class="n">UsersFirstVisit</span><span class="p">;</span>
<span class="k">return</span> <span class="nf">View</span><span class="p">(</span><span class="s">"Index"</span><span class="p">,</span> <span class="n">firstVisit</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Now we are completely free to change the caching strategy of our application in a single place.</p>
<h2 id="get-the-code">Get the Code</h2>
<p>Rather than pasting the full source here, I will be publishing it along with a sample project at <a href="https://mvcgrabbag.codeplex.com"><strong>https://mvcgrabbag.codeplex.com</strong></a></p>
<h4 id="browse-the-httpcache-code-mvcgrabbagwebcaching-folder"><a href="https://mvcgrabbag.codeplex.com/SourceControl/changeset/view/2ea3da6732a6#MvcGrabBag.Web%2fCaching%2fHttpCache.cs">Browse the HttpCache code, MvcGrabBag.Web/Caching folder</a></h4>
<p> </p>Matt HidingerTidy up MVC forms with a simple HtmlFormHelper2012-01-10T00:00:00+00:002012-01-10T00:00:00+00:00https://matthidinger.com/archive/2012/01/10/tidy-up-mvc-forms-with-a-simple-htmlformhelper<p>Many line-of-business applications contain dozens of forms similar to the following, each field consisting of a few common characteristics:</p>
<ol>
<li>A Label with the name of the field</li>
<li>The field editor itself</li>
<li>Asterisks and special styling for required fields</li>
<li>A tooltip that can be hovered for a detailed description of the field</li>
<li>Validation messages if the input is incorrect</li>
</ol>
<p><img src="/images/subtext-content/www_matthidinger_com/Windows-Live-Writer/1d7e768239e6_E33C/image_thumb_8.png" alt="" /></p>
<p>To achieve this, we can create the following Model</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">ProductInput</span>
<span class="p">{</span>
<span class="p">[</span><span class="nf">HiddenInput</span><span class="p">(</span><span class="n">DisplayValue</span> <span class="p">=</span> <span class="k">false</span><span class="p">)]</span>
<span class="k">public</span> <span class="kt">int</span> <span class="n">Id</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">[</span><span class="n">Required</span><span class="p">]</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Name</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">[</span><span class="n">Required</span><span class="p">]</span>
<span class="p">[</span><span class="nf">Display</span><span class="p">(</span><span class="n">Description</span> <span class="p">=</span> <span class="s">"A brief description of the product"</span><span class="p">)]</span>
<span class="p">[</span><span class="nf">DataType</span><span class="p">(</span><span class="n">DataType</span><span class="p">.</span><span class="n">MultilineText</span><span class="p">)]</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Description</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">[</span><span class="nf">Display</span><span class="p">(</span><span class="n">Description</span> <span class="p">=</span> <span class="s">"An optional alternate description of the product to display when featured on the home page"</span><span class="p">)]</span>
<span class="p">[</span><span class="nf">DataType</span><span class="p">(</span><span class="n">DataType</span><span class="p">.</span><span class="n">MultilineText</span><span class="p">)]</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">FeaturedDescription</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">[</span><span class="n">Required</span><span class="p">]</span>
<span class="k">public</span> <span class="kt">decimal</span><span class="p">?</span> <span class="n">Price</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">[</span><span class="nf">Display</span><span class="p">(</span><span class="n">Description</span> <span class="p">=</span> <span class="s">"Price of the product during a sale"</span><span class="p">)]</span>
<span class="k">public</span> <span class="kt">decimal</span><span class="p">?</span> <span class="n">SalePrice</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>However, when it comes to actually rendering the view, many MVC forms contain some variation of the following pattern, <em>repeated over and over for every single field.</em></p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p"><</span><span class="n">div</span> <span class="k">class</span><span class="err">="</span><span class="nc">field</span><span class="p">-</span><span class="n">wrapper</span><span class="s">">
</span> <span class="p"><</span><span class="n">div</span> <span class="k">class</span><span class="err">="</span><span class="nc">field</span><span class="p">-</span><span class="n">label</span><span class="s">">
</span> <span class="n">@Html</span><span class="p">.</span><span class="nf">LabelFor</span><span class="p">(</span><span class="n">m</span> <span class="p">=></span> <span class="n">m</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span>
<span class="p"></</span><span class="n">div</span><span class="p">></span>
<span class="p"><</span><span class="n">div</span> <span class="k">class</span><span class="err">="</span><span class="nc">field</span><span class="p">-</span><span class="n">input</span><span class="s">">
</span> <span class="n">@Html</span><span class="p">.</span><span class="nf">EditorFor</span><span class="p">(</span><span class="n">m</span> <span class="p">=></span> <span class="n">m</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span>
<span class="n">@Html</span><span class="p">.</span><span class="nf">TooltipFor</span><span class="p">(</span><span class="n">m</span> <span class="p">=></span> <span class="n">m</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span>
<span class="n">@Html</span><span class="p">.</span><span class="nf">ValidationMessageFor</span><span class="p">(</span><span class="n">m</span> <span class="p">=></span> <span class="n">m</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span>
<span class="p"></</span><span class="n">div</span><span class="p">></span>
<span class="p"></</span><span class="n">div</span><span class="p">></span>
</code></pre></div></div>
<p>While this pattern certainly takes advantage of great MVC functionality like Editor Templates and strongly-typed inputs, it’s clear that this template is going to be pasted all over the application, with a quick rename on the property being rendered. Unfortunately this type of duplication creates 2 distinct problems:</p>
<ol>
<li>Immediately, it offers no way of styling required fields differently (like adding an asterisk or bolding labels)</li>
<li>It becomes very time consuming to handle a business request like “Please move the tooltip icon before the textboxes instead of after”</li>
</ol>
<p>To solve this, I use a very simple HtmlFormHelper called FullFieldEditor, which renders the exact same HTML described above, but allows me to easily re-style it in a single place.</p>
<p>The entire View in the screenshot above consists of the following:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p"><</span><span class="n">form</span> <span class="n">action</span><span class="p">=</span><span class="s">""</span> <span class="n">method</span><span class="p">=</span><span class="s">"post"</span><span class="p">></span>
<span class="p"><</span><span class="n">div</span> <span class="k">class</span><span class="err">="</span><span class="nc">two</span><span class="p">-</span><span class="n">column</span><span class="s">">
</span>
<span class="p"><</span><span class="n">div</span> <span class="k">class</span><span class="err">="</span><span class="nc">field</span><span class="p">-</span><span class="k">group</span><span class="s">">
</span> <span class="n">@Html</span><span class="p">.</span><span class="nf">FullFieldEditor</span><span class="p">(</span><span class="n">m</span> <span class="p">=></span> <span class="n">m</span><span class="p">.</span><span class="n">Id</span><span class="p">)</span>
<span class="n">@Html</span><span class="p">.</span><span class="nf">FullFieldEditor</span><span class="p">(</span><span class="n">m</span> <span class="p">=></span> <span class="n">m</span><span class="p">.</span><span class="n">Name</span><span class="p">)</span>
<span class="n">@Html</span><span class="p">.</span><span class="nf">FullFieldEditor</span><span class="p">(</span><span class="n">m</span> <span class="p">=></span> <span class="n">m</span><span class="p">.</span><span class="n">Price</span><span class="p">)</span>
<span class="n">@Html</span><span class="p">.</span><span class="nf">FullFieldEditor</span><span class="p">(</span><span class="n">m</span> <span class="p">=></span> <span class="n">m</span><span class="p">.</span><span class="n">Description</span><span class="p">)</span>
<span class="p"></</span><span class="n">div</span><span class="p">></span>
<span class="p"><</span><span class="n">div</span> <span class="k">class</span><span class="err">="</span><span class="nc">field</span><span class="p">-</span><span class="k">group</span><span class="s">">
</span> <span class="n">@Html</span><span class="p">.</span><span class="nf">FullFieldEditor</span><span class="p">(</span><span class="n">m</span> <span class="p">=></span> <span class="n">m</span><span class="p">.</span><span class="n">SalePrice</span><span class="p">)</span>
<span class="n">@Html</span><span class="p">.</span><span class="nf">FullFieldEditor</span><span class="p">(</span><span class="n">m</span> <span class="p">=></span> <span class="n">m</span><span class="p">.</span><span class="n">FeaturedDescription</span><span class="p">)</span>
<span class="p"></</span><span class="n">div</span><span class="p">></span>
<span class="p"></</span><span class="n">div</span><span class="p">></span>
<span class="p"><</span><span class="n">div</span> <span class="k">class</span><span class="err">="</span><span class="nc">clear</span><span class="p">-</span><span class="n">fix</span><span class="s">"></div>
</span> <span class="p"><</span><span class="n">input</span> <span class="n">type</span><span class="p">=</span><span class="s">"submit"</span> <span class="k">value</span><span class="p">=</span><span class="s">"Save"</span><span class="p">/></span>
<span class="p"></</span><span class="n">form</span><span class="p">></span>
</code></pre></div></div>
<h3 id="source-code">Source Code</h3>
<p>Rather than pasting the full source here, I will be publishing it along with a sample project at <a href="https://mvcgrabbag.codeplex.com">https://mvcgrabbag.codeplex.com</a></p>
<h4 id="view-the-full-htmlformhelpercs"><a href="https://mvcgrabbag.codeplex.com/SourceControl/changeset/view/dee469477184#MvcGrabBag.Web%2fHelpers%2fHtmlFormHelper.cs" title="HtmlFormHelper.cs">View the full HtmlFormHelper.cs</a></h4>
<p> </p>Matt HidingerMany line-of-business applications contain dozens of forms similar to the following, each field consisting of a few common characteristics: