tag:blogger.com,1999:blog-19021580342208938922024-03-05T14:09:09.873+00:00Diary of a DotNet DeveloperNot poems and rubbish - Science!Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.comBlogger87125tag:blogger.com,1999:blog-1902158034220893892.post-60778990660094421222021-12-30T11:08:00.002+00:002021-12-30T11:08:33.130+00:00Advent of Learning 2021<p style="text-align: justify;"><span style="font-family: verdana;">I came across <a href="http://adventofcode.com" target="_blank">Advent of Code</a> a few years ago and last year I introduced it to my team at Superdrug. For those who aren't familiar, it is a series of programming puzzles acros the 25 days of Advent; there are two puzzles each day, completing the first one unlocks the second one which is a variation or extension of the first. You can complete them in any language/environment.</span></p><p style="text-align: justify;"><span style="font-family: verdana;">This is what I've learned this year from doing AoC.</span></p><p style="text-align: justify;"><span style="font-family: verdana;">I had an aspiration this year to do at least some of the puzzles in JavaScript instead of C# so I could brush up on my JS a little bit/learn a JS unit test framework. But by the time 1st Dec rolled around I had nothing in place (or more accurately, I said I wanted to do some in JS but then did nothing else about it), so I've done everything in C# again this year, JS will have to wait another year.</span></p><p style="text-align: justify;"><span style="font-family: verdana;">I did a couple of the early days in bed first thing in the morning on my Surface Pro tablet, but I found the Type Cover keyboard a little too fiddly on an unstable surface so switched after that to doing them at my desk on a full-size keyboard.</span></p><p style="text-align: justify;"><span style="font-family: verdana;"><b>Exponentials and Overflows</b></span></p><p style="text-align: justify;"><span style="font-family: verdana;"><a href="https://adventofcode.com/2021/day/6" target="_blank">Day 6</a> featured exponential growth of lanternfish. If there's one thing we should have all learned in the past two years, it's how to model exponential growth... There was a trap in the puzzle in that you could complete Part 1 by modelling each individual fish, but the numbers of fish were so large in Part 2 that this approach wasn't viable (I briefly contemplated spinning up a high performance VM on Azure to run my solution...).</span></p><p style="text-align: justify;"><span style="font-family: verdana;">So I completely rewrote my solution to work on a </span><span style="font-family: courier;">Dictionary<int, int></span><span style="font-family: verdana;">, where for each day that passed the number of fish at each stage of their life dropped down a step. I ran this solution for Part 1 to confirm it gave me the same answer as my previous solution, then ran it for Part 2 and entered the result to the AoC site to get my confirmation. To my surprise the answer was still too low! Debugging into my solution I discovered some of the values in the dictionary were becoming negative numbers, and it took me a minutes thought to work out that this was probably integer overflow, the first time I can recall coming across it in 25 years of coding professionally (I very rarely deal with numbers large enough that the problem arises). I changed the dictionary to </span><span style="font-family: courier;">Dictionary<int, long></span><span style="font-family: verdana;"> and the puzzle was solved. </span></p><p style="text-align: justify;"><span style="font-family: verdana;"><b>Stacks</b></span></p><p style="text-align: justify;"><span style="font-family: verdana;">In <a href="https://adventofcode.com/2021/day/10" target="_blank">Day 10</a>'s puzzle, you had to find a corrupt character in a string, which in another first for me marked the first time I can remember having to use a Stack. </span></p><p style="text-align: justify;"><span style="font-family: verdana;">(I was watching my friend <a href="https://twitter.com/dylanbeattie" target="_blank">Dylan</a> doing this one, and he figured out it was a Stack machine within a few seconds, but says that is the result of having had to write a LISP interpreter at college...)</span></p><p style="text-align: justify;"><span style="font-family: verdana;"><b>A* and Djikstra</b></span></p><p style="text-align: justify;"><span style="font-family: verdana;"><a href="https://adventofcode.com/2021/day/15" target="_blank">Day 15</a> required you to find the lowest risk path through a cave filled with chitons. Which in turn required me to learn about the Djikstra and A* algorithms, and then implement one of them. I found <a href="https://dotnetcoretutorials.com/2020/07/25/a-search-pathfinding-algorithm-in-c/" target="_blank">a C# version of A*</a> that I could crib from, and wrote my solution. Which didn't (and at time of writing still doesn't) work.</span></p><p style="text-align: justify;"><span style="font-family: verdana;">However discussing it with my team, we were talking about practical uses for A* and think we could use it for planning routes through our stores when in-store staff are picking customer orders. </span></p><p style="text-align: justify;"><span style="font-family: verdana;"><b>LINQ</b></span></p><p style="text-align: justify;"><span style="font-family: verdana;">The puzzle for <a href="https://adventofcode.com/2021/day/7" target="_blank">Day 7</a> involved crabs in tiny submarines moving from side to side and finding the most efficient point for them to align on (you get used to this sort of imagery when you do AoC...). For which based on the example I took to mean finding the point on which the most submarines were located. Which meant I had to properly learn how to use the GroupBy method in Linq. And this was useful again on <a href="https://adventofcode.com/2021/day/14" target="_blank">Day 14</a> where having constructed a long string of letters you had to find the most and least common occurring letters, I used GroupBy to project each letter and it's count, followed by OrderBy and OrderByDescending to get the two letters. </span></p><p style="text-align: justify;"><span style="font-family: verdana;">On <a href="https://adventofcode.com/2021/day/4" target="_blank">Day 4</a>, we were playing bingo with a giant squid, and the task in Part 2 was to find the last winning bingo card from a set of cards. Which I was struggling with in using </span><span style="font-family: courier;">Enumerable.All</span><span style="font-family: verdana;">, when I switched it to </span><span style="font-family: courier;">List.TrueForAll </span><span style="font-family: verdana;">it worked first time</span><span><span style="font-family: verdana;">. I've just looked up the docs for </span><span style="font-family: courier;">Enumerable.All</span><span style="font-family: verdana;"> and I have a feeling I may not have been calling it the correct way. (Incidentally our dev manager had a great hack for this day where after laying out the bingo cards, he transposed the columns into extra rows so that when checking for a winning card he only had to write a method for finding a winning row and not worry about columns as well.)</span></span></p><p style="text-align: justify;"><span style="font-family: verdana;">Also in the aforementioned C# implementation of the A* algorithm, it uses the </span><span style="font-family: courier;">List.FindIndex</span><span style="font-family: verdana;"> method which is not one I've come across before, and when discussing this with my colleagues they mentioned the </span><span style="font-family: courier;">List.IndexOf</span><span style="font-family: verdana;"> method. These two methods look pretty much identical, but it looks like their implementations are different - there's some discussion in the answers to <a href="https://stackoverflow.com/q/31965778/1738" target="_blank">this SO question</a> which suggests that IndexOf is about 10 times faster than FindIndex.</span></p><p style="text-align: justify;"><span style="font-family: verdana;"><b>Wrap Up</b></span></p><p style="text-align: justify;"><span style="font-family: verdana;">I've picked up quite a few things this year that I can take back to the day job, GroupBy being probably the one I'm most pleased about and potentially the most applicable. And I did set a new PB this year.</span></p><p style="text-align: justify;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfbYxE8T_HMbQHuHjO-3oHPaEy6IP0YKBAtLgUR5O9m28AtN1tqy0ArigO_K13Zx4iMGRByEysEzeEVxZQTf4NNvn_QdhsQfe7EAmy4y4jwOCUmzFz3Be4grhAN0g47rPVpIWe_uai-d3C/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="183" data-original-width="142" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfbYxE8T_HMbQHuHjO-3oHPaEy6IP0YKBAtLgUR5O9m28AtN1tqy0ArigO_K13Zx4iMGRByEysEzeEVxZQTf4NNvn_QdhsQfe7EAmy4y4jwOCUmzFz3Be4grhAN0g47rPVpIWe_uai-d3C/" width="186" /></a></div><br /><span style="font-family: verdana;">I also made some useful changes to my <a href="https://github.com/philpursglove/AdventofCodeTemplate" target="_blank">AoC project template</a>. For next year I'd really like to make this a template in Visual Studio so I can have solutions named for the day they are for instead of multiple AdventTemplate solutions. And I still want to get a template together for JavaScript ahead of AoC 2022.</span><p></p>Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com1tag:blogger.com,1999:blog-1902158034220893892.post-47160128763731920732021-02-14T22:33:00.001+00:002021-02-14T22:33:18.367+00:00Regional Settings in Azure App Services<p style="text-align: justify;"><span style="font-family: verdana;">Thought I should share something we've come across this week while testing our API on Azure...</span></p><p style="text-align: justify;"><span style="font-family: verdana;">I was testing some reporting functions where we put in To and From dates, and I entered 01/01/2021 and 31/01/2021 - and I got an exception. Looking it up in AppInsights, it was an InvalidFormatException coming from DateTimeOffset.Parse. I checked the same dates on our production site (currently hosted on-prem) and it was fine. So what's the issue?</span></p><p style="text-align: justify;"><span style="font-family: verdana;">Well, it turns out that for an App Service instance, the regional settings (all those currency symbols and, most relevantly here, date formats) are set to US English, and trying to parse 31 as a month doesn't work. You can demonstrate this for yourself if you go to an App Service instance and then go to the Kudu debug console - in Powershell the command </span><span style="font-family: courier;">Get-WinSystemLocale</span><span style="font-family: verdana;"> will show you what your current region settings are set to. Here's a screenshot from one of mine which is located in the UK West Azure region:</span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZFUpVVMJx5h-uPkNcBw_JyyWMZ8GYF_R1enhQYnqyNz0ihWyL9mf-Q_fqhZzrciWIPyWx6ltZCxb9Llj1_bSW5o86k0yJH8dU2cFu7Q6JQM1EX_JhMsloA0oSYaECGYwy1Jo4lCPNSoZ8/s1056/AppService+Region+Setting.PNG" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: verdana;"><img alt="Kudu console showing regional settings for an AppService instance" border="0" data-original-height="822" data-original-width="1056" height="311" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZFUpVVMJx5h-uPkNcBw_JyyWMZ8GYF_R1enhQYnqyNz0ihWyL9mf-Q_fqhZzrciWIPyWx6ltZCxb9Llj1_bSW5o86k0yJH8dU2cFu7Q6JQM1EX_JhMsloA0oSYaECGYwy1Jo4lCPNSoZ8/w400-h311/AppService+Region+Setting.PNG" width="400" /></span></a></div><span style="font-family: verdana;"><br /></span><p style="text-align: justify;"><span style="font-family: verdana;">So how do you fix it? There is a counterpart </span><span style="font-family: courier;">Set-WinSystemLocale</span><span style="font-family: verdana;"> Powershell command, which you might be tempted to try, but it won't work as you need to be an administrator on the computer, which you aren't...</span></p><p style="text-align: justify;"><span style="font-family: verdana;">If you are using the .NET framework, there is a relatively simple fix: in your web.config in the system.web element, add a new globalization element:</span></p><p><span style="font-family: courier;"><system.web></span></p><p><span style="font-family: courier;"> <globalization culture="en-GB"/></span></p><p><span style="font-family: courier;"></system.web></span></p><p style="text-align: justify;"><span style="font-family: verdana;">(Or replace the region code with the one relevant to you - there's a good list of codes <a href="https://ss64.com/locale.html" target="_blank">here</a>). </span><span style="font-family: verdana;">And then your API will parse dates correctly.</span></p><p style="text-align: justify;"><span style="font-family: verdana;">In .NET Core/.NET 5, you can set the CultureInfo for the current thread in the Configure method of your Startup class as laid out in <a href="https://stackoverflow.com/a/40449401/1738" target="_blank">this SO answer</a>.</span></p><p style="text-align: justify;"><span style="font-family: verdana;">You can add an <a href="https://docs.microsoft.com/en-us/azure/app-service/faq-configuration-and-management#how-do-i-set-the-server-time-zone-for-my-web-app" target="_blank">application setting</a> to your app (WEBSITE_TIME_ZONE/TZ depending on whether you are using a Windows host or a Linux host) that manages which timezone it will use, and it would be neat if there was an equivalent that allowed to specify what regional settings you want to use.</span></p>Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com0tag:blogger.com,1999:blog-1902158034220893892.post-54376986673841520002021-01-30T23:26:00.000+00:002021-01-30T23:26:35.834+00:00AZ-204 Study Materials<p><span style="font-family: verdana;"> I took - and passed :-) - the <a href="https://docs.microsoft.com/en-us/learn/certifications/exams/az-204" target="_blank">AZ-204 Developing Solutions for Azure</a> exam yesterday. </span></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoMMm4b3RT4sV6KcDQtSZyduwHHIsQigCJQSj8cH303Yj4u7DMUPZ0DrVupjoV0Bo9y5TLe-G9iiWb0Z-ghSaJqs_QfyyohVDStk7a06h95iqj490K8I_zbKqpkFxPJWLDGMJ_PMZlHqDm/s600/azure-developer-associate-600x600.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="600" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoMMm4b3RT4sV6KcDQtSZyduwHHIsQigCJQSj8cH303Yj4u7DMUPZ0DrVupjoV0Bo9y5TLe-G9iiWb0Z-ghSaJqs_QfyyohVDStk7a06h95iqj490K8I_zbKqpkFxPJWLDGMJ_PMZlHqDm/s320/azure-developer-associate-600x600.png" /></a></div><br /><span style="font-family: verdana;"><br /></span><p></p><p><span style="font-family: verdana;">Study materials I used were:</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: verdana;">The MS learning paths listed on <a href="https://docs.microsoft.com/en-us/learn/certifications/exams/az-204" target="_blank">the exam page</a></span></li><li><span style="font-family: verdana;">The Pluralsight <a href="https://app.pluralsight.com/paths/certificate/developing-solutions-for-microsoft-azure-az-204" target="_blank">exam prep path</a></span></li><ul><li><span style="font-family: verdana;">In particular I found the Exam Alert sessions really useful, and also even though I've been doing MS exams on and off for 20 years, I found Matt Kruzcek's session on <a href="https://app.pluralsight.com/library/courses/microsoft-azure-developer-preparing-take-az-204-exam/table-of-contents" target="_blank">Preparing To Take The AZ-204 exam</a> really useful the night before as a refresher on what to expect on the day, and usefully on the question types used on the exam</span></li></ul><li><span style="font-family: verdana;">Before Xmas through work we had an invite to a Microsoft exam preparation session which walked through each entry in the list of skills measured in the exam; I picked up some really useful bits from this session so if you can get on one of them I'd recommend it</span></li></ul><p></p><p><span style="font-family: verdana;"><br /></span></p><p><span style="font-family: verdana;">What Next?</span></p><p><span style="font-family: verdana;">I'm now debating what to study for next - I want to do the Azure Solutions Architect certification, but also (now that I've unlocked it) the DevOps Engineer Expert certification is likely to be both useful and relevant for work. So I'm not sure which one to work on...</span></p>Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com0tag:blogger.com,1999:blog-1902158034220893892.post-33896997433396602402020-11-17T16:40:00.011+00:002020-11-23T08:58:54.744+00:0010 VS Extensions You Might Have Missed<p style="text-align: justify;"><span style="font-family: verdana;">I presented a lightning talk tonight at <a href="https://www.dotnetoxford.com/" target="_blank">DotNetOxford</a> on '10 VS Extensions You Might Have Missed' covering some perhaps lesser-known items in the Visual Studio Marketplace. All of these extensions are free, and they all provide a useful addition to what you get out of the box in Visual Studio.</span></p><p style="text-align: left;"><span style="font-family: verdana;">UPDATE: And now you can see the whole evening's set of talks at <a href="https://www.youtube.com/playlist?list=PL4qgjzgv2UYTTCbWELKjyJrcKMz02K7DH" target="_blank">https://www.youtube.com/playlist?list=PL4qgjzgv2UYTTCbWELKjyJrcKMz02K7DH</a></span></p><p><span style="font-family: verdana;"><br /></span></p><p><span style="font-family: verdana;">Customize Visual Studio Window Title</span></p><p><a href="https://marketplace.visualstudio.com/items?itemName=mayerwin.RenameVisualStudioWindowTitle" target="_blank"><span style="font-family: verdana;">https://marketplace.visualstudio.com/items?itemName=mayerwin.RenameVisualStudioWindowTitle</span></a></p><p><span style="font-family: verdana;"><br /></span></p><p><span style="font-family: verdana;">Azure DevOps Status Monitor</span></p><p><a href="https://marketplace.visualstudio.com/items?itemName=UtkarshShigihalliandTarunArora.VSTSStatusInspector" target="_blank"><span style="font-family: verdana;">https://marketplace.visualstudio.com/items?itemName=UtkarshShigihalliandTarunArora.VSTSStatusInspector</span></a></p><p><span style="font-family: verdana;"><br /></span></p><p><span style="font-family: verdana;">Viasfora</span></p><p><a href="https://marketplace.visualstudio.com/items?itemName=TomasRestrepo.Viasfora" target="_blank"><span style="font-family: verdana;">https://marketplace.visualstudio.com/items?itemName=TomasRestrepo.Viasfora</span></a></p><p><span style="font-family: verdana;"><br /></span></p><p><span style="font-family: verdana;">Tweaks</span></p><p><a href="https://marketplace.visualstudio.com/items?itemName=MadsKristensen.Tweaks" target="_blank"><span style="font-family: verdana;">https://marketplace.visualstudio.com/items?itemName=MadsKristensen.Tweaks</span></a></p><p><span style="font-family: verdana;"><br /></span></p><p><span style="font-family: verdana;">Trailing Space Visualizer</span></p><p><a href="https://marketplace.visualstudio.com/items?itemName=MadsKristensen.TrailingWhitespaceVisualizer" target="_blank"><span style="font-family: verdana;">https://marketplace.visualstudio.com/items?itemName=MadsKristensen.TrailingWhitespaceVisualizer</span></a></p><p><span style="font-family: verdana;"><br /></span></p><p><span style="font-family: verdana;">Web Essentials</span></p><p><a href="https://marketplace.visualstudio.com/items?itemName=MadsKristensen.WebEssentials2019" target="_blank"><span style="font-family: verdana;">https://marketplace.visualstudio.com/items?itemName=MadsKristensen.WebEssentials2019</span></a></p><p><span style="font-family: verdana;"><br /></span></p><p><span style="font-family: verdana;">Const Visualiser</span></p><p><a href="https://marketplace.visualstudio.com/items?itemName=MattLaceyLtd.ConstVisualizer" target="_blank"><span style="font-family: verdana;">https://marketplace.visualstudio.com/items?itemName=MattLaceyLtd.ConstVisualizer</span></a></p><p><span style="font-family: verdana;"><br /></span></p><p><span style="font-family: verdana;">Warn About TODOs</span></p><p><a href="https://marketplace.visualstudio.com/items?itemName=MattLaceyLtd.WarnAboutTODOs" target="_blank"><span style="font-family: verdana;">https://marketplace.visualstudio.com/items?itemName=MattLaceyLtd.WarnAboutTODOs</span></a></p><p><span style="font-family: verdana;"><br /></span></p><p><span style="font-family: verdana;">Snippet Designer</span></p><p><a href="https://marketplace.visualstudio.com/items?itemName=vs-publisher-2795.SnippetDesigner" target="_blank"><span style="font-family: verdana;">https://marketplace.visualstudio.com/items?itemName=vs-publisher-2795.SnippetDesigner</span></a></p><p><span style="font-family: verdana;"><br /></span></p><p><span style="font-family: verdana;">Stack Trace Explorer</span></p><p><span style="font-family: verdana;"><a href="https://marketplace.visualstudio.com/items?itemName=SamirBoulema.StackTraceExplorer" target="_blank">https://marketplace.visualstudio.com/items?itemName=SamirBoulema.StackTraceExplorer</a></span></p><p><br /></p><p><span style="font-family: verdana;">I hope everyone got something out of this and found at least one extension that might be useful for them!</span></p>Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com0tag:blogger.com,1999:blog-1902158034220893892.post-11375290153252058772020-09-27T17:10:00.001+01:002020-09-27T17:10:17.551+01:00ASP.NET Bundling and http 403 Errors<p style="text-align: justify;"><span style="font-family: verdana;"> So I'm probably late to the game in running into this, but it bit me at work last week and I thought it was worth writing up...</span></p><p style="text-align: justify;"><span style="font-family: verdana;">I made a change to one of our internal websites that involved bringing in FontAwesome so I could use some of it's widgets. I downloaded the FontAwesome CSS and font files to serve them from our internal server, and I added them to my project under the Content folder, and I created a new StyleBundle that referenced the CSS file so I could get that sweet minification. I ran up the site on my laptop and there were my new widgets. Cool. I committed and pushed my changes, had my pull request accepted, and Azure DevOps deployed the new build to the server. I ran it up on the server - and my widgets weren't showing. But, but, but, it Works On My Machine. Time for some investigation.</span></p><p style="text-align: justify;"><span style="font-family: verdana;">My first stop was to look at the console in Chrome, where there was an important clue:</span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEig887HG_EgLdW55Z-blApEzVXbczr6gNHcYPTYrWJelfb1H9pdVuV2UKwwdANZ5YIUMcm_ZoGoRzHWKvkXj8kIxhPauT2MlryEa-HFjpXBg8K08CiWi9hHgDo-5MHcKXB6D8xSrvs23ebI/s956/Bundling1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: verdana;"><img border="0" data-original-height="78" data-original-width="956" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEig887HG_EgLdW55Z-blApEzVXbczr6gNHcYPTYrWJelfb1H9pdVuV2UKwwdANZ5YIUMcm_ZoGoRzHWKvkXj8kIxhPauT2MlryEa-HFjpXBg8K08CiWi9hHgDo-5MHcKXB6D8xSrvs23ebI/s320/Bundling1.png" width="320" /></span></a></div><span style="font-family: verdana;"><div style="text-align: justify;"><br /></div></span><div class="separator" style="clear: both; text-align: justify;"><span style="text-align: left;"><span style="font-family: verdana;">A http 403 error? But where was that coming from and how did it relate to FontAwesome? Step 2 in my investigation, look at the raw request in Fiddler and see where the 403 is coming from.</span></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo0ER7euIhkxStUZ7MvdeNLDYTgUwhCJzUkjzVCIWdM3V5cvc4Vs3mlw-XC2uBopVC_Kun0hWMDPkYlHnXgtN7SoKZd794m3OJq5a8AEpdKQUfePVkLx8uDEmWugsRvD1KB2BZKPNau8AV/s703/Bundling2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: verdana;"><img border="0" data-original-height="124" data-original-width="703" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo0ER7euIhkxStUZ7MvdeNLDYTgUwhCJzUkjzVCIWdM3V5cvc4Vs3mlw-XC2uBopVC_Kun0hWMDPkYlHnXgtN7SoKZd794m3OJq5a8AEpdKQUfePVkLx8uDEmWugsRvD1KB2BZKPNau8AV/s320/Bundling2.png" width="320" /></span></a></div><div style="text-align: justify;"><span style="font-family: verdana;"><br /></span></div><span style="font-family: verdana;"><div style="text-align: justify;">So, the first request produces a 301 result, which for those of you who haven't memorised the http status codes is 'Moved Permanently' and provides a Location in the response headers for the browser to redirect to. Notice in the Fiddler screenshot that the 301 result is generated by a request to /Content/FontAwesome, which corresponds to the name of my bundle, but the 403 result comes from /Content/FontAwesome/ - which corresponds with the path in my project that I put the FontAwesome CSS files into. </div></span><div><div style="text-align: justify;"><span style="font-family: verdana;">So, there's an issue with bundling when your bundle name matches a path in the file system, and the result is this 301-403 dance where your CSS files doesn't get loaded. And the solution is obvious - don't give your bundles a name that matches a path in the file system. In my case, I renamed my bundle from ~/Content/FontAwesome to ~/bundles/FontAwesome and all was right with the world.</span></div><div style="text-align: justify;"><span style="font-family: verdana;">Why did it work on my machine? Well, in one of those 'obvious in hindsight' things, I forgot that when you have debugging enabled in your web.config, ASP.NET bundling doesn't take effect and your files that would go through the bundling are actually served straight from the file system. When I ran my code locally without debugging, I saw the same behaviour on my machine. </span></div><div><div style="text-align: justify;"><span style="font-family: verdana;">Why did I pick a bundle name that matched the file system in the first place? Simple - I was following the same pattern as the boilerplate bundling code gives you for StyleBundles:</span></div><div style="text-align: justify;"><div><span style="font-family: courier;">bundles.Add(new StyleBundle("~/Content/css").Include(</span></div><div><span style="font-family: courier;"> "~/Content/bootstrap.css",</span></div><div><span style="font-family: courier;"> "~/Content/site.css"));</span></div><div style="font-family: verdana;"><br /></div><div style="font-family: verdana;">All the above relates to .Net Framework ASP.NET sites. What happens in ASP.NET Core and can you have the same issue? Well, if you go down the bundling route in ASP.NET Core, it works differently and your bundling code produces a file for you to include in your markup rather than a virtual directory. Which means there shouldn't be an issue of a virtual directory name clashing with a physical one. See the MSDN documentation for bundling <a href="https://docs.microsoft.com/en-us/aspnet/core/client-side/bundling-and-minification?view=aspnetcore-3.1" target="_blank">here</a>.</div></div></div></div>Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com0tag:blogger.com,1999:blog-1902158034220893892.post-90062682565985625092020-08-10T16:35:00.006+01:002020-08-11T13:32:40.653+01:00Linq vs Regex<p style="text-align: justify;"><span style="font-family: verdana;">I recently had to write a password validator as part of a technical test for a prospective employer, where three of the conditions were:</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: verdana;">Passwords must contain an upper case character</span></li><li><span style="font-family: verdana;">Passwords must contain a lower case character</span></li><li><span style="font-family: verdana;">Passwords must contain a number</span></li></ul><p></p><p style="text-align: justify;"><span style="font-family: verdana;">Having recently had occasion to learn that you can treat a string as a collection of characters and then use Linq to run set operations across the collection, in the test I used this code:</span></p><p><span style="font-family: courier;">password.Any(char.IsUpper)</span></p><p><span style="font-family: courier;">password.Any(char.IsLower)</span></p><p><span style="font-family: courier;">password.Any(char.IsDigit)</span></p><p><span style="font-family: verdana;">But I worked through the same test again yesterday as an exercise with a friend, and we used Regex instead, so the code became:</span></p><p><span style="font-family: courier;">new Regex(@"[A-Z]").IsMatch(password)</span></p><p><span style="font-family: courier;">new Regex(@"[a-z]").IsMatch(password)</span></p><div><p><span style="font-family: courier;">new Regex(@"[0-9]").IsMatch(password)</span></p></div><div style="text-align: justify;"><span style="font-family: verdana;">Plainly either version works; I don't see myself as a great Regex developer, which is partly why I reached for the Linq solution first. But seeing the solution written both ways I got to wondering if there was a performance benefit one way or the other. Clearly, there's only one way to find out...</span></div><div style="text-align: justify;"><span style="font-family: verdana;"><br /></span></div><div style="text-align: justify;"><span style="font-family: verdana;">I wrote up a console app that would use a Stopwatch to time each operation, and I ran it over 100 iterations and reported the average number of ticks taken (I started off measuring the number of milliseconds taken but this was zero...). </span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhH_TmGDZXrQeFWWi8N-B0QOfTCVu-oIHFMl9HUFjG4BETaDuv-mfQ9yzbF1MUmfj2tVD157TuAyfkYCdmP1M-wODxmhLnWlPf7jRkmHasOiuGmds2CqzITyNc9LDtf_uNfDAWI9Ll8mqR3/s1838/SetvsRegex1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1020" data-original-width="1838" height="284" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhH_TmGDZXrQeFWWi8N-B0QOfTCVu-oIHFMl9HUFjG4BETaDuv-mfQ9yzbF1MUmfj2tVD157TuAyfkYCdmP1M-wODxmhLnWlPf7jRkmHasOiuGmds2CqzITyNc9LDtf_uNfDAWI9Ll8mqR3/w512-h284/SetvsRegex1.png" width="512" /></a></div><span style="font-family: verdana;">And we can see that in two cases the Regex outperforms the Linq version, and in the third it's more or less even. Job done!</span></div><div><span style="font-family: verdana;"><br /></span></div><div><span style="font-family: verdana;">But... what happens if we up the number of iterations? Here's the same code run across 1 000, 10 000 and 1 000 000 iterations.</span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPQcr8mJYfh4k0FFLaj7lfUmIxqWQnv7U0vT4UxjD2NsRuqDessjAmDxyQeBU5I65SKU-0jygwX962QTvWVl3Gzq75J6epptkeKYmgxCSLGK_Xwf6iKFmpBfZu3JwrW56093Ovd2NVP9FW/s1838/SetvsRegex2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1020" data-original-width="1838" height="284" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPQcr8mJYfh4k0FFLaj7lfUmIxqWQnv7U0vT4UxjD2NsRuqDessjAmDxyQeBU5I65SKU-0jygwX962QTvWVl3Gzq75J6epptkeKYmgxCSLGK_Xwf6iKFmpBfZu3JwrW56093Ovd2NVP9FW/w512-h284/SetvsRegex2.png" width="512" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEis5JmtaD4ZMQKT7y97w0sbIWXteLQsfLOeWdAGNDHq2qJvom0o7UVHf4AwQUGpgFrm7Ke0ebL5Lw_muvqENtjGfuy8WTDaM96rG8-v5zWuQrX7raJOyWM_4Yb8psT2H9_gTbz53cIDmOM1/s1838/SetvsRegex3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1020" data-original-width="1838" height="284" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEis5JmtaD4ZMQKT7y97w0sbIWXteLQsfLOeWdAGNDHq2qJvom0o7UVHf4AwQUGpgFrm7Ke0ebL5Lw_muvqENtjGfuy8WTDaM96rG8-v5zWuQrX7raJOyWM_4Yb8psT2H9_gTbz53cIDmOM1/w512-h284/SetvsRegex3.png" width="512" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBBGTCrG-5CZno3c-rllrTG0hftuZJzId651BQmhy-2wqQEIE79T0jjo-Fx8hlHbVV5TlaL3FuC-H9U8B4JqzHM2qa7DCDqmbJzbp0CyhbfGImpVzEy3TiuAecr8bjFVpHGZhHCjtspUrR/s1838/SetvsRegex4.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1020" data-original-width="1838" height="284" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBBGTCrG-5CZno3c-rllrTG0hftuZJzId651BQmhy-2wqQEIE79T0jjo-Fx8hlHbVV5TlaL3FuC-H9U8B4JqzHM2qa7DCDqmbJzbp0CyhbfGImpVzEy3TiuAecr8bjFVpHGZhHCjtspUrR/w512-h284/SetvsRegex4.png" width="512" /></a></div><span style="font-family: verdana;"><div><span style="font-family: verdana;"><br /></span></div>Across more iterations, the Linq version performs faster!</span></div><div><span style="font-family: verdana;"><br /></span></div><div style="text-align: justify;"><span style="font-family: verdana;">So which should you use? Well, as with most things programming, it depends... It's important to remember that we're talking about differences of only a tick or two, measurements so small that your user won't notice. So with that in mind, we should think about other considerations, like our relative skill levels between Linq and Regex, and which version we find more accessible and readable. So for me, if I was making the choice I'd opt for the Linq versions; I tend to find Regex somewhat impenetrable. But you might make a different choice, and that's fine too.</span></div><div style="text-align: justify;"><span style="font-family: verdana;"><br /></span></div><div style="text-align: justify;"><span style="font-family: verdana;">If you want to try my code (and the performance might be different on your machine), my code is at <a href="https://github.com/philpursglove/LinqVsRegex">https://github.com/philpursglove/LinqVsRegex</a></span></div><div><span style="font-family: verdana;"><br /></span></div><div style="text-align: justify;"><span style="font-family: verdana;">(Aside: I was very pleasantly surprised to find the tooling support for writing Regexes in Visual Studio has massively improved, when you start writing your expression now you get Intellisense that shows you some of the options, and you get colour-coding inside your expression that helps you identify the parts of your expression)</span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCcNfo9NJ-wyYh7szshnhdfYRpbuHwhyphenhyphenYFgiJw7S0D7jlStzPMvERwib-58WZEQym7sbynrht7CsWBvVXz5Cmos0Jsp3DEclljODWRxOzJxl4VEIXb34f8o-6Y1OM8bxzDe7Y7_vl-kwUm/s361/RegexColourCoding.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="61" data-original-width="361" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCcNfo9NJ-wyYh7szshnhdfYRpbuHwhyphenhyphenYFgiJw7S0D7jlStzPMvERwib-58WZEQym7sbynrht7CsWBvVXz5Cmos0Jsp3DEclljODWRxOzJxl4VEIXb34f8o-6Y1OM8bxzDe7Y7_vl-kwUm/s0/RegexColourCoding.png" /></a></div><span style="font-family: verdana;"><br /></span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMr9ummguxUK9PoeukUI-AYbmqI2lz8X0_B8of5opijyEmp1QNjbkeue6ZP-WWdgL36PwsK3hQncOOu32aZpF7hFJMF_hQ-McAFVrzhN4vkxdQPmj6YllChso2iKiGMH8Us4W0H7KLXauQ/s600/RegexTooling.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="338" data-original-width="600" height="270" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMr9ummguxUK9PoeukUI-AYbmqI2lz8X0_B8of5opijyEmp1QNjbkeue6ZP-WWdgL36PwsK3hQncOOu32aZpF7hFJMF_hQ-McAFVrzhN4vkxdQPmj6YllChso2iKiGMH8Us4W0H7KLXauQ/w480-h270/RegexTooling.gif" width="480" /></a></div><span style="font-family: verdana;"><br /></span></div><div style="text-align: justify;"><span style="font-family: verdana;">Update: After I posted this, <a href="https://twitter.com/stevetalkscode" target="_blank">Steve</a> got in touch to say that compiled Regexes may offer a performance benefit. You specify that a Regex is compiled by adding an option into the constructor:</span></div><div><span style="font-family: courier;">new Regex("[A-Z]", RegexOptions.Compiled)</span></div><div style="text-align: justify;"><span style="font-family: verdana;">When a Regex is compiled, it is converted to MSIL and executed by the JIT compiler, and the MSIL is then cached by the regular expression engine. The price you pay for this is a longer startup time as the compilation happens, but then you get a faster execution. (Microsoft has <a href="https://docs.microsoft.com/en-us/dotnet/standard/base-types/best-practices" target="_blank">a whole article</a> on best practices for Regexes that covers this and some other considerations, and there's <a href="https://docs.microsoft.com/en-us/dotnet/standard/base-types/compilation-and-reuse-in-regular-expressions">another piece</a> about compilation and reuse of Regexes).</span></div><div style="text-align: justify;"><span style="font-family: verdana;">So let's kick the tyres on this... I added a switch to my code that allows you to switch compilation on and off. Here's some numbers over 100 iterations with compilation on.</span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIRWjBvUTeKpiDbRBHv4gDsLisgnvc-2vWlXmu_RP6OJdImzPJ_L_2TXjmad8aVK2mG2Lry2LNNDBb-gEqwarCwiGY1e3tXQ9G3bjVDjthoPZh46OdXugyyBhemURCZVzDZpSDP-Hvo5zH/s1838/SetvsRegex5.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1020" data-original-width="1838" height="284" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIRWjBvUTeKpiDbRBHv4gDsLisgnvc-2vWlXmu_RP6OJdImzPJ_L_2TXjmad8aVK2mG2Lry2LNNDBb-gEqwarCwiGY1e3tXQ9G3bjVDjthoPZh46OdXugyyBhemURCZVzDZpSDP-Hvo5zH/w512-h284/SetvsRegex5.png" width="512" /></a></div><div class="separator" style="clear: both; text-align: justify;"><span style="font-family: verdana;">We can see immediately that the startup impact of compiling the Regex adds an order of magnitude of overhead to our code (but remember that the practical impact of this is probably still only a matter of milliseconds), and over a relatively small number of iterations this means it will be significantly outperformed by the Linq solution. If we up the number of iterations, does paying that upfront cost return us any kind of performance dividend? Here's the same code over 1 000 000 iterations.</span></div></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhg6ruGOUyE8cFPjZn8dEV4OBUC_4a90BqFdmZkvZP9MMiCN53IMCiKG2oF2dRm4XEhkEm_Anzi6VPlT3ZNMk4lEIdAj6L872zpHk8TeuXeyhufPoWtActEjBFwvaV-osTPMXYgBGNkDxDI/s1838/SetvsRegex6.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1020" data-original-width="1838" height="284" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhg6ruGOUyE8cFPjZn8dEV4OBUC_4a90BqFdmZkvZP9MMiCN53IMCiKG2oF2dRm4XEhkEm_Anzi6VPlT3ZNMk4lEIdAj6L872zpHk8TeuXeyhufPoWtActEjBFwvaV-osTPMXYgBGNkDxDI/w512-h284/SetvsRegex6.png" width="512" /></a></div><div class="separator" style="clear: both; text-align: justify;"><span style="font-family: verdana;">Over more iterations, the upfront cost of compiling the Regex gets amortised down, but (on average) it still gets beaten by Linq (and I've also tried it over 10m and 100m iterations and this pattern remains consistent). </span></div><div class="separator" style="clear: both; text-align: justify;"><span style="font-family: verdana;">So Linq is consistently better, yes? Maybe, maybe not... For one thing, the Regexes I'm using are pretty simple - I have a sneaking suspicion that a compiled, more complex Regex would turn out to beat a number of chained Linq expressions. Some of the other <a href="https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-options">options</a> for Regex may also have an impact.</span></div><div class="separator" style="clear: both; text-align: justify;"><span style="font-family: verdana;"><br /></span></div><div class="separator" style="clear: both; text-align: justify;"><span style="font-family: verdana;">Steve also pointed me to <a href="https://benchmarkdotnet.org/" target="_blank">Benchmarkdotnet</a> to look at other aspects such as memory usage to get a fuller picture not only of which method looks better from the raw timings but also in terms of memory usage etc, which I may look at in a future post...</span></div>Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com0tag:blogger.com,1999:blog-1902158034220893892.post-58637846971266116322020-07-25T17:14:00.001+01:002020-07-25T17:14:25.249+01:00Controlling Your Costs With Azure Policy<div style="text-align: justify;"><span style="font-family: verdana;">I made a mistake. I've been trying to figure something out in Azure, and I needed a website to do it with, so I spun one up on a new App Service Plan. I missed that the default plan is a premium plan, and I only noticed this the other day. In the meantime, my site has been racking up charges, and as a result my Azure bill for July is going to be ... about £100. </span></div><div style="text-align: justify;"><font face="verdana"><br /></font></div><div style="text-align: justify;"><font face="verdana">Which is (kind of) fine, experience is the best teacher, it's my mistake and I'm going to own it. It's not a problem-causing amount of money for me. </font><span style="font-family: verdana;">And I'm not averse to spending that kind of money on Azure services </span><i style="font-family: verdana;">on purpose</i><span style="font-family: verdana;">, it's just not the sort of thing I want to be doing again by accident.</span></div><div style="text-align: justify;"><font face="verdana"><br /></font></div><div style="text-align: justify;"><font face="verdana">Fortunately, I know by using <a href="https://docs.microsoft.com/en-us/azure/governance/policy/" rel="nofollow" target="_blank">Azure Policy</a> that you can put all kinds of controls in Azure to stop people doing this sort of thing and ending up costing your company lots of money, so I've put the same kind of control in for myself.</font></div><div style="text-align: justify;"><font face="verdana"><br /></font></div><div style="text-align: justify;"><font face="verdana">What I need is a policy that stops me creating any more premium App Service Plans, and this is not that difficult to achieve.</font></div><div style="text-align: justify;"><font face="verdana"><br /></font></div><div style="text-align: justify;"><font face="verdana">Policies work on an 'if-then' model, you give the 'if' clause a set of conditions and if the set of conditions matches, then the 'then' clause fires. So in my case when I'm creating a new Azure resource my conditions will be: the resource type is an App Service Plan, and the SKU name is not set to 'F1', and my action will be to stop the action i.e. prevent the resource from being created.</font></div><div style="text-align: justify;"><font face="verdana"><br /></font></div><div style="text-align: justify;"><font face="verdana">Policies are written in JSON, you can write them directly in the Azure Portal, there is also <a href="https://docs.microsoft.com/en-us/azure/governance/policy/how-to/extension-for-vscode" target="_blank">a VSCode extension</a> to help you with creating them. Here's a skeleton policy:</font></div><br /><div><div style="line-height: 19px;"><div style="background-color: #fffffe; font-size: 14px; text-align: justify; white-space: pre;"><font face="courier"><span style="color: #a31515;">"policyRule"</span>: {</font></div><div style="background-color: #fffffe; font-size: 14px; text-align: justify; white-space: pre;"><font face="courier"> <span style="color: #a31515;">"if"</span>: {</font></div><div style="background-color: #fffffe; font-size: 14px; text-align: justify; white-space: pre;"><font face="courier"> }</font></div><div style="background-color: #fffffe; font-size: 14px; text-align: justify; white-space: pre;"><font face="courier"> },</font></div><div style="background-color: #fffffe; font-size: 14px; text-align: justify; white-space: pre;"><font face="courier"> <span style="color: #a31515;">"then"</span>: {</font></div><div style="background-color: #fffffe; font-size: 14px; text-align: justify; white-space: pre;"><font face="courier"> <span style="color: #a31515;">"effect"</span>: <span style="color: #0451a5;">""</span></font></div><div style="background-color: #fffffe; font-size: 14px; text-align: justify; white-space: pre;"><font face="courier"> }</font></div><div style="background-color: #fffffe; font-size: 14px; text-align: justify; white-space: pre;"><font face="courier"> }</font></div><div style="line-height: 19px;"><br /></div><font face="verdana"><div style="text-align: justify;">Effects can be any of a number of values, including "deny" which disallows the action completely, "audit" which allows the action but logs that your policy is being violated, and a number of others including some that will change your action to make it comply with your policy.</div></font></div><div style="line-height: 19px;"><br /><div style="text-align: justify;"><span style="font-family: verdana;">So clearly the effect in my then clause needs to be "deny", so that it correctly prevents the action. Which leaves me to work out what the correct if clause is. As I said above, I have two conditions, so I'll be using the allof condition which translates to an AND operator (there is also anyof which is the equivalent of OR). My first condition is that I want the policy to act on App Service Plans, so I'll need to be looking at the type of thing that's being created. Policies use a system of aliases for types (with namespaces), there are two ways to find the alias you want. The hard(er) way is to use the Azure command-line tool to query a list of available aliases as suggested in the </span><a href="https://docs.microsoft.com/en-us/azure/governance/policy/tutorials/create-custom-policy-definition#find-the-property-alias" style="font-family: verdana;">documentation</a><span style="font-family: verdana;"> e.g.</span></div></div></div><div style="line-height: 19px;"><font face="verdana"><br /></font></div><div style="line-height: 19px;"><font face="courier">az provider show --namespace Microsoft.Web --expand "resourceTypes/aliases" --query "resourceTypes[].aliases[].name"</font></div><div style="line-height: 19px;"><font face="verdana"><br /></font></div><div style="line-height: 19px; text-align: justify;"><font face="verdana">The easy way is to go through the resource creation process in the Azure portal, through to the 'Review and Create' step. Once there, don't create the resource, but download the ARM template, and then search through it for the 'resources' element; inside the resources element, look for a 'type' property, and the value of the property is the alias you want. Which tells me that for an App Service Plan, the alias I should be using is 'Microsoft.Web/serverfarms'. On to the SKU value! I need to look at a property of a serverfarms object and check whether or not the value is 'F1' (the name of the free tier). And if we go back to the command-line query and browse the results, we can see that under Microsoft.Web/serverfarms there is a sku.name property; we can use that with a 'notEquals' operator to check the value.</font></div><div style="line-height: 19px;"><font face="verdana"><br /></font></div><div style="line-height: 19px;"><font face="verdana">So our whole policy looks like this:</font></div><div style="line-height: 19px;"><font face="verdana"><br /></font></div><div style="line-height: 19px;"><div style="line-height: 19px;"><font face="courier">"policyRule": {</font></div><div style="line-height: 19px;"><font face="courier"> "if": {</font></div><div style="line-height: 19px;"><font face="courier"> "allof": [</font></div><div style="line-height: 19px;"><font face="courier"> {</font></div><div style="line-height: 19px;"><font face="courier"> "field": "type",</font></div><div style="line-height: 19px;"><font face="courier"> "equals": "Microsoft.Web/serverfarms"</font></div><div style="line-height: 19px;"><font face="courier"> },</font></div><div style="line-height: 19px;"><font face="courier"> {</font></div><div style="line-height: 19px;"><font face="courier"> "field": "Microsoft.Web/serverfarms/sku.name",</font></div><div style="line-height: 19px;"><font face="courier"> "notEquals": "F1"</font></div><div style="line-height: 19px;"><font face="courier"> }</font></div><div style="line-height: 19px;"><font face="courier"> ]</font></div><div style="line-height: 19px;"><font face="courier"> },</font></div><div style="line-height: 19px;"><font face="courier"> "then": {</font></div><div style="line-height: 19px;"><font face="courier"> "effect": "deny"</font></div><div style="line-height: 19px;"><font face="courier"> }</font></div><div style="line-height: 19px;"><font face="courier"> }</font></div></div><div style="line-height: 19px;"><font face="verdana"><br /></font></div><div style="line-height: 19px;"><font face="verdana">I applied this policy to my subscription, and here's what happens if I now try to create a premium service plan.</font></div><div style="line-height: 19px;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7CGZZ3dwrb9p4aCgp85dSg6PxmosUbmlRAbwiXBcp4oI3ry7IddG-as_MvMDMndUKNP_QJkDNWgw9BHnvP0zv2UpjLVcxSgKodOveYp4YITo_WXW2GJW1VSjGkQgEjA_51ViIYdpyv2hM/s1593/Azure+Policy+Portal.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1593" data-original-width="1246" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7CGZZ3dwrb9p4aCgp85dSg6PxmosUbmlRAbwiXBcp4oI3ry7IddG-as_MvMDMndUKNP_QJkDNWgw9BHnvP0zv2UpjLVcxSgKodOveYp4YITo_WXW2GJW1VSjGkQgEjA_51ViIYdpyv2hM/s320/Azure+Policy+Portal.png" /></a></div><font face="verdana"><br /></font></div><div style="line-height: 19px;"><font face="verdana">Note that the policy evaluation happens in the review stage, before the resource is created.</font></div><div style="line-height: 19px;"><font face="verdana"><br /></font></div><div style="line-height: 19px;"><font face="verdana">We've looked here at creating a basic (but useful!) Azure policy to restrict creation of a premium Azure resource, and you can apply that to your own subscriptions to help keep you from making the same mistake I did. And this is only a taste of what you can achieve with Azure Policy.</font></div><div style="line-height: 19px;"><font face="verdana"><br /></font></div><div style="line-height: 19px;"><font face="verdana">(And now I'm protected from accidentally creating any more premium App Service Plans - but I could create a premium database, or a storage account, or a VM... Hmm, maybe I need to go write some more policies...)</font></div>Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com0tag:blogger.com,1999:blog-1902158034220893892.post-86777492389184369652020-04-23T15:44:00.000+01:002020-04-23T16:06:04.095+01:00Reading and Writing Azure KeyVault Secrets with C#<div style="text-align: justify;">
<span style="font-family: "verdana" , sans-serif;">Every application has secrets of one kind or another; database connection strings, API keys or other credentials are all common examples and you can probably think of others without having to try too hard. So every application needs to be able to store, read, update and remove secrets. </span></div>
<div style="text-align: justify;">
<span style="font-family: "verdana" , sans-serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: "verdana" , sans-serif;">Azure KeyVault is the Azure store for securely storing and accessing secrets, in this blog I'm going to go through how to setup a C# application to get your secrets in and out of KeyVault.</span></div>
<span style="font-family: "verdana" , sans-serif;"><br /></span>
<span style="font-family: "verdana" , sans-serif;">So I've set up a KeyVault through the Azure portal, and I've added a secret to it.</span><br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiIDgI2DbN257t6FOd9qDd5RJZbG-3P6f1W1TU-SV31utUERYpgAUYrMod9B9xrLFQWsh3m0fi6S-XQaCJMYLLu-xI-KGbu-825-gPktXZ0Y5RhPeuLBQzirMdFyAS_QCHSmvVB-JFqH5w/s1600/KeyVault1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="239" data-original-width="1600" height="56" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiIDgI2DbN257t6FOd9qDd5RJZbG-3P6f1W1TU-SV31utUERYpgAUYrMod9B9xrLFQWsh3m0fi6S-XQaCJMYLLu-xI-KGbu-825-gPktXZ0Y5RhPeuLBQzirMdFyAS_QCHSmvVB-JFqH5w/s400/KeyVault1.png" width="400" /></a></div>
<span style="font-family: "verdana" , sans-serif;"><br /></span>
<br />
<div style="text-align: justify;">
<span style="font-family: "verdana" , sans-serif;">The next thing we need to do is set up a principal in Azure Active Directory; this will give our application a context by which it will be able to access the KeyVault. This can also be done through the Azure portal by entering 'Active Directory' in the top search bar. Once in the AD blade, you need to create a new app registration, so click on 'App Registrations' in the menu and then click 'New Registration'. You'll need to enter at a minimum a name for your registration, and you can optionally enter a URI that receives an authentication token. I'm not entering one here as my demo will just be a console application, but you might need one depending on your individual applications. Note that if you do enter a URI, it must be either secured by SSL e.g. https, or it must be a http://localhost address.</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTJ-UtaxmuOCPDvGceBMVUOp8j4nYLOMDqawTh3dwpadGkKfJ80tzVrRrXE9YD5-YTviyabbo89pTfbA-Fe_PlkhIPclhEf89jvbLFCfSGQYSYJptd71U4Xr_fTk2V852qY7GXqjPhkHqj/s1600/KeyVault2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1045" data-original-width="1600" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTJ-UtaxmuOCPDvGceBMVUOp8j4nYLOMDqawTh3dwpadGkKfJ80tzVrRrXE9YD5-YTviyabbo89pTfbA-Fe_PlkhIPclhEf89jvbLFCfSGQYSYJptd71U4Xr_fTk2V852qY7GXqjPhkHqj/s320/KeyVault2.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: "verdana" , sans-serif;"><br /></span>
<span style="font-family: "verdana" , sans-serif;">Once the registration is created, you'll see it in the portal. You can see the clientId here, which we'll need later.</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw4gysrzQRFY33RtfMmNEv8n9flqmP0-YrdwhzNMlHZVRRx9PPkcBeAR1E4twvZLpi9wyGzaKJKWn5Sl8W1ZhlBMqMAHnSMp6Bg6hOpnfQL0FruaRW4h1zlbNxj1Iqn17eITiI4frcFVDQ/s1600/KeyVault3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="550" data-original-width="1411" height="124" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw4gysrzQRFY33RtfMmNEv8n9flqmP0-YrdwhzNMlHZVRRx9PPkcBeAR1E4twvZLpi9wyGzaKJKWn5Sl8W1ZhlBMqMAHnSMp6Bg6hOpnfQL0FruaRW4h1zlbNxj1Iqn17eITiI4frcFVDQ/s320/KeyVault3.png" width="320" /></a></div>
<div style="text-align: justify;">
<span style="font-family: "verdana" , sans-serif;">We'll also need to create a secret that our application will use to prove its identity to AzureAD when we try to request an authentication token. (Think of the clientId and secret as being like a username/password combination). Click on Certificates and Secrets in the menu, and then click the New Client Secret button. Enter a description and how long the secret should be valid for, and create the new secret. Like the clientId, we'll need the secret later, so make a note of it now as you will not be able to view it later on.</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhv9NFMcjS8v8u4aI6bwcfXJvU9ump2xexsX4dOyvU3aysML26HqToh-0uct2mSRl5MUTNke2vH9VCr79J0o9vYkb2Z91U5wrKXsw3BsO56e30jHpNDoN41AHhKMva3WsNEV1g0sD2pv5tM/s1600/KeyVault4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="260" data-original-width="1600" height="51" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhv9NFMcjS8v8u4aI6bwcfXJvU9ump2xexsX4dOyvU3aysML26HqToh-0uct2mSRl5MUTNke2vH9VCr79J0o9vYkb2Z91U5wrKXsw3BsO56e30jHpNDoN41AHhKMva3WsNEV1g0sD2pv5tM/s320/KeyVault4.png" width="320" /></a></div>
<div style="text-align: justify;">
<span style="font-family: "verdana" , sans-serif;">With the App Registration setup, we now need to associate that with the KeyVault. Return to your KeyVault in the portal, and click Access Policies in the menu. To allow the app to access the KeyVault, click the Add Access Policy link. Here you can set the permissions that your app will have against your vault. There are a set of predefined templates you can use, or you can assign individual permissions. For now, I just want to read and write secrets, so in the Secret Permissions dropdown I'll just select Get/List/Set/Delete.</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNGPdg2WZivP6MaFF1WYnKE3rFD4yauqWCJDNuT2lhmxAncgdZpMWNInlbAgIj6qoVbMj3E-1GSF8_8fvptUlwKhoPAB4Am7PJPI1_q4xmdPgZdu0HB0DyOsZKwfJZQcD0i2v1CNaeUpHV/s1600/KeyVault5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="790" data-original-width="1277" height="197" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNGPdg2WZivP6MaFF1WYnKE3rFD4yauqWCJDNuT2lhmxAncgdZpMWNInlbAgIj6qoVbMj3E-1GSF8_8fvptUlwKhoPAB4Am7PJPI1_q4xmdPgZdu0HB0DyOsZKwfJZQcD0i2v1CNaeUpHV/s320/KeyVault5.png" width="320" /></a></div>
<div style="text-align: justify;">
<span style="font-family: "verdana" , sans-serif;">With the permissions selected, you need to associate them with the principal we created in Active Directory. Click Select Principal to open the blade. You'll see a whole set of standard principals, so the easiest way to find the correct principal is to enter the name in the search box.</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDJ0lTJB9903QKUSK-oAnOoVkPrRo-TYuQVuB4btbnN3BUM73ZnBL0rOgUfLubRPSsz096l9QPUZ45qwY5VHUdcfZLdqZSe6oCuBq6-F37DLJHRXe9lI6qbpBZzLml1nRzy5a7I-r8H97V/s1600/KeyVault6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="738" data-original-width="767" height="307" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDJ0lTJB9903QKUSK-oAnOoVkPrRo-TYuQVuB4btbnN3BUM73ZnBL0rOgUfLubRPSsz096l9QPUZ45qwY5VHUdcfZLdqZSe6oCuBq6-F37DLJHRXe9lI6qbpBZzLml1nRzy5a7I-r8H97V/s320/KeyVault6.png" width="320" /></a></div>
<span style="font-family: "verdana" , sans-serif;">Once you've selected the principal, click Add to close the blade. And then click Save to save your application's access policy.</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlrZ5viA4v1njv-7a7SBb0zypR9mEtwjA1vnbXInVQzTefcrCgOvGCL0QBGavwhgkNIM4J1lzPJxeQ5CdNV-EEFgQI5__5Xeo19dB-sDet5esWpS12GbsQTkEvY_MLcEbcozVSSBN8xoKP/s1600/KeyVault7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="189" data-original-width="757" height="79" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlrZ5viA4v1njv-7a7SBb0zypR9mEtwjA1vnbXInVQzTefcrCgOvGCL0QBGavwhgkNIM4J1lzPJxeQ5CdNV-EEFgQI5__5Xeo19dB-sDet5esWpS12GbsQTkEvY_MLcEbcozVSSBN8xoKP/s320/KeyVault7.png" width="320" /></a></div>
<span style="font-family: "verdana" , sans-serif;"><br /></span>
<br />
<div style="text-align: justify;">
<span style="font-family: "verdana" , sans-serif;">With all that prep work done, we can go write some code!</span></div>
<div style="text-align: justify;">
<span style="font-family: "verdana" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "verdana" , sans-serif;">In Visual Studio, start a new .NET Core Console app, and add the Nuget packages Microsoft.Azure.KeyVault and Microsoft.IdentityModel.Clients.ActiveDirectory to it. </span></div>
<div style="text-align: justify;">
<span style="font-family: "verdana" , sans-serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: "verdana" , sans-serif;">The KeyVaultClient class is what we'll use to perform operations against the vault; it has a number of different constructors depending on your scenario, the one I'm using takes an AuthenticationCallback delegate. </span></div>
<span style="font-family: "courier new" , "courier" , monospace;">KeyVaultClient vaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(Program.GetToken));</span><br />
<span style="font-family: "verdana" , sans-serif;"><br /></span>
<br />
<div style="text-align: justify;">
<span style="font-family: "verdana" , sans-serif;">The GetToken method's signature must match what the delegate expects - three string parameters for authority, resource and scope, and, probably because I don't deal with delegates very often, this was the part of this I found the most confusing as I couldn't see where they were coming from. The answer is that they are filled in by the callback at runtime, you don't need to supply the values yourself at any point. This is also where the clientId and secret we created earlier come in. Here's a sample GetToken method.</span></div>
<span style="font-family: "courier new" , "courier" , monospace;">private static async Task<string> GetToken(string authority, string resource, string scope)</string></span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> ClientCredential credential = new ClientCredential(clientId, clientSecret);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> var context = new AuthenticationContext(authority, TokenCache.DefaultShared);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> var result = await context.AcquireTokenAsync(resource, credential);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> return result.AccessToken;</span><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="font-family: "verdana" , sans-serif;"><br /></span>
<br />
<div style="text-align: justify;">
<span style="font-family: "verdana" , sans-serif;">Once we have a KeyVaultClient instance, we can start to query our vault. Your goto methods are most likely to be GetSecretsAsync, GetSecretAsync and SetSecretAsync, but there's a whole raft of methods for managing keys, secrets and certificates. GetSecretAsync returns a SecretBundle, of which the most relevant property is the actual value of the secret. Calling SetSecretAsync will create a new version of a secret; this will include creating the secret if it doesn't already exist in your vault, and it will also create a new version even if you set it to the same value as it already holds (GetSecretAsync also has an overload that allows you to specify a version identifier). So putting it all together here's what our console app looks like.</span></div>
<span style="font-family: "verdana" , sans-serif;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">class Program</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> static string clientId = "myClientId";</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> static string clientSecret = "myClientSecret";</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> static async Task Main(string[] args)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> KeyVaultClient vaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(Program.GetToken));</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> string vaultAddress = "https://myVaultUrl";</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> string secretName = "secret1";</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> var secret = await vaultClient.GetSecretAsync(vaultAddress, secretName);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> Console.WriteLine($"Current secret value: {secret.Value}");</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> Console.ReadLine();</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> private static async Task<string> GetToken(string authority, string resource, string scope)</string></span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> ClientCredential credential = new ClientCredential(clientId, clientSecret);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> var context = new AuthenticationContext(authority, TokenCache.DefaultShared);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> var result = await context.AcquireTokenAsync(resource, credential);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> return result.AccessToken;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtQVLN88yOuYkTlP4-ebVdwIIzQJng_T0EPg2zdp3zULRV_uGh7-Us28RCUtaX-Kh5C32odoOqS9igvEgkKKz1D_EsUxQipJfLJFI1LHCUkCdXR_0IdCd4Ej-AOQHcPAMR0sjDw6PEb9iH/s1600/KeyVault8%255D.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="888" data-original-width="1600" height="177" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtQVLN88yOuYkTlP4-ebVdwIIzQJng_T0EPg2zdp3zULRV_uGh7-Us28RCUtaX-Kh5C32odoOqS9igvEgkKKz1D_EsUxQipJfLJFI1LHCUkCdXR_0IdCd4Ej-AOQHcPAMR0sjDw6PEb9iH/s320/KeyVault8%255D.png" width="320" /></a></div>
<div>
<span style="font-family: "verdana" , sans-serif;">And if I refer back to my vault, you can see that the value of secret1 is indeed 'it's a secret'</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-emNtM_Z2awdbpjRsTSf09ypOI17o-JultQeWVmNlPasDyHo_HRTJAeWNQ86M4NxVWoNZqu0JcnUHz5YBrkrHpBFsGqgcaPe35ZCiHy2Wv0vRL0ryVinKcwIOEJUZxOQ3Avz3_ze8ziNU/s1600/KeyVault9.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1427" data-original-width="914" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-emNtM_Z2awdbpjRsTSf09ypOI17o-JultQeWVmNlPasDyHo_HRTJAeWNQ86M4NxVWoNZqu0JcnUHz5YBrkrHpBFsGqgcaPe35ZCiHy2Wv0vRL0ryVinKcwIOEJUZxOQ3Avz3_ze8ziNU/s320/KeyVault9.png" width="204" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
<span style="font-family: "verdana" , sans-serif;">So, in this blog we've seen how to create a console application that authenticates against Azure Active Directory and then reads and writes secrets to and from Azure KeyVault. </span></div>
<div class="separator" style="clear: both; text-align: justify;">
<span style="font-family: "verdana" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: justify;">
<span style="font-family: "verdana" , sans-serif;">I've created a Github repo at <a href="https://github.com/philpursglove/KeyVaultDemo" target="_blank">https://github.com/philpursglove/KeyVaultDemo</a> with a complete solution for listing, creating, updating and deleting your KeyVault secrets.</span></div>
<div>
<br /></div>
Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com0tag:blogger.com,1999:blog-1902158034220893892.post-41990295514763922172015-01-01T21:20:00.000+00:002015-01-01T21:20:33.386+00:00Introducing Threepio!<blockquote class="twitter-tweet" lang="en">
Sign up now to get early access to the API: <a href="http://t.co/CscaWn9fbJ">http://t.co/CscaWn9fbJ</a><br />
— Star Wars (@swapico) <a href="https://twitter.com/swapico/status/540848341178150912">December 5, 2014</a></blockquote>
<br />
<span style="font-family: Verdana, sans-serif;">I saw this a few weeks ago and thought 'That might be interesting', since it seems to combine two of my favourite things, Star Wars and code, so I signed up. On 21st December beta access to the API was opened up, and I started having a look at it. Almost immediately, a set of helper libraries appeared for different stacks (Javascript, Ruby, even PHP), but none for .net. So I sprang into action (well, it was more of a lurch really) and started to put together some C#, and over the Christmas break I've finished it (or at least I have it at a point where I'm prepared for other people to look at it).</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">It's written in C(#), and it translates from JSON into .net objects, so I had to call it Threepio...</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">The code is on Github at <a href="https://github.com/philpursglove/Threepio">https://github.com/philpursglove/Threepio</a>.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Things I want to look at/think about doing:</span><br />
<br />
<ul>
<li><span style="font-family: Verdana, sans-serif;">Should the GetPage methods return IEnumerable<t> instead of List<t>?</t></t></span></li>
<li><span style="font-family: Verdana, sans-serif;">The <t>Get(id) methods throw an exception if you call them with an invalid id, inline with <a href="http://geekswithblogs.net/mrsteve/archive/2014/12/31/naming-things-is-hard-method-naming-patterns.aspx" target="_blank">this</a> which I read yesterday would it be better to change them to TryGet?</t></span></li>
<li><span style="font-family: Verdana, sans-serif;">Putting up a Nuget package.</span></li>
</ul>
<br />
<script async="" charset="utf-8" src="//platform.twitter.com/widgets.js"></script>Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com0tag:blogger.com,1999:blog-1902158034220893892.post-53405535354353686912014-04-13T12:59:00.000+01:002014-04-14T10:25:13.422+01:00Book Clearout<span style="font-family: Verdana, sans-serif;">I had a tidy-up and spring clean of my home office yesterday, and I cleared a lot of books of my shelves. Before they go to the tip for recycling, here's a list of what I cleared. If anyone wants any of these, let me know by 18th April.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><strike>A Programmers Introduction to C#, Eric Gunnerson</strike></span><br />
<span style="font-family: Verdana, sans-serif;">Visual C# Language Reference</span><br />
<span style="font-family: Verdana, sans-serif;">Programming ASP.NET 2.0 Advanced Topics 2005 Ed, Dino Esposito</span><br />
<span style="font-family: Verdana, sans-serif;"><strike>Debugging .NET 2.0 Apps, John Robbins</strike></span><br />
<span style="font-family: Verdana, sans-serif;"><strike>Javascript: The Definitive Guide 4th Ed, David Flanagan</strike></span><br />
<span style="font-family: Verdana, sans-serif;">ASP.NET 2.0 Cookbook, Geoffrey LeBlond</span><br />
<span style="font-family: Verdana, sans-serif;">Essential ASP.NET 2.0, Fritz Onion</span><br />
<span style="font-family: Verdana, sans-serif;">nHibernate in Action, Pierre Kuate</span><br />
<span style="font-family: Verdana, sans-serif;">ASP.NET 2.0 Server Control & Component Development, Shahram Khosravi<br />
<span style="font-family: Verdana, sans-serif;"><strike>The Definitive Guide to The Microsoft Enterprise Library, Keenan Newton</strike></span><br />
<span style="font-family: Verdana, sans-serif;">ASP.NET 2.0 Anthology, Jeff Atwood</span><br />
<span style="font-family: Verdana, sans-serif;">ADO.NET & ADO Examples and Best Practices, Bill Vaughn</span><br />
<span style="font-family: Verdana, sans-serif;">Pro ASP.NET MVC 1.0, Scott Hanselman</span><br />
<span style="font-family: Verdana, sans-serif;">Building a Web 2.0 Portal w/ASP.NET 3.5, Omar Al-Zabir</span><br />
<span style="font-family: Verdana, sans-serif;"><strike>Designing and Developing Web-Based Applications Using the .NET Framework, Mike Snell</strike></span><br />
<span style="font-family: Verdana, sans-serif;">Distributed .NET Programming in VB.NET, Tom Barnaby</span><br />
<span style="font-family: Verdana, sans-serif;">Applied ADO.NET, Mahesh Chand</span><br />
<span style="font-family: Verdana, sans-serif;">Developing ASP.NET Server Controls & Components, Nikhil Kothari</span><br />
<span style="font-family: Verdana, sans-serif;"><strike>Enterprise Development with Visual Studio.NET, UML & MSF, John Erik Hansen</strike></span><br />
<span style="font-family: Verdana, sans-serif;">Inside VS.NET 2003, Brian Johnson</span></span>Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com0tag:blogger.com,1999:blog-1902158034220893892.post-58156142548601800162014-02-19T11:51:00.000+00:002014-02-19T11:54:59.404+00:0064-bit Considered Harmful...<span style="font-family: Verdana, sans-serif;">Thought I should write about a problem I ran into last month in the hope that it saves someone else some heartache (or potentially someone tells me how to fix it...)</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">A few weeks ago, while I was searching for something else in Visual Studio's Settings, I ran across this option:</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWSpXUvlOSYDh7eIaye6jjbbxp3bo2oKXZv8UYKiNHjI1OR-CxKsEc0ml6ia0g2_nUJNU0SoTyB8q-DXh2L8tl5PQQK6ITX3iW2wzrQfnublEKAOLtCs-GIm0n-brLy1-SEDPKqqHVHwde/s1600/64BitIISExpress.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWSpXUvlOSYDh7eIaye6jjbbxp3bo2oKXZv8UYKiNHjI1OR-CxKsEc0ml6ia0g2_nUJNU0SoTyB8q-DXh2L8tl5PQQK6ITX3iW2wzrQfnublEKAOLtCs-GIm0n-brLy1-SEDPKqqHVHwde/s1600/64BitIISExpress.png" height="232" width="400" /></a></div>
<span style="font-family: Verdana, sans-serif;">I run on 64-bit Windows, so I figured this would be a sensible option to set and switched it on. And all was good in the world.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Until I started on a new project a couple of weeks later, that is, when running it up for the first time I was puzzled to see this YSOD:</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6x8x7YiEppvCj6XIpVO9m_ErdKYzroiKfH-2Y12DTvb6BWcsxkdyS-Pb9YYhwYLHyMFzZDcLylFlkm9frJW3hYbQq_Qupj2s7IBENpMJ69_H49458s3m6oD4aIadqtVx8n86voZKpgjAB/s1600/64BitIISConsideredHarmful.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6x8x7YiEppvCj6XIpVO9m_ErdKYzroiKfH-2Y12DTvb6BWcsxkdyS-Pb9YYhwYLHyMFzZDcLylFlkm9frJW3hYbQq_Qupj2s7IBENpMJ69_H49458s3m6oD4aIadqtVx8n86voZKpgjAB/s1600/64BitIISConsideredHarmful.png" height="223" width="400" /></a></div>
<span style="font-family: Verdana, sans-serif;">Invalid program? What the hell's that coming from? The only thing that I could immediately think of was that the last thing I did before hitting F5 was to install Ninject. I cast around for an hour or so trying assorted types of restarting processes/PCs etc, before going to Twitter...</span><br />
<br />
<blockquote class="twitter-tweet" lang="en-gb">
With <a href="https://twitter.com/search?q=%23ninject&src=hash">#ninject</a>, has anyone seen this error? 'Common Language Runtime detected an invalid program.' More importantly, anyone know how 2 fixit<br />
— Phil Pursglove (@philpursglove) <a href="https://twitter.com/philpursglove/statuses/425269013871333376">January 20, 2014</a></blockquote>
<script async="" charset="utf-8" src="//platform.twitter.com/widgets.js"></script><span style="font-family: Verdana, sans-serif;"><a href="http://geekswithblogs.net/franhoey/Default.aspx" target="_blank">Fran</a> quickly replied with this:</span><br />
<br />
<blockquote class="twitter-tweet" data-conversation="none" lang="en-gb">
<a href="https://twitter.com/philpursglove">@philpursglove</a> ... yes, but I cant remember the details. Sounds a bit like a 32bit app/dll trying to reference a 64bit dll?<br />
— Fran Hoey (@franhoey) <a href="https://twitter.com/franhoey/statuses/425269619419807744">January 20, 2014</a></blockquote>
<script async="" charset="utf-8" src="//platform.twitter.com/widgets.js"></script><span style="font-family: Verdana, sans-serif;">
which was the clue I needed:
</span><br />
<blockquote class="twitter-tweet" data-conversation="none" lang="en-gb">
<a href="https://twitter.com/franhoey">@franhoey</a> ooh, you might be onto something there - let me check... // <a href="https://twitter.com/brightoniant">@brightoniant</a><br />
— Phil Pursglove (@philpursglove) <a href="https://twitter.com/philpursglove/statuses/425270099579523072">January 20, 2014</a></blockquote>
<script async="" charset="utf-8" src="//platform.twitter.com/widgets.js"></script><span style="font-family: Verdana, sans-serif;">
And yep, as soon as I turned off 64-bit IIS Express the world righted itself...</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">So I'm interested to know what causes this and whether there's a way to successfully run Ninject in 64-bit code (I'm quite prepared for this to be something related to my inexperience with Ninject).</span><br />
<br />Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com1tag:blogger.com,1999:blog-1902158034220893892.post-87042417530079638912012-03-16T14:29:00.000+00:002012-03-16T14:29:32.842+00:00GiveCamp<br />
<b><span style="font-family: Verdana, sans-serif;">What’s A GiveCamp? </span></b><br />
<span style="font-family: Verdana, sans-serif;">I spent the weekend of 21st-23rd October last year working for charity at GiveCamp. What’s a GiveCamp? Givecamp is an event where technology experts give their time over a weekend to build projects for charities. It’s funded by corporate sponsorship, which means it’s free to attend for both the charities and the volunteers. The concept originates from Microsoft in Texas in 2007 – since then over $1m worth of time and consultancy has been donated. In 2011, GiveCamp UK was the first GiveCamp to be held outside the USA. I got involved through knowing the organisers; many of my friends from the UK Microsoft programming community were also there. </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span><br />
<b><span style="font-family: Verdana, sans-serif;">How Does It Work? </span></b><br />
<span style="font-family: Verdana, sans-serif;">We assembled at UCL’s Bloomsbury Campus on the afternoon of 21st October, where there was a chance for a cup of coffee and a gossip with people while we waited to find out where we needed to be. At about 5pm we all trooped into a lecture theatre, where representatives from a set of charities each delivered a short pitch about their charity, and more importantly, the project they wanted people to tackle over the weekend. In the main room, there was a chance to speak to the charity reps again to get more detail on their project, and everybody gradually organised themselves into teams. </span><br />
<span style="font-family: Verdana, sans-serif;">I chose to work with a charity called <a href="http://www.sceneandheard.org/" target="_blank">Scene And Heard</a> , who run playwriting courses for children – the plays the children write are then performed by volunteer professional actors. The project that Scene And Heard pitched for was to build them a ticketing system. As we got into the detail of their requirements, we all realised that rather than building a system for them ourselves, we could set them up with an account on EventBrite, which is a website that provides ticketing services for events. And EventBrite wouldn’t cost them anything to use. Score! And even better, at that point the catered dinner arrived! </span><br />
<span style="font-family: Verdana, sans-serif;">Having such a quick and easy win for us was a great boost for our team, and, fortified by yummy sausages and mash, it meant we could go back to Scene And Heard and say ‘what else can we do for you?’. It transpired that they were managing their lists of volunteers, plays and performances in a set of Excel spreadsheets and, in their own words ‘a car-crash Access database’. This, then, would be our project for the rest of the weekend – to meld all these elements into a single, web-based database. We started to explore some initial options using a new Microsoft technology called Lightswitch up to about midnight on Friday night. </span><br />
<span style="font-family: Verdana, sans-serif;">On Saturday morning we arrived back at our table in dribs and drabs, but were greeted by a cornucopia of bacon sandwiches, sausage sandwiches and pastries! I found I’d made exactly the right decision to stay at the Premier Inn round the corner – some people had elected to take the ‘camp’ part of GiveCamp quite seriously and there was a large room full of tents and sleeping bags, however it seemed that one of the campers was an epic snorer, and there were several bleary-eyed developers to be seen. </span><br />
<span style="font-family: Verdana, sans-serif;">Fuelled by the aforementioned breakfast and endless cups of coffee and tea, we were all back at our table and working by 10am, however we were all starting to struggle with problems with Lightswitch, in part because none of us had used it before. After a lunch of delicious burritos, at about 2pm, we had a stand-up where we reviewed the progress we’d made and discussed the problems we were having (a stand-up is a short project status meeting (that is held standing up to remind people to keep the meeting short)). </span><br />
<span style="font-family: Verdana, sans-serif;">The various problems we were having with Lightswitch were killing our productivity, so we took the decision to throw it all away and switch to a different style of web development. This meant we would be up against it to get things delivered, but crucially the switch meant we could all be much more productive and we started to see the benefits almost straight away. We worked into the night, stopping only for pizza and the odd bottle of beer, but by 2am we were all flagging badly and agreed to call it a night. </span><br />
<span style="font-family: Verdana, sans-serif;">Sunday morning was the home stretch – the cutoff for all teams was midday, which was probably just as well as otherwise we’d all have kept going until UCL kicked us out. We still had loads to do however, and I was back at our table at 8am, typing with one hand and eating a pain au chocolat with the other. We continued to make steady progress and integrate the different pieces of work we’d all been doing, right up to 12, and we agreed to continue to work on the project after the weekend in our own time to complete the parts we’d been unable to finish. There were a couple of hours to decompress and chat to other teams to see how they’d been getting on, before we all trooped across the road into a lecture theatre so each team could present on what they’d been doing. (You can see Dan Elliott’s presentation on the You Can Hub project through the medium of interpretive dance at <a href="http://tinyurl.com/agileguygivecampvideo">http://tinyurl.com/agileguygivecampvideo</a>). Our new friends from Scene And Heard were thrilled with how much we’d been able to accomplish in less than two days – ‘you’ve changed people’s lives’ was their reaction, and there were several people with tears in their eyes. Not me, I just had something in my eye. Honest. </span><br />
<span style="font-family: Verdana, sans-serif;">All the projects were seriously impressive, everybody had worked flat out all weekend and many people had learned on the spot things they’d never needed before, from integrating YouTube into a website, to using EventBrite like us, to building a CRM system in a weekend. There was a prizegiving ceremony - many companies had donated prizes to be given out, and courtesy of the Charity Technology Trust everyone received a brand new solid-state disc drive for their laptop – before it was time to say our farewells and head home for some much-needed sleep. As GiveCamp was held over a weekend, I was able to use my WSP volunteering days to take two days off afterwards to recover! </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span><br />
<b><span style="font-family: Verdana, sans-serif;">What Did I Learn? </span></b><br />
<span style="font-family: Verdana, sans-serif;">As well as picking up some techniques for recording and managing project requirements and measuring progress, my biggest takeaway from GiveCamp was the importance of flagging up project concerns early. Our decision to try Lightswitch cost us over half a day, which in a time-critical situation like this was time we couldn’t afford, when I’m not sure any of us was absolutely convinced it was the right thing to do. My other takeaway is how much can be done in just two days; for an individual, it’s difficult to achieve anything substantial in such a short space of time, but a team of highly skilled and motivated people working together for a couple of days can deliver impressive results. I’m already looking forward to seeing what we can do at GiveCamp 2012. </span><br />
<br />
<br />Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com0tag:blogger.com,1999:blog-1902158034220893892.post-42268364433640082022011-11-18T13:28:00.001+00:002011-11-18T15:28:14.118+00:00The Case of the Hung Visual Studio Installer<span style="font-family: Verdana, sans-serif;">(with apologies to <a href="http://blogs.technet.com/b/markrussinovich/" target="_blank">Mark Russinovich</a> :-) ) </span><br />
<br />
<span style="font-family: Verdana, sans-serif;">I got my shiny new work laptop on Tuesday this week, a HP EliteBook 8560P. Mmm, shiny. </span><br />
<br />
<span style="font-family: Verdana, sans-serif;">So a portion of the remainder of my week has been spent on installing things like SQL Server and other development tools on it. Until I got to Visual Studio 2010, for which the installer hung at the end of the first screen (the one where it installs Setup components before you get to choose which bits of VS you actually want to install). </span><br />
<br />
<span style="font-family: Verdana, sans-serif;">A few details. I'm running Windows 7 Enterprise, and I was installing Visual Studio 2010 Ultimate. I was using </span><a href="http://www.slysoft.com/en/virtual-clonedrive.html" target="_blank"><span style="font-family: Verdana, sans-serif;">Virtual CloneDrive</span></a><span style="font-family: Verdana, sans-serif;"> to mount an ISO image of the Visual Studio DVD from a USB hard drive. All things I've done before without any issues. </span><br />
<br />
<span style="font-family: Verdana, sans-serif;"><strong>Thought 1: My ISO image has got subtly corrupted somehow</strong>. I downloaded from MSDN a new ISO image of Visual Studio. No joy. </span><br />
<br />
<span style="font-family: Verdana, sans-serif;"><strong>Thought 2: There's a problem with running the installer off a mounted ISO</strong>. Despite being sure I'd successfully run off a mounted ISO before, I burned a DVD and ran the installer from there. No joy. </span><br />
<br />
<span style="font-family: Verdana, sans-serif;">At this point I tweeted that I was struggling: </span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzd49pdPAMz8hodJNdEuIDreWZVXP03AJOFCqIpec8UeNWWymIA1WYLkN_7cYRiqctpvmBZU1WkRK5ARYxaV1tMqc2IL4gKX79Ilf1iRsRTqtxzRcVkBxhyBCO_L876jqeGhPLF6D-8VhR/s1600/VS2010InstallerHangingTweet.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" height="105" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzd49pdPAMz8hodJNdEuIDreWZVXP03AJOFCqIpec8UeNWWymIA1WYLkN_7cYRiqctpvmBZU1WkRK5ARYxaV1tMqc2IL4gKX79Ilf1iRsRTqtxzRcVkBxhyBCO_L876jqeGhPLF6D-8VhR/s320/VS2010InstallerHangingTweet.png" width="320" /></span></a></div>
<span style="font-family: Verdana, sans-serif;">I was grousing more than expecting anyone to offer advice, but I received these tweets back: </span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjg0P_zSinDcGHb71NgtfXoRhu66XZYpN8QQ2IoXBFzof9z6JESK6QbzT9vCCkzFVM6boOOcPscySCZdbxibt5dG48lUKSVKpPapYKXudIo9_ZcVigf0-1gILOh5wScrLFmlmtbXFdcWi-X/s1600/VS2010InstallerHangingTweetResponse.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" height="176" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjg0P_zSinDcGHb71NgtfXoRhu66XZYpN8QQ2IoXBFzof9z6JESK6QbzT9vCCkzFVM6boOOcPscySCZdbxibt5dG48lUKSVKpPapYKXudIo9_ZcVigf0-1gILOh5wScrLFmlmtbXFdcWi-X/s320/VS2010InstallerHangingTweetResponse.png" width="320" /></span></a></div>
<div align="justify" class="separator" style="clear: both;">
<span style="font-family: Verdana, sans-serif;">Fair enough, I'll give that a go:</span></div>
<div align="justify" class="separator" style="clear: both; text-align: center;">
<br /></div>
<div align="justify" class="separator" style="clear: both;">
<span style="font-family: Verdana, sans-serif;"><strong>Thought 3: It is working, I'm just not giving it long enough to work.</strong> I ran the installer for at least 8 hours overnight Wednesday. No joy. </span></div>
<div align="justify" class="separator" style="clear: both;">
<br /></div>
<div align="justify" class="separator" style="clear: both;">
<span style="font-family: Verdana, sans-serif;">At this point I was Googling pretty hard for issues relating to the Visual Studio hanging, but no one seemed to have had a problem at the same stage as me. It did lead to me trying </span></div>
<div align="justify" class="separator" style="clear: both;">
<br /></div>
<div align="justify" class="separator" style="clear: both;">
<span style="font-family: Verdana, sans-serif;"><strong>Thought 4: A missing Registry key</strong> </span></div>
<div align="justify" class="separator" style="clear: both;">
<span style="font-family: Verdana, sans-serif;">I added the key. No joy. </span></div>
<div align="justify" class="separator" style="clear: both;">
<span style="font-family: Verdana, sans-serif;">and </span></div>
<div align="justify" class="separator" style="clear: both;">
<span style="font-family: Verdana, sans-serif;"><strong>Thought 5: The installer was trying to write temporary files to the external USB drive</strong>. I copied the ISO onto the hard drive, disconnected the external USB drive and re-ran the installer. No joy. </span></div>
<div align="justify" class="separator" style="clear: both;">
<br /></div>
<div align="justify" class="separator" style="clear: both;">
<span style="font-family: Verdana, sans-serif;">Desperation was setting in at this point, and I began to wonder if the problem was my install order. </span></div>
<div align="justify" class="separator" style="clear: both;">
<br /></div>
<div align="justify" class="separator" style="clear: both;">
<span style="font-family: Verdana, sans-serif;"><strong>Thought 6: Because I've installed SQL Server (and SQL Express), something in SQL Server is interfering with the install</strong>. I uninstalled both instances of SQL Server 2008 and the shared components. No joy. </span></div>
<div align="justify" class="separator" style="clear: both;">
<br /></div>
<div align="justify" class="separator" style="clear: both;">
<span style="font-family: Verdana, sans-serif;"><strong>Here comes the science bit...</strong> </span></div>
<div align="justify" class="separator" style="clear: both;">
<span style="font-family: Verdana, sans-serif;">I'd already been running SysInternals' </span><a href="http://technet.microsoft.com/en-gb/sysinternals/bb896653" target="_blank"><span style="font-family: Verdana, sans-serif;">Process Explorer</span></a><span style="font-family: Verdana, sans-serif;"> to try and see what was going on with the installer process but it didn't really show me enough detail. However I notioced from a discussion on the Microsoft forum someone else using </span><a href="http://technet.microsoft.com/en-gb/sysinternals/bb896645" target="_blank"><span style="font-family: Verdana, sans-serif;">Process Monitor</span></a><span style="font-family: Verdana, sans-serif;">, so I fired that up instead, and filtered it so I was just looking at setup.exe. This is what I saw: </span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgS5JuRwlfdSZFC2BO1u8RQVwcy1zPWmfFatdVfbeqKNypoLp3Lbtz7-B4gMoy-OHpBLeYlB6bDhRWWxSJkb2TygDHWyY5bLZad7khu7qKEOlzLQDdw1_5mgAvhTDHABnnjgnUaqSWK_Fyr/s1600/ProcMon+Hung+VS2010+Installer.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" hda="true" height="233" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgS5JuRwlfdSZFC2BO1u8RQVwcy1zPWmfFatdVfbeqKNypoLp3Lbtz7-B4gMoy-OHpBLeYlB6bDhRWWxSJkb2TygDHWyY5bLZad7khu7qKEOlzLQDdw1_5mgAvhTDHABnnjgnUaqSWK_Fyr/s640/ProcMon+Hung+VS2010+Installer.png" width="640" /></a></div>
<div align="justify" class="separator" style="clear: both;">
<br /></div>
<div align="justify" class="separator" style="clear: both;">
<span style="font-family: Verdana, sans-serif;">My first thought here was: why is setup.exe trying to write files to live.sysinternals.com?, closely followed by: have I done this right or is Process Monitor somehow screwing up these results? And suddenly, in one of my occasional flashes of intuition, it clicked. </span></div>
<div align="justify" class="separator" style="clear: both;">
<br /></div>
<div align="justify" class="separator" style="clear: both;">
<span style="font-family: Verdana, sans-serif;"><strong>The Answer</strong> </span></div>
<div align="justify" class="separator" style="clear: both;">
<span style="font-family: Verdana, sans-serif;">I have a drive mapped to </span><a href="http://live.sysinternals.com/" target="_blank"><span style="font-family: Verdana, sans-serif;">\\live.sysinternals.com\tools</span></a><span style="font-family: Verdana, sans-serif;">, and the drive that I have mapped is the I: drive. 'Cos, y'know, Internals begins with I. Turns out that the Visual Studio installer maps a folder in your %TEMP% folder to I: too and then uses it for decompressing some of the CAB files that the installer uses. Since I already had an I: drive, the installer was trying to use it but failing as I (obviously) don't have write privileges to the SysInternals folder, and the whole thing ended up in an infinite loop. I unmapped my I: drive from the SysInternals folder, re-ran the installer and everything installed successfully. </span></div>
<div align="justify" class="separator" style="clear: both;">
<span style="font-family: Verdana, sans-serif;">Now, clearly, the set of people who a) have an I: drive mapped but b) don't have write access to it and c) need to install Visual Studio, is going to be pretty small, but at the same time I can't help feeling the installer should have handled this better. In the end it was a simple workaround for me to resolve it, but it took me too long to discover the problem. Logged on Connect at </span><a href="https://connect.microsoft.com/VisualStudio/feedback/details/705657."><span style="font-family: Verdana, sans-serif;">https://connect.microsoft.com/VisualStudio/feedback/details/705657.</span></a></div>Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com0tag:blogger.com,1999:blog-1902158034220893892.post-39725737553754914032011-11-08T17:04:00.000+00:002011-11-08T17:06:57.252+00:00World Clocks with jClock and TimeZoneInfo<div style="font-family: Verdana,sans-serif;">
Everyone else seems to be writing about the clocks changing this week, I don't see why I should miss out... </div>
<div style="font-family: Verdana,sans-serif;">
<br /></div>
<div style="font-family: Verdana,sans-serif;">
Last year while I was working on our group intranet project, I wrote a web part for diplaying times around the world corresponding to some of our major offices. It uses the <a href="http://plugins.jquery.com/project/jclock" target="_blank">jClock</a> jQuery plugin so it does actually tick every second instead of being static (and in a future release I'm going to change this so it doesn't show the seconds and only ticks every minute instead). The list of locations is driven by an XML file so we can dynamically add more if we open offices in other time zones.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg3GgCltVclNuxhIA5fv5H-9qZSleqm3ACyCpLZMAujgFkAD_2Bg3na9Ng_1Kw2rr7h6jOo9kmLm_PEWvTmFPweWSAXUOP70JMp89iikeB1bOs0_E8bXXVFSwYU8kir8VO51ugJgvSHLVz/s1600/WorldClocks.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg3GgCltVclNuxhIA5fv5H-9qZSleqm3ACyCpLZMAujgFkAD_2Bg3na9Ng_1Kw2rr7h6jOo9kmLm_PEWvTmFPweWSAXUOP70JMp89iikeB1bOs0_E8bXXVFSwYU8kir8VO51ugJgvSHLVz/s1600/WorldClocks.png" /></a></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<div style="font-family: Verdana,sans-serif;">
jClock by default shows you your local time, or you can give it an offset (in decimal) from GMT/UTC if you want to display the time from a different timezone. So the XML file that we went into production with last year was along the lines of;</div>
<blockquote>
<pre><locations>
<location>
<name>London</name>
<offset>0</offset>
</location>
<location>
<name>Stockholm</name>
<offset>1.0</offset>
</location>
</locations>
</pre>
</blockquote>
<div style="font-family: Verdana,sans-serif;">
The serverside code in the web part then uses a HtmlTextWriter to generate a set of DIVs and a block of JavaScript that sets up jClock.</div>
<br />
<blockquote>
<pre><script type="text/javascript">
<span style="font-family: "Courier New",Courier,monospace;"> $(document).ready(function ()</span>
<span style="font-family: "Courier New",Courier,monospace;"> {</span>
<span style="font-family: "Courier New",Courier,monospace;"> $('#jclock').jclock();</span>
<span style="font-family: "Courier New",Courier,monospace;"> $('#jclockLondon').jclock({ utc: true, utc_offset: 0 });</span>
<span style="font-family: "Courier New",Courier,monospace;"> $('#jclockStockholm').jclock({ utc: true, utc_offset: 1 });</span>
<span style="font-family: "Courier New",Courier,monospace;"> });</span>
<span style="font-family: "Courier New",Courier,monospace;"></script></span>
<span style="font-family: "Courier New",Courier,monospace;"><h2>WORLD CLOCKS</h2></span>
<span style="font-family: "Courier New",Courier,monospace;"><div style="text-align: center;"></span>
<span style="font-family: "Courier New",Courier,monospace;"> <div></span>
<span style="font-family: "Courier New",Courier,monospace;"> <span>Local time:</span></span>
<span style="font-family: "Courier New",Courier,monospace;"> <span id="jclock"></span></span>
<span style="font-family: "Courier New",Courier,monospace;"> </div></span>
<span style="font-family: "Courier New",Courier,monospace;"> <div style='background-color: #F0F0F0; width: 100%;'></span>
<span style="font-family: "Courier New",Courier,monospace;"> <span>London</span></span>
<span style="font-family: "Courier New",Courier,monospace;"> <span id='jclockLondon'></span></span>
<span style="font-family: "Courier New",Courier,monospace;"> </div></span>
<span style="font-family: "Courier New",Courier,monospace;"> <div></span>
<span style="font-family: "Courier New",Courier,monospace;"> <span>Stockholm</span></span>
<span style="font-family: "Courier New",Courier,monospace;"> <span id='jclockStockholm'></span></span>
<span style="font-family: "Courier New",Courier,monospace;"> </div></span>
<span style="font-family: "Courier New",Courier,monospace;"></div></span></pre>
</blockquote>
<div style="font-family: Verdana,sans-serif;">
The two generated strings are put into a <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.pair.aspx" target="_blank">Pair</a> and then cached as one object to cut down some of the work for the server. And all this was fine, until the clocks changed in the spring. I worked out the new offsets and updated the XML file on the server, so then we had;</div>
<blockquote>
<pre><locations>
<location>
<name>London</name>
<offset>1.0</offset>
</location>
<location>
<name>Stockholm</name>
<offset>2.0</offset>
</location>
</locations>
</pre>
</blockquote>
<div style="font-family: Verdana,sans-serif;">
When the clocks changed again last week, I realised that this was going to be unsustainable and needed reworking. My first thought was to add a set of dates to the XML that denoted when to switch between winter and summer times. I coded this up, tested it, and checked it in, thinking I was done. Until it was pointed out to me that not everyone changes their clocks on the same date. </div>
<div style="font-family: Verdana,sans-serif;">
<br /></div>
<div style="font-family: Verdana,sans-serif;">
With a steer from <a href="https://twitter.com/#%21/gustaflidvall" target="_blank">Gustaf</a>, I looked into the <a href="http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx" target="_blank">System.TimeZoneInfo</a> class. Now I wish I'd looked at this last year...</div>
<div style="font-family: Verdana,sans-serif;">
<br /></div>
<div style="font-family: Verdana,sans-serif;">
To get an instance of the TimeZoneInfo class, you call the static method FindSystemTimeZoneById and pass it the string Id of the timezone you want e.g. 'GMT Standard Time'. You can see all the timezones that your system supports by calling GetSystemTimeZones, which returns a ReadOnlyCollection of all the timezones Windows knows about. Each timezone has an id but also a DisplayName e.g. ' - it's the DisplayName that you see if you go into the Control Panel to change your system's timezone:</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdEoTxdAOPS6RuDA7e20qbFwkxRWrnBglJZB-TFhqBtTvM0UDk5jg9JO-8wEbxRmFUc3FCm7OgZIEtjpoZuvM_68BKjv934Ig-37Qby26uuMu3Co6TEHkDOTjtbimAp5BpADhunXI5jhId/s1600/TimeZoneInfo+DisplayName.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="179" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdEoTxdAOPS6RuDA7e20qbFwkxRWrnBglJZB-TFhqBtTvM0UDk5jg9JO-8wEbxRmFUc3FCm7OgZIEtjpoZuvM_68BKjv934Ig-37Qby26uuMu3Co6TEHkDOTjtbimAp5BpADhunXI5jhId/s320/TimeZoneInfo+DisplayName.png" width="320" /></a></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<div style="font-family: Verdana,sans-serif;">
The id is constant across all installations of Windows, however the Displayname is localised - this was an important point for me as our intranet runs on servers in Sweden. For our World Clocks web part, the key function of TimeZoneInfo is GetUTCOffset. This takes a DateTime parameter which allows you to calculate the UTC offset for any given timezone on any given date. The key point is that this automatically factors in daylight savings times e.g. British Summer Time. I'd expected British Summer Time (or equally Central European Summer Time) to be listed as separate timezones, but they aren't, the timezone knows when it should apply changes for daylight savings e.g.</div>
<br />
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: #2b91af;">TimeZoneInfo</span> info = <span style="color: #2b91af;">TimeZoneInfo</span>.FindSystemTimeZoneById(<span style="color: #a31515;">"GMT Standard Time"</span>);
<span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"Id: {0} - DisplayName: {1}"</span>,</pre>
<pre style="background: none repeat scroll 0% 0% white; color: black; font-family: Consolas; ">info.Id,info.DisplayName));
<span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"Summer offset is {0}"</span>, </pre>
<pre style="background: none repeat scroll 0% 0% white; color: black; font-family: Consolas; ">info.GetUtcOffset(<span style="color: blue;">new</span> <span style="color: #2b91af;">DateTime</span>(2011,5,7))));
<span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"Winter offset is {0}"</span>, </pre>
<pre style="background: none repeat scroll 0% 0% white; color: black; font-family: Consolas; ">info.GetUtcOffset(<span style="color: blue;">new</span> <span style="color: #2b91af;">DateTime</span>(2011,11,7))));
<span style="color: #2b91af;">Console</span>.ReadLine();</pre>
<br />
produces<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwGYufytG9XmTcH1m44FwBVrobz0GTy5vImKH7O5-PxIrTCsZoxECY2coLt-8PHgmpSDq0i0cPbpM_J8UCOwKukmKMBnKlLIysrVW8rPr-hsd5fiB2aXZ5ZWkPyFcXmePBHxN40ZjGZ9h1/s1600/GMT+Offsets.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="89" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwGYufytG9XmTcH1m44FwBVrobz0GTy5vImKH7O5-PxIrTCsZoxECY2coLt-8PHgmpSDq0i0cPbpM_J8UCOwKukmKMBnKlLIysrVW8rPr-hsd5fiB2aXZ5ZWkPyFcXmePBHxN40ZjGZ9h1/s640/GMT+Offsets.png" width="640" /></a></div>
<br />
<span style="font-family: Verdana,sans-serif;">One of my colleagues asked what will happen if the rules for a given timezone change e.g. suppose the UK changes the dates on which the clocks change. The answer is this is now Microsoft's problem instead of mine, all the timezone information is held in the Registry and if any timezone changes, Microsoft will release a Windows Update that contains the new information.</span><br />
<br />
<span style="font-family: Verdana,sans-serif;">So I've got rid of an annoying manual job in changing the XML twice a year, and the XML itself is much simpler because now for each location all it needs is a name, and a timezone id. Simples.</span>Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com0tag:blogger.com,1999:blog-1902158034220893892.post-46665371840854254982011-06-10T15:10:00.000+01:002011-06-10T15:10:02.081+01:00Guathon 2011<span style="font-family: Verdana, sans-serif;">Monday this week saw this years Guathon in London, a day of technical presentations from St Scott of Guthrie, ably assisted this year by Steve Sanderson. The event is free and held in a cinema - now I know how big I want my next monitor to be :-) Unfortunately, due to Microsoft's lack of organisation in changing the venue at the last minute, there were lots of empty seats and many more developers could have attended. This year Scott did the first and last sessions, with Steve covering the late-morning/early-afternoon shifts.</span><br />
<br />
<b></b><br />
<div><span style="font-family: Verdana, sans-serif;"><strong>Build An App Using ASP.NET MVC 3, EF Code First, NuGet, and IIS</strong></span></div></b><span style="font-family: Verdana, sans-serif;">The first session (which due to National Express East Anglia's incompetence I missed the start of) was Scott covering some of the features of MVC3/Razor and Code-First Entity Framework. This was probably the session I got the most out of all day, as I haven't done any MVC/EF in anger yet there was a lot of value here for me. Key points I took away were:</span><br />
<span style="font-family: Verdana, sans-serif;">Razor syntax</span><br />
<span style="font-family: Verdana, sans-serif;">@ - starts a code block</span><br />
<span style="font-family: Verdana, sans-serif;">@: - is the prefix for a string literal e.g. if you want to output some HTML inside a code block</span><br />
<span style="font-family: Verdana, sans-serif;">There is detection for the @ symbol inside an email address that means it automatically renders a mailto: link</span><br />
<span style="font-family: Verdana, sans-serif;">@@ - acts as an escape character</span><br />
<span style="font-family: Verdana, sans-serif;">@helper - one of the biggest things for me, I've never seen this before. @helper allows you to write a helper method that acts like a method but with Razor syntax so you can call the helper to display a canned piece of HTML. Helpers can be declared in-line or in a partial class within the App_Code folder. Scott also mentioned that </span><a href="http://blog.davidebbo.com/"><span style="font-family: Verdana, sans-serif;">David Ebbo</span></a><span style="font-family: Verdana, sans-serif;"> (</span><a href="http://twitter.com/davidebbo"><span style="font-family: Verdana, sans-serif;">@davidebbo</span></a><span style="font-family: Verdana, sans-serif;">) has a project on his website that allows you to write helpers that are compiled into an assembly. It's actually now on CodePlex at </span><a href="http://razorgenerator.codeplex.com/"><span style="font-family: Verdana, sans-serif;">http://razorgenerator.codeplex.com/</span></a><span style="font-family: Verdana, sans-serif;">.</span><br />
<span style="font-family: Verdana, sans-serif;">@model -By default the Model variable in a page is of the dynamic type, which means at design-time you don't get (much) Intellisense from it, however an @model declaration at the top of the page allows you to specify the exact type of Model, and you then get proper Intellisense support. If you create the View as a strongly-typed view and select the concrete type the View will support, it puts an @model declaration in for you.</span><br />
<span style="font-family: Verdana, sans-serif;">_ViewStart.cshtml - Allows you to setup defaults for a set of views, including setting the _Layout.cshtml page. Someone asked whether you can have multiple _ViewStarts, Scott didn't know but was surprised when someone else said that you can. Gunnar Peipman's </span><a href="http://weblogs.asp.net/gunnarpeipman/archive/2010/10/10/asp-net-mvc-3-beta-view-start-files-for-razor-view-engine.aspx"><span style="font-family: Verdana, sans-serif;">blog</span></a><span style="font-family: Verdana, sans-serif;"> makes this clear - a _ViewStart is scoped to the folder that it is in.</span><br />
<span style="font-family: Verdana, sans-serif;">_Layout.cshtml - The Razor equivalent of an ASP.NET Master page.</span><br />
<br />
<div></div></font><span style="font-family: Verdana, sans-serif;">Scott also showed off a couple of tools:</span><br />
<a href="http://www.modernizr.com/"><span style="font-family: Verdana, sans-serif;">Modernizr.js</span></a><span style="font-family: Verdana, sans-serif;"> - allows you to detect which HTML5 and CSS3 features are supported on the browser instead of detecting these from the User-Agent string. Scott also showed off some HTML5 features in his demos, to which somebody asked if you could use those outside Razor. Scott's reply? "Yes, you can open your project and start typing the HTML5 tags" :-)</span><br />
<a href="http://getglimpse.com/"><span style="font-family: Verdana, sans-serif;">Glimpse</span></a><span style="font-family: Verdana, sans-serif;"> - "FireBug for your server" is the best description of this tool. It shows you on the client what is happening on your server, how your server is configured. And I confess I'm pleased to see this is currently available for ASP.NET only, I'd assumed it was something other frameworks had had for a while but it seems not.</span><br />
<br />
<div></div></font><span style="font-family: Verdana, sans-serif;"><strong>Dynamic Web UIs with Knockout.js</strong></span><br />
<span style="font-family: Verdana, sans-serif; font-size: small;">Steve's first session covered Knockout.js, an MVVM framework that works with any JSON feed. I think I may have misunderstood the principle behind this, it seemed to me to be largely another jQuery templating framework, although looking on the website it says that you can use your choice of templating engine. Talking to others in the evening though, there seem to be other concerns around Knockout - lack of testability and accessibility were the principal ones, and no degradation support means for me I'm unlikely to use Knockout. Plus I'm primarily a server-side guy - I can do some jQuery but right now I don't have the bandwidth to learn another JavaScript framework.</span><br />
<br />
<div></div></font><span style="font-family: Verdana, sans-serif; font-size: small;"><strong>C#5 and Asynchronous Web Applications</strong></span><br />
<span style="font-family: Verdana, sans-serif; font-size: small;">After lunch Steve was on again, demoing some of the asynchronous bits that are coming in C#5. Steve talked about polling, long polling and sockets. The difference between these is as follows (I've probably got these wrong, if I have someone please tell me so I don't look a complete Muppet):</span><br />
<ul><li><span style="font-family: Verdana, sans-serif; font-size: small;">polling - call a service at a regular interval e.g. every second, the service returns any changes made since the last call.</span></li>
<li><span style="font-family: Verdana, sans-serif; font-size: small;">long polling - call a service, the call doesn't return until the service has some data to return to the client, however long this takes.</span></li>
<li><span style="font-family: Verdana, sans-serif; font-size: small;">sockets - opens a channel between the caller and a service and the service then returns data to the client whenever it has any, keeping the channel open.</span></li>
</ul><span style="font-family: Verdana, sans-serif;">Of these sockets is the best, however there is currently limited support for it on browsers so we won't see this go mainstream for a little while yet. </span><br />
<br />
</font><span style="font-family: Verdana, sans-serif; font-size: small;"><strong></strong></span><br />
<span style="font-family: Verdana, sans-serif; font-size: small;"><strong>Cloud Development</strong></span><br />
<span style="font-family: Verdana, sans-serif; font-size: small;">The last session of the day saw Scott back on the podium talking about developing for the cloud and Windows Azure. Scott has recently taken on management of the Azure team, although this was badly publicised as it sounded like Scott had moved away from ASP.NET and all the other things he was managing - this is not so, he's still in charge of ASP.NET and everything else, the Azure stuff is <i>in addition to</i>, not <i>instead of</i>. Scott talked about and showed off a lot of the infrastructure behind Azure, including fun facts like:</span><br />
<ul><li><span style="font-family: Verdana, sans-serif; font-size: small;">the ratio of servers to staff in the data centres is 15 000:1</span></li>
<li><span style="font-family: Verdana, sans-serif; font-size: small;">the centres are constructed from containers</span></li>
<li><span style="font-family: Verdana, sans-serif; font-size: small;">the newer containers they are deploying don't have roofs which saves a lot of energy on cooling</span></li>
<li><span style="font-family: Verdana, sans-serif; font-size: small;">for every watt of energy that powers a server, they only use an additional 0.1 of a watt on ancillary usage such as heating/cooling etc</span></li>
</ul><span style="font-family: Verdana, sans-serif; font-size: small;">This gives you a much lower TCO when you use services in the cloud, however Scott came out with the quote of the day when talking about this:</span><br />
<div style="text-align: center;"><span style="font-family: Verdana, sans-serif; font-size: small;"><strong>"Developers don't care about money, we just care about developing cool stuff."</strong></span></div><span style="font-family: Verdana, sans-serif; font-size: small;">Employers, take note...</span><br />
<br />
<div></div></font><span style="font-family: Verdana, sans-serif; font-size: small;">Scott demo'ed developing an ASP.NET application to be hosted in the cloud and showed the steps necessary to set this up. I was interested to hear that there is/will be a PowerShell commandlet for deploying solutions to your Azure setup.</span><br />
<br />
<div></div></font><span style="font-family: Verdana, sans-serif; font-size: small;">Scott showed off some forthcoming technology on Azure, a Queuing service allowing you to de-couple parts of your business processes, which was interesting and made me wonder whether Microsoft might be thinking of putting some of the BizTalk infrastructure in the cloud. This would be a big win, I think, in terms of making BizTalk a more accessible technology and getting more take-up - we looked at BizTalk for a project a couple of years ago but the costs for setting up BizTalk on-site are currently prohibitive.</span><br />
<br />
<span style="font-family: Verdana, sans-serif; font-size: small;">Scott presented a mini-case study on EasyJet - they host their applications in the cloud and then connect to them in airports using local WiFi, which saves them money on having to setup infrastructure in every airport they operate in. </span><br />
<br />
<span style="font-family: Verdana, sans-serif;">Scott touched on the Azure AppFabric caching service, which I'm interested to know more about - I'm still fuzzy on the benefits. The throughput rate for the caching service is 4Tb/s - not too shabby. Scott also mentioned, almost, as my old German teacher would say, <em>en passant</em>, that Microsoft will shortly be rolling out a Content Delivery Network service on the Azure infrastructure, which is something I find really exciting. But maybe I'm just sad that way...</span><br />
<br />
</font><span style="font-family: Verdana, sans-serif;">Thanks to Scott and Steve for presenting, </span><a href="http://weblogs.asp.net/Plip/"><span style="font-family: Verdana, sans-serif;">Phil</span></a><span style="font-family: Verdana, sans-serif;"> and </span><a href="http://blogs.ipona.com/davids/default.aspx"><span style="font-family: Verdana, sans-serif;">Dave</span></a><span style="font-family: Verdana, sans-serif;"> for organising it all, and </span><a href="http://paulstack.co.uk/blog/"><span style="font-family: Verdana, sans-serif;">Paul</span></a><span style="font-family: Verdana, sans-serif;">, </span><a href="http://designcoderelease.blogspot.com/"><span style="font-family: Verdana, sans-serif;">Nathan</span></a><span style="font-family: Verdana, sans-serif;">, </span><a href="http://twitter.com/#!/johanbarnard"><span style="font-family: Verdana, sans-serif;">Johan</span></a><span style="font-family: Verdana, sans-serif;"> and </span><a href="http://tiwtter.com/danstuken"><span style="font-family: Verdana, sans-serif;">Dan</span></a><span style="font-family: Verdana, sans-serif;"> for the conversation over dinner at TGIs!</span>Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com0tag:blogger.com,1999:blog-1902158034220893892.post-46653920778310441642011-02-17T13:58:00.000+00:002011-02-17T13:58:54.959+00:00Making a Hybrid Web Application Project Type<span style="font-family: Verdana, sans-serif;">Like so many of my blog entries, I've been meaning to write this one for weeks. Ever since Scott Hanselman wrote </span><a href="http://www.hanselman.com/blog/IntegratingASPNETMVC3IntoExistingUpgradedASPNET4WebFormsApplications.aspx"><span style="font-family: Verdana, sans-serif;">Integrating ASP.NET MVC 3 into existing upgraded ASP.NET 4 Web Forms applications</span></a><span style="font-family: Verdana, sans-serif;">, in fact. Scott just wrote </span><a href="http://www.hanselman.com/blog/CreatingANuGetPackageIn7EasyStepsPlusUsingNuGetToIntegrateASPNETMVC3IntoExistingWebFormsApplications.aspx"><span style="font-family: Verdana, sans-serif;">an updated post</span></a><span style="font-family: Verdana, sans-serif;"> on using NuGet to bring the MVC bits into a WebForms application, which is a muc easier way to do it. But to me, Scott's still missing the final piece of the puzzle which is: do this once, create it a <em>project type</em> from it, and forget about it.</span><br />
<span style="font-family: Verdana, sans-serif;"></span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span style="font-family: Verdana, sans-serif;">So, creating a hybrid project type. First of all, </span><a href="http://www.hanselman.com/blog/CreatingANuGetPackageIn7EasyStepsPlusUsingNuGetToIntegrateASPNETMVC3IntoExistingWebFormsApplications.aspx"><span style="font-family: Verdana, sans-serif;">go do Scott's NuGet stuff</span></a><span style="font-family: Verdana, sans-serif;"> and create your hybrid application. Oh, and add any of your other favourite references - NHibernate, CastleWindsor, whatever. It's OK, I'll wait.</span> <br />
<span style="font-family: Verdana, sans-serif;"></span> <br />
<span style="font-family: Verdana, sans-serif;">Done that. Good.</span> <br />
<span style="font-family: Verdana, sans-serif;"></span> <br />
<span style="font-family: Verdana, sans-serif;">Now click File|Export Template... and open the Export Template Wizard. Check the 'Project Template' radio button so we export the hybrid project as a template. Click Next.</span> <br />
<span style="font-family: Verdana, sans-serif;"></span> <br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7EzMFaX44MtL_E9XJO555Y_F2Nq-tHWGNUZ5PnyxvsseFk1K8JjxnR2y-wQ-YVCnX03pCyWH756_vC3pDiLP0HVGIQfPqK7bem3o07BEi_Nem4zjwhNeGqP1-XhwZB7kB8-KxSTHI1M6W/s1600/ETWScreen1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" height="313" j6="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7EzMFaX44MtL_E9XJO555Y_F2Nq-tHWGNUZ5PnyxvsseFk1K8JjxnR2y-wQ-YVCnX03pCyWH756_vC3pDiLP0HVGIQfPqK7bem3o07BEi_Nem4zjwhNeGqP1-XhwZB7kB8-KxSTHI1M6W/s400/ETWScreen1.png" width="400" /></span></a></div><span style="font-family: Verdana, sans-serif;">On the second screen, enter a suitable name for the project type and description, and choose an icon if you want.</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGiBpQ3_hwckiToPPB_3R1-_VHicRvmPyAer09icWkA3Rc9WMHH22u16O6xekaCIknPYvbNChUeyXLSW2JF5nYhJr9lI8CymWx2q0JyqqJRTg5cvM7qZwuXu5iyeeRXIwbdaM4gqyPtcsx/s1600/ETWScreen2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" height="313" j6="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGiBpQ3_hwckiToPPB_3R1-_VHicRvmPyAer09icWkA3Rc9WMHH22u16O6xekaCIknPYvbNChUeyXLSW2JF5nYhJr9lI8CymWx2q0JyqqJRTg5cvM7qZwuXu5iyeeRXIwbdaM4gqyPtcsx/s400/ETWScreen2.png" width="400" /></span></a></div><span style="font-family: Verdana, sans-serif;">Click Finish and you're done!</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZ4ll0yw1OZMyjKY2L2Uc72UE1OxD76e-eR24C671s_k9iL__JkKfH_e8enn8rvPju3zlaRqdnfSPNKuT-Y1SWyeodG3FJAEQDDQNutRMClYuQpnCQ2kgwCUvg1uutMs1KTxC615CV0zPM/s1600/NewProjectWithHybridApplication.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" height="276" j6="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZ4ll0yw1OZMyjKY2L2Uc72UE1OxD76e-eR24C671s_k9iL__JkKfH_e8enn8rvPju3zlaRqdnfSPNKuT-Y1SWyeodG3FJAEQDDQNutRMClYuQpnCQ2kgwCUvg1uutMs1KTxC615CV0zPM/s400/NewProjectWithHybridApplication.png" width="400" /></span></a></div>Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com0tag:blogger.com,1999:blog-1902158034220893892.post-49588791833327890842011-01-30T22:48:00.001+00:002011-01-30T22:49:29.901+00:00What's A DDD9?<div style="font-family: Verdana,sans-serif;">Some of my (non-geek) colleagues who follow <a href="http://twitter.com/philpursglove">me</a> on Twitter have asked me recently: what's a DDD9? The answer: for the UK .net community, it's the major event of the year. Held annually at Microsoft's offices in Reading, it is a free one-day conference run totally by the community. The DDD stands for Developer Developer Developer, from Steve Ballmer's chant of several years ago (<a href="http://www.youtube.com/watch?v=8To-6VIJZRE">http://www.youtube.com/watch?v=8To-6VIJZRE</a>) *. Microsoft employees are welcome to attend, but they aren't allowed to speak. It is only advertised through word-of-mouth and Twitter: this year it sold out 350 spaces in 12 minutes, the waiting list for spaces was full after another 30 minutes. You may find this slightly more notable as DDD is held on a Saturday, which ensures that the people who are there are the kind of passionate people who are prepared to give up a large part (or in many cases the entirety) of their weekend to attend. The programme is completely voted for by the attendees, this year there was again a great mix of <i>technical</i> and <i>technique</i> sessions. The sessions I saw this year were:</div><div style="font-family: Verdana,sans-serif;"><br />
</div><div style="font-family: Verdana,sans-serif;">.net Collections Deep Dive - <a href="http://twitter.com/garyshort">Gary Short</a></div><div style="font-family: Verdana,sans-serif;">Actually I wanted to see all four talks in the first session, but I picked Gary's as I don't think I've ever seen him talk before. This was a session going through many of the Collection classes available in .net, how they work internally and in what circumstances each one offers better performance. It included such gems as the fact that in the multithreaded collections if you call the Count property it is not guaranteed to be accurate unless you can be sure all threads have exited. In which case it wouldn't be, y'know, multithreaded. The top tip I took away was that if you know how many elements you are going to put in a collection, to set the Capacity in the initialiser:</div><div style="font-family: "Courier New",Courier,monospace;">List<string> myListOfTenElements = new List<string>(10);</string></string></div><div style="font-family: Verdana,sans-serif;"><br />
</div><div style="font-family: Verdana,sans-serif;">CQRS, Fad or Future - <a href="http://twitter.com/ICooper">Ian Cooper</a></div><div style="font-family: Verdana,sans-serif;">OK, so I, um, didn't actually see this session, I got chattinjg to people in the speakers lounge. The presence of chocolate and raspberry cheesecake brownies (made by me) was a total coincidence. This was still quite useful as I was able to talk to <a href="http://twitter.com/davesussman">Dave Sussman</a> about a CSS issue I'd been having and get some advice. However I look forward to seeing Ian's slides and maybe catching this talk at a user group sometime.</div><div style="font-family: Verdana,sans-serif;"><br />
</div><div style="font-family: Verdana,sans-serif;">A Primer on RavenDB - <a href="http://twitter.com/robashton">Rob Ashton</a></div><div style="font-family: Verdana,sans-serif;">One of the sessions I really wanted to see as I'm interested in playing with RavenDB and I can see cases in WSP where it could be a very good technical fit. Rob is quite opinionated, especially on how MongoDB and RavenDB differ. Rob recommends getting the unstable version of RavenDB to play with so you can see the features, although I think at least initially I'll be using the stable build until I've found my feet with it. One of the things I'm most impressed with is the fact that for unit testing purposes, you can run RavenDB completely in memory with no impact to disk.</div><div style="font-family: Verdana,sans-serif;"><br />
</div><div style="font-family: Verdana,sans-serif;">Is Your Code SOLID - <a href="http://twitter.com/NathanGloyn">Nathan Gloyn</a></div><div style="font-family: Verdana,sans-serif;">This talk walked through the SOLID principles of software engineering.Nathan began with a pretty ropey bit of code, and then talked through each principle before demonstrating how the code changed after the application of the principle. A really interesting session for me, SOLID is something I need to think about more as I write software.</div><div style="font-family: Verdana,sans-serif;"><br />
</div><div style="font-family: Verdana,sans-serif;">CSS Is Code - <a href="http://twitter.com/helephant">Helen Emerson</a></div><div style="font-family: Verdana,sans-serif;">Helen's theme was that CSS code is as important as application source code, but that the rules and principles we apply to source code aren't often applied to CSS. Probably not the right session for me given that I'm a total numpty where CSS is concerned, although it was useful to see that in Helen's demos there were things that chimed with some of the CSS we used on the Intranet last year.</div><div style="font-family: Verdana,sans-serif;"><br />
</div><div style="font-family: Verdana,sans-serif;">A Beginner's Guide to Continuous Integration - <a href="http://twitter.com/stack72">Paul Stack</a></div><div style="font-family: Verdana,sans-serif;">A great session to round off the day from Paul Stack, talking about how to use CI to reduce the time it takes to release your software. Like RavenDB, CI is something I definitely want to look into, in fact in that respect it was a shame it was a Saturday as I was fired up enough that I wanted to go straight into the office and set up a CI server. The only real negative in this session for me was that there was little discussion of how to set up CI with TFS, although Paul tells me this is straightforward.</div><div style="font-family: Verdana,sans-serif;"><br />
</div><div style="font-family: Verdana,sans-serif;">The Social Network</div><div style="font-family: Verdana,sans-serif;">There's much more to DDD than just a technical conference - for many if not all of the delegates it is as much a social event as a learning opportunity. It's a chance to catch up with old friends, make new ones, or just an opportunity to put faces to Twitter handles - I've been chatting with Nathan and Paul on Twitter for months but Saturday was the first time I'd met them. And the socialising continues into the evening - there is a Geek Dinner after the conference, at which 40 of us take over most of Pizza Express to eat, drink and chat. </div><div style="font-family: Verdana,sans-serif;">We had an interesting conversation at our end of the table about the nature of developers and DDD and why it seems to work for us but no-one else. There simply doesn't seem to be any other profession that does events like this - even inside IT, there's no equivalent event for IT Pros.</div><div style="font-family: Verdana,sans-serif;"><br />
</div><div style="font-family: Verdana,sans-serif;">* I did discover through the power of Google an alternative DDD9 conference - <a href="http://www.google.co.uk/url?sa=t&source=web&cd=2&ved=0CB4QFjAB&url=http%3A%2F%2Fwww.dur.ac.uk%2Ftheology.religion%2Fabout%2Fevents%2F%3Feventno%3D4488&rct=j&q=ddd9%20death&ei=9-lFTZ_BOZOxhQfamIGzAQ&usg=AFQjCNGoIcKTzmNWoA1K4L1Ao2eJdPj5UA&cad=rja">Death, Dying and Disposal</a>. Which doesn't sound anything like as much fun.</div>Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com0tag:blogger.com,1999:blog-1902158034220893892.post-73475997380712627712010-12-23T15:18:00.000+00:002010-12-23T15:18:54.799+00:00switch vs Select Case<span style="font-family: Verdana, sans-serif;">I knew if I looked long enough, I'd find something you can do in VB.NET that you can't do in C#. And I <em>think</em> I just found it.</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span style="font-family: Verdana, sans-serif;">Consider this bit of markup:</span><br />
<span style="font-family: "Courier New", Courier, monospace;">Why is it not possible to use an existing approved supplier?</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><asp:radiobutton id="ClientNominatedRadioButton" runat="server" text="Nominated/named by client" GroupName="NewSupplierReasonRadioButtonGroup" /></span><br />
<span style="font-family: "Courier New", Courier, monospace;"><asp:radiobutton id="AlreadyOnSiteRadioButton" runat="server" text="Already on site" GroupName="NewSupplierReasonRadioButtonGroup" /></span><br />
<span style="font-family: "Courier New", Courier, monospace;"><asp:radiobutton id="NewLocationRadioButton" text="New location and no existing supplier" runat="server" GroupName="NewSupplierReasonRadioButtonGroup" /></span><br />
<span style="font-family: "Courier New", Courier, monospace;"><asp:radiobutton id="OtherRadiobutton" runat="server" text="Other (please state)" GroupName="NewSupplierReasonRadioButtonGroup" runat="server" /></span><br />
<br />
<span style="font-family: Verdana, sans-serif;">At some point, I'll want to examine this set of radio buttons to deduce which one is selected. In VB.NET, I would normally do this with a Select Case construct, viz.</span><br />
<span style="font-family: "Courier New", Courier, monospace;">Select Case True</span><br />
<span style="font-family: "Courier New", Courier, monospace;"></span><br />
<span style="font-family: "Courier New", Courier, monospace;"> Case ClientNominatedRadioButton.Checked</span><br />
<br />
<span style="font-family: "Courier New", Courier, monospace;"> Case AlreadyOnSiteRadioButton.Checked</span><br />
<br />
<span style="font-family: "Courier New", Courier, monospace;"> Case NewLocationRadioButton.Checked</span><br />
<br />
<span style="font-family: "Courier New", Courier, monospace;"> Case OtherRadiobutton.Checked</span><br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">End Select</span><br />
<span style="font-family: Verdana, sans-serif;">which I always think is a more elegant construct than a thousand 'if...then...else if...then..else if' blocks.</span><br />
<br />
<span style="font-family: Verdana, sans-serif;">But it seems this construct is not available in C# - here's a screenshot from Visual Studio:</span><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjx9IrNcIBjdg5_qEn7B5IJ6S9NSdTq4t5JvDQ-ZIKWwt7IANHF57DABbxzaCDae8VQGLBbj58Kevljtd7hkHbPIxicIgRTYQol1CmVXWOM9ZsCxHHMZ-MhyAk2GI7PA2ILKRK0OD8RPrp4/s1600/BrokenSwitch.png" imageanchor="1" style="clear: left; cssfloat: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="185" n4="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjx9IrNcIBjdg5_qEn7B5IJ6S9NSdTq4t5JvDQ-ZIKWwt7IANHF57DABbxzaCDae8VQGLBbj58Kevljtd7hkHbPIxicIgRTYQol1CmVXWOM9ZsCxHHMZ-MhyAk2GI7PA2ILKRK0OD8RPrp4/s320/BrokenSwitch.png" width="320" /></a></div><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<span style="font-family: Verdana, sans-serif;">The tooltip for the red squiggly reads 'Code is unreachable. A constant value is expected'. </span><br />
<span style="font-family: Verdana, sans-serif;"></span> <br />
<span style="font-family: Verdana, sans-serif;">All of which leaves me slightly confused. If they compile down to the same bytecode then why does this approach work in only one language? And is there a more elegant way to determine the selected radiobutton than the aforementioned 'if...then' block?</span>Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com2tag:blogger.com,1999:blog-1902158034220893892.post-29007687418958060902010-10-26T13:23:00.001+01:002010-10-26T13:23:26.361+01:00Twenty Top 2010 TipsPlaceholderPhilhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com0tag:blogger.com,1999:blog-1902158034220893892.post-84598874494296087852010-08-25T10:58:00.001+01:002010-08-25T11:07:58.943+01:00DateTime.DaysInMonth<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">I stumbled upon this yesterday and thought it was worth publicising a bit.</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">I'm writing a tidgy little app that will take a load of data about our press releases out of one of our databases and turn into flat HTML files. It needs to write separate files for years and months - years are easy as it's just a </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">for</span><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"> loop, and months are also a </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">for</span><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"> loop, but I need to know the end date for each month so I can create the appropriate SQL query. I'd written a </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">switch</span><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"> block to calculate the last day of the month:</span><br />
<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">for (int i = 1; i < 13; i++)</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">{</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> DateTime startDate = new DateTime(int.Parse(year), i, 1, 0, 0, 0);</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> DateTime endDate;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> switch (i)</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> case 9, 4, 6, 11:</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> endDate = new DateTime(int.Parse(year), i, 30, 23, 59, 59);</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> break;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> case 2:</span><br />
<br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> endDate = new DateTime(int.Parse(year), i, 28, 23, 59, 59);</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> // TODO: Leap years</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> break;</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> default:</span></div><div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> endDate = new DateTime(int.Parse(year), i, 31, 23, 59, 59);</span></div></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> break;</span></div><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">}</span><br />
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">But further down in my code, I was doing something else with the DateTime class and I spotted it has a DaysInMonth function. You give it a year and a month (both ints), and it calculates the number of days in the month for you, and deals with the leap years that I hadn't got round to doing. Which means I can collapse my </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">for</span><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"> down to:</span><br />
<br />
<br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">for (int i = 1; i < 13; i++)</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">{</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> DateTime startDate = new DateTime(int.Parse(year), i, 1, 0, 0, 0);</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> DateTime endDate = new DateTime(int.Parse(year), DateTime.DaysInMonth(int.Parse(year), i), 30, 23, 59, 59);</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">}</span></div><div><br />
</div><div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Smaller code for the win!</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">EDIT: I just looked <a href="http://msdn.microsoft.com/en-us/library/system.datetime.daysinmonth(v=VS.100).aspx">DaysInMonth</a> up on MSDN and I'm surprised to discover it's been in the Framework since .NET 1.0!</span></div>Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com1tag:blogger.com,1999:blog-1902158034220893892.post-80966559851447278682010-08-14T19:33:00.001+01:002010-08-14T19:48:12.343+01:00A Good Day<div style="font-family: Verdana,sans-serif;">Yesterday had an inauspicious start when the alarm went at 6am. I woke my wife up (again) when getting dressed. And when I got to the station I didn't have time to go to the shop and get a paper to read on the train.</div><div style="font-family: Verdana,sans-serif;"><br />
</div><div style="font-family: Verdana,sans-serif;">But then...</div><div style="font-family: Verdana,sans-serif;"><br />
The ticket inspector had an unexpected sense of humour.</div><div style="font-family: Verdana,sans-serif;">A totally hot woman sat next to me on the train. </div><div style="font-family: Verdana,sans-serif;">I wrote a StackOverflow <a href="http://stackoverflow.com/questions/3474275/checking-hidden-field-is-empty-or-not/3474313#3474313">answer</a> on the hateful editor on my phone. </div><div style="font-family: Verdana,sans-serif;">And it was accepted.</div><div style="font-family: Verdana,sans-serif;">Getting off the train I bumped into an ex-colleague I haven't seen for four or five years.</div><div style="font-family: Verdana,sans-serif;">I got to spend the whole day getting my geek on watching ScottGu present on VS2010, ASP.NET 4, EF4 and MVC...</div><div style="font-family: Verdana,sans-serif;"><br />
</div><div style="font-family: Verdana,sans-serif;">Amusingly, as I was waiting outside the cinema an American girl walked past and I heard her say 'must be a premiere' - I wonder how she'd have reacted if I'd told her we were all waiting to see a man from Microsoft...<br />
<br />
VS2010 and ASP.NET 4</div><div style="font-family: Verdana,sans-serif;"></div><div style="font-family: Verdana,sans-serif;"></div><div style="font-family: Verdana,sans-serif;">The first session was on what's in VS2010 and ASP.NET 4. As I've been using VS2010 since April I wasn't sure just how much I'd get from this session - the answer was, obviously, loads. </div><div style="font-family: Verdana,sans-serif;">I've already been using the HTML snippets, but now I know that there's a setting where I can turn off the requirement for an angle bracket before VS offers to complete the tag for me. What I didn't know is that there's a set of snippets for JavaScript as well. And a <a href="http://jquerysnippets.codeplex.com/documentation?referringTitle=Home">set for jQuery</a>. </div><div style="font-family: Verdana,sans-serif;">We all learned that Scott doesn't like regions round his privates - cue much sniggering, I'm not sure it means quite the same thing in the States. But the learning point was that if you like regions done one way and your team mate prefers another, you can have regions that are private to you and won't show up when your colleague opens the file in VS. Ctrl + M, Ctrl + K is the keystroke to create one of these. </div><div style="font-family: Verdana,sans-serif;">Someone asked if there's a way to label these regions, to which the answer is no, however someone else pointed out that if you put a comment at the top of the region, it can work as a label when you hover over the collapsed region.</div><div style="font-family: Verdana,sans-serif;">I picked up a <i>bundle</i> of new shortcut keys. </div><div style="font-family: Verdana,sans-serif;">Collapse all regions - Ctrl + M, Ctrl + O</div><div style="font-family: Verdana,sans-serif;">Incremental Search - Ctrl + I</div><div style="font-family: Verdana,sans-serif;">Navigate files - Ctrl + Alt + Down Arrow</div><div style="font-family: Verdana,sans-serif;">Navigate to - Ctrl + ,</div><div style="font-family: Verdana,sans-serif;">View Call Hierarchy - Ctrl + K, Ctrl + T</div><div style="font-family: Verdana,sans-serif;"></div><div style="font-family: Verdana,sans-serif;"></div><div style="font-family: Verdana,sans-serif;"><br />
Scott demoed some of the debugging features in VS2010, including pinning of watched variables, conditional breakpoints where the debugger only stops on a certain Boolean condition. And trace points, which allow you to write debugging messages to a TraceListener - optionally you can also continue executing your code, which neatly handles debugging a multi-threaded situation where breaking into the debugger hides the bug you're actually trying to find (<a href="http://en.wikipedia.org/wiki/Uncertainty_principle#Uncertainty_principle_and_observer_effect">the Heisenberg uncertainty principle</a> in action!). <br />
Scott showed how to use the ASP.NET Routing module in WebForms (the same one as used in ASP.NET MVC), and also showed off some of the deployment features, especially the Transforms which allow you to generate custom web.config files for different environments. Scott also told us that in the next couple of weeks there will be a new hosting gallery appearing on http://asp.net, which will allow you to search for a web host based on features they support. <br />
<br />
MVC2 & EF4</div><div style="font-family: Verdana,sans-serif;">I've seen a number of sessions in the last year on MVC and Entity Framework, but this was the first time I actually felt I was starting to 'get' it. I should have Scott sat next to me at work, think how much more productive I'd be!<br />
Due to popular demand (and some well-publicised issues with the registration system for the day), Scott built a system based around developer events. For this session Scott started with a database, and built an entity model from it, then showed some of the features in MVC for displaying and editing data from the model. Highlights for me were the ease of allowing client-side validation - <% HTML.EnableClientValidation %>. That's it, one line of code!I was also very impressed with the scaffolding feature that allows you to build an editor page really quickly for a model. Whereas previously, you'd have written something like <% Html.TextBoxFor(fieldname) %> and the page will output a text-type INPUT tag (where field name is a string value), you can use the scaffolding to say <% Html.EditorFor(fieldname) %>, and the page will output a field appropriate to the data type of the field - a textbox for a string field, a checkbox for a Boolean field etc. And you can take this a level further - if you write <% Html.EditorFor(model) %>, ASP.NET iterates over the class and outputs the set of controls necessary to display and edit all the fields in the class - seriously cool.<br />
In a large application, the number of controllers and views can grow so large as to make it difficult to pick a particular one out of the clutter, so Scott demonstrated how you can split an application up into Areas which allow you to group sets of controllers and views together to make it more manageable. Finally in this session Scott showed off some of the unit testing features. This included the gems that the 'Do you want to create unit tests' dialog when you create a new project is referred to as the 'Guilt' dialog, and the 'No I don't want to create unit tests' radio button is known as the 'I suck' button.<br />
<br />
Windows Phone 7<br />
After lunch, Scott took a (well-deserved) break and handed over to <a href="http://blogs.msdn.com/b/mikeormond/">Mike Ormond</a> to talk about Windows Phone 7. There are two programming models available for WP7, one in Silverlight and one in XNA. The Silverlight model should be used for event-driven type applications, the XNA one is more suited for time-driven apps e.g. game. However both types of apps can use features from the other if necessary. Mike also talked about how applications are distributed to a device, however what wasn't completely clear to me was how, as a corporate developer, if I write an app to be used internally to the company, I distribute the app and whether or not I have to release it to the marketplace. I was, mostly, quite intrigued about the platform as a whole - maybe later in the year I'll look more closely into developing for it.<br />
<br />
Web Futures<br />
The final session saw Scott back and talking about a number of the things that should be released by Microsoft later in the year, including IIS Express, MVC3, code-first Entity Framework and Razor. Of these, the ones that interested me most are IIS Express, and code-first EF. IIS Express I'm looking forward to as it will allow us to locally test our SSL pages (it comes with a local certificate). Code-first EF was interesting, although having not done any EF work I don't really know how much difference it would make. Similarly with Razor, I haven't done any MVC so I couldn't really appreciate the differences. Finally Scott showed off some TDD and in ten minutes explained Dependency Injection. I've been reading odd bits around DI over the last year, but I can honestly say I picked up more in that ten minutes than I did over the preceding 12 months!<br />
<br />
And then we went to the pub with Scott to interrogate him, in which:</div><div style="font-family: Verdana,sans-serif;">I learned that Dependency Injection and Inversion of Control are (more or less) the same thing. </div><div style="font-family: Verdana,sans-serif;">We were all amazed at how much of Microsoft ScottGu runs. </div><div style="font-family: Verdana,sans-serif;">I learned the year the HTML 4 spec was ratified, though Dave Sussman says I can't tell anyone this.<br />
<br />
It was A Good Day.</div>Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com0tag:blogger.com,1999:blog-1902158034220893892.post-58192511098104916022010-08-12T17:48:00.000+01:002010-08-12T17:48:32.367+01:00Data does not exist in the namespace Microsoft.Practices.EnterpriseLibrary<div style="font-family: Verdana,sans-serif;">I started to build a new application this afternoon. It's nothing complicated, it just needs to read all the data for the forum on our Intranet and write it into flat files so we can archive it somewhere on our new improved Intranet. I fired up Visual Studio and knocked up a UI - basically it has a Start button and a number of progress bars. Switching to the code, I added a reference to the Enterprise Library 4.1 Data Access Application Block and wrote some code to read the data. Having got to the first point where I wanted to check that things were going more or less as I wanted them, I hit F5 to build and run the application.</div><div style="font-family: "Courier New",Courier,monospace;">The type or namespace name 'Data' does not exist in the namespace 'Microsoft.Practices.EnterpriseLibrary' (are you missing an assembly reference?)</div><div style="font-family: Verdana,sans-serif;">Er, huh? I hit Rebuild with the same result. </div><div style="font-family: Verdana,sans-serif;">I checked that I'd added the block - yep, there it was in my project References. </div><div style="font-family: Verdana,sans-serif;">Rebuild. No joy. </div><div style="font-family: Verdana,sans-serif;">In the immortal words of Kenneth Williams, <a href="http://www.sadena.com/BBC-Radio/Kenneth%20Williams/Kenneth%20Williams%20-%20Stop%20Messin%20About.mp3">"stop messing about"</a>. I actually fired up Explorer and browsed to the DLL under my Program Files folder to ensure it was there.</div><div style="font-family: Verdana,sans-serif;">Still no joy...</div><div style="font-family: Verdana,sans-serif;"><br />
</div><div style="font-family: Verdana,sans-serif;">And then I had a flash of inspiration. The default .NET Framework version for the application was set to '.NET Framework 4.0 Client Profile' - what if that was causing a problem? That's caught me out before when I've been playing with MEF stuff. I changed it to the .NET Framework 4.0 full profile, hit Rebuild again and - success!</div><div style="font-family: Verdana,sans-serif;"><br />
</div><div style="font-family: Verdana,sans-serif;">I solved my problem, but I'm sure I can't be the only one who's run into this one. It's trivial for me to solve because this application will only ever run on my laptop, but for someone who wants to use the Enterprise Library but also needs a minimal footprint when their app is installed, the two things become mutually incompatible. I can't help feeling that when you add a reference by browsing to a DLL, as I did, that Visual Studio should do a bit of inspection on the DLL and warn you if it's incompatible with the framework version you're currently using.</div>Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com6tag:blogger.com,1999:blog-1902158034220893892.post-25934152213977023152010-07-22T14:20:00.000+01:002010-07-22T14:20:55.220+01:00AppFabric Goes South(ampton)<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">(Very!) Belated thanks to the good developers of the NxtGen user group in Southampton for having me down last week to give my Developers Guide to Distributed Caching with Windows Server AppFabric talk. Despite a horrible journey round the M25, I had a really good time - I felt the session went well, the technology didn't let me down, and there were some really good and interesting discussions during the session and afterwards in the pub. It was also good to put a few faces to Twitter names!</span>Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com0tag:blogger.com,1999:blog-1902158034220893892.post-27201881222758724402010-06-13T18:07:00.001+01:002010-06-13T19:34:12.044+01:00AppFabric Goes to Ireland<div style="font-family: Verdana,sans-serif;">Last week I gave my Distributed Caching with Windows Server Appfabric talk at <a href="http://epicenter.ie/2010.html">EpiCenter</a>, the Irish Software Show, at Trinity College in Dublin. My audience was a little, ahem, disappointing, particularly in the week that AppFabric was officially announced and released, since I only had one audience member, <a href="http://www.markhneedham.com/blog/">Mark Needham</a> of <a href="http://thoughtworks.com/">Thoughtworks</a>, who was presenting in the afternoon. I also had technical troubles with AppFabric again - clearly in a previous life I seriously pissed off the demo gods. I've now torn down my AppFabric demo infrastructure to rebuild it - this also gives me a chance to recompile my demos with the release version of AppFabric - I've been using the Release Candidate.</div><div style="font-family: Verdana,sans-serif;"><br />
</div><div style="font-family: Verdana,sans-serif;">My slides from EpiCenter can be seen on <a href="http://www.slideshare.net/philpursglove/the-need-for-speed-epicenter-2010">Slideshare</a>, and my demo code is downloadable <a href="http://philippursglove.com/velocity/epicenter_csappfabricdemos.zip">here</a>.</div>Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com0tag:blogger.com,1999:blog-1902158034220893892.post-60762272792887124172010-06-08T12:06:00.000+01:002010-06-08T12:06:59.931+01:00Windows Server AppFabric is out!<div style="font-family: Verdana,sans-serif;">As announced at TechEd yesterday, v1 of Windows Server AppFabric was released to the web at the weekend (though like the Release Candidate, I found out the Chris Alcock's excellent <a href="http://blog.cwa.me.uk/">Morning Brew blog</a>). You can download it directly <a href="http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=467e5aa5-c25b-4c80-a6d2-9f8fb0f337d2">here</a>, or through the Windows Platform Installer. There's an installation guide <a href="http://www.microsoft.com/downloads/info.aspx?na=40&p=4&SrcDisplayLang=en&SrcCategoryId=&SrcFamilyId=467e5aa5-c25b-4c80-a6d2-9f8fb0f337d2&u=http%3a%2f%2fgo.microsoft.com%2ffwlink%2f%3fLinkID%3d184618">here</a>. If you've been using the Beta 2 Refresh release, the installer will allow you to upgrade from this to the release version - there are details <a href="http://msdn.microsoft.com/en-us/library/ff637697.aspx">here</a>. </div><div style="font-family: Verdana,sans-serif;"><br />
</div><div style="font-family: Verdana,sans-serif;">Additional coverage:</div><div style="font-family: Verdana,sans-serif;">Official announcement from the <a href="http://blogs.iis.net/appfabric/archive/2010/06/07/windows-server-appfabric-now-generally-available.aspx">AppFabric blog</a> </div><div style="font-family: Verdana,sans-serif;"><a href="http://coolthingoftheday.blogspot.com/2010/06/windows-server-appfabric-v1-rtw-and.html">Greg Duncan</a></div><div style="font-family: Verdana,sans-serif;"><br />
</div><div style="font-family: Verdana,sans-serif;"><br />
</div><div style="font-family: Verdana,sans-serif;"><br />
</div><div style="font-family: Verdana,sans-serif;"><br />
</div>Philhttp://www.blogger.com/profile/03175106028217224674noreply@blogger.com0