tag:blogger.com,1999:blog-44170899486479369492024-03-12T20:52:06.704-07:00NeimkeThe blog of Darren NeimkeAnonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.comBlogger37125tag:blogger.com,1999:blog-4417089948647936949.post-38905577691016552302016-02-01T15:17:00.000-08:002016-02-02T03:26:51.316-08:00Have the ability to rapidly build and run micro-applications<i><span style="font-size: large;">All life is an experiment. The more experiments you make the better.</span></i><br />
<i><span style="font-size: large;">- Ralph Waldo Emerson</span></i><br />
<br />
I'm in the process of developing my own application 'stack' (generic application slices with reusable cross-cutting concerns - e.g. Security, Configuration, and Logging). <br />
<br />
I have most of it in place at the moment, but still need to work out how I will secure my API's. Presently, I am looking at <a href="https://identityserver.github.io/Documentation/" target="_blank">IdentityServer</a> as a possible solution for this.<br />
<br />
This is the sort of solution that I want to be able to design/develop/build/package/release quickly:<br />
<br />
* Web API Service Bus<br />
* Typescript Client<br />
* Identity Management Server (this probably only needs to be build and deployed once)<br />
<br />
I have lots of little ideas that I want to be able to push out and host as an Azure AppService. One of them is a Garden Maintenance Planning application, another one is a Habit Kicker service.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-cpb07-ay5z4/Vq_mMnEw4tI/AAAAAAAAkag/MAyEUOCoOiY/s1600/HabitKicker.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="346" src="http://1.bp.blogspot.com/-cpb07-ay5z4/Vq_mMnEw4tI/AAAAAAAAkag/MAyEUOCoOiY/s640/HabitKicker.PNG" width="640" /></a></div>
<br />
<br />
The Habit Kicker application let's you create a habit that you want to kick - in my case, I am aiming to have alcohol free days (AFD's) and then record success outcomes. The system will push out an alert asking for feedback about whether you have achieved your goal for the day.<br />
<br />
You can see from the user interface that, even for such a simple little idea, there are many problems to be solved:<br />
<ul>
<li>How will notifications be implemented</li>
<li>How will schedules be implemented</li>
<li>What technologies will be used to develop the user interface</li>
<li>How are users identified</li>
</ul>
For these types of micro-applications, it would be desirable to have a consistent, repeatable recipe for build/package/release that would scale across the different application types - e.g. Typescript client, DNX Web application, ASP.NET 4.6.<br />
<br />
Being able to create the infrastructure components and deployment pipeline rapidly, means that you can focus on developing value from as early in Sprint 1 as possible.<br />
<br />
In terms of infrastructure, my plan is to use <a href="https://www.visualstudio.com/en-us/products/visual-studio-team-services-vs.aspx" target="_blank">Visual Studio Team Services</a> for source code hosting, and for Build/Package/Release. Using Azure AppServices as my hosting platform provides me with a high level of control and flexibility. Azure AppServices also have useful platform components such as WebJobs that I can take advantage of.<br />
<br />
The next major problems that I want to solve are:<br />
<br />
<br />
<ol>
<li>Identity and Access Management - I want a low touch solution that is as decoupled from my Application as possible</li>
<li>Build/Package/Release - recipes for different flavors of app, as mentioned above</li>
</ol>
<br />
Please feel free to leave any tips or comments to let me know how you achieve rapid deployment for your little ideas.<br />
<br />
<br />
<b><br /></b>
<b>Relevant posts</b><br />
<br />
<ul>
<li><a href="http://neimke.blogspot.com.au/2016/01/new-project-bootstrap-tasks-for.html" target="_blank">Bootstrapping process for new Typescript applications</a></li>
</ul>
Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com0tag:blogger.com,1999:blog-4417089948647936949.post-16282851781832198412016-01-27T03:45:00.002-08:002016-01-27T13:34:31.202-08:00Configuring .NET Core projects for optimal local development<div lang="en-US" style="margin: 0in;">
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;">When developing an <a href="http://www.hanselman.com/blog/ASPNET5IsDeadIntroducingASPNETCore10AndNETCore10.aspx" target="_blank">ASP.NET Core applications</a>, among other decisions, you need to choose which version of the ASP.NET Core and .NET Core packages to consume. When using .NET Core tooling in its</span></span><span style="font-family: "calibri"; font-size: 14.6667px;"> default state, you will likely bump against the following issues when developing many projects locally:</span><br />
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;"></span></span><br />
<ol>
<li><span style="font-family: "calibri";"><span style="font-size: 14.6667px;"><span style="font-family: "calibri"; font-size: 14.6667px;">The default Nuget settings are a global configuration (</span><span style="font-family: "courier new" , "courier" , monospace; font-size: 14.6667px;">%AppData%\NuGet\NuGet.config</span><span style="font-family: "calibri"; font-size: 14.6667px;">). How do different developers keep their Nuget package source configurations in sync if they are not in source control?</span></span></span></li>
<li><span style="font-family: "calibri";"><span style="font-size: 14.6667px;"><span style="font-family: "calibri"; font-size: 14.6667px;">The default package source folder is a global setting (</span><span style="font-family: "courier new" , "courier" , monospace; font-size: 14.6667px;">%userprofile%\.dnx\packages</span><span style="font-family: "calibri"; font-size: 14.6667px;">). How can you run separate projects against a different .NET Core package versions without getting version conflicts for packages?</span></span></span></li>
</ol>
<br />
<h4>
<span style="font-size: 14.6667px;"><span style="font-family: "calibri";">Choosing a .NET Core version for your solution</span></span></h4>
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;"><a href="https://github.com/aspnet/home" target="_blank">ASP.NET Core source code is developed on GitHub</a> and then pushed to several different Nuget feeds, based on the stability of the code. The cadence and feed choices are as follows:</span></span><br />
<br />
<ul>
<li><a href="https://www.myget.org/F/aspnetvolatiledev/" style="font-family: calibri; font-size: 14.6667px;" target="_blank">aspnetvolatiledev</a><span style="font-family: "calibri"; font-size: 14.6667px;"> – Any package that compiles is pushed here. Only used by contributors dealing with breaking changes between repos.</span></li>
<li><a href="http://myget.org/gallery/aspnetcidev" style="font-family: calibri; font-size: 14.6667px;" target="_blank">aspnetcidev</a><span style="font-family: "calibri"; font-size: 14.6667px;"> – A coherent set of packages that compiled referencing eachother. Used by contributors when building under normal circumstances.</span></li>
<li><a href="http://myget.org/gallery/aspnetvnext" style="font-family: calibri; font-size: 14.6667px;" target="_blank">aspnetvnext</a><span style="font-family: "calibri"; font-size: 14.6667px;"> – A coherent set of signed packages that have passed automated testing. Used by consumers evaluating the latest developments in the stack.</span></li>
<li><a href="http://nuget.org/" style="font-family: calibri; font-size: 14.6667px;">Nuget.org</a><span style="font-family: "calibri"; font-size: 14.6667px;"> – Official releases used by general consumers.</span></li>
</ul>
<br />
<span style="font-family: "calibri"; font-size: 14.6667px;">The choice will depend on your appetite for risk/change/stability. Choosing the Nuget.org release means that your packages will be very stable for a long period (e.g. Beta 5, Beta 6, RC1, RC2, etc.) but you will have a lot of catching up to do when new packages are released due to the high amount of code and API churn that is happening at the moment.</span><br />
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;"><br /></span></span>
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;">In choosing the ASPNETCIDev feed you will avoid monolithic refactors but, instead, you will get hit with regular breaking changes that will impact your development productivity on a daily basis. </span></span><br />
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;"><br /></span></span>
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;">The vNext feed sits between the official feed and the CIDev feed and provides a trade-off between daily breaking changes or a monolithic set of changes.</span></span><br />
<h4>
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;">Restoring Packages</span></span></h4>
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;">.NET Core projects define their dependencies in global.json and project.json files. Global.json identifies the platform version dependency while project.json specifies individual package dependencies. After you have configured these files in your project, it is simply a matter of<a href="http://www.hanselman.com/blog/ExploringTheNewNETDotnetCommandLineInterfaceCLI.aspx" target="_blank"> running the dotnet CLI tool</a> to restore packages from the feed source to your local machine. </span></span><br />
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;"><br /></span></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-Ul3h4GdjOQw/VqipZjYSb_I/AAAAAAAAkVc/bk0_Pg5bumc/s1600/dotnetrestore.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="100" src="http://2.bp.blogspot.com/-Ul3h4GdjOQw/VqipZjYSb_I/AAAAAAAAkVc/bk0_Pg5bumc/s640/dotnetrestore.PNG" width="640" /></a></div>
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;"><br /></span></span>
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;"><br /></span></span>
<span style="font-family: "calibri"; font-size: 14.6667px;">The dotnet restore command uses Nuget configuration to identify which feeds to use when restoring. The user profile defaults for Nuget are located at </span><span style="font-size: 14.6667px;"><span style="font-family: "courier new" , "courier" , monospace;">%AppData%\NuGet\NuGet.config</span></span><span style="font-family: "calibri"; font-size: 14.6667px;">. These defaults are updated when you manage package sources via the Nuget configuration tool in Visual Studio.</span><br />
<span style="font-family: "calibri"; font-size: 14.6667px;"><br /></span>
<span style="font-family: "calibri"; font-size: 14.6667px;">To add the vNext feed source to your defaults, open the configuration tool and add an entry to the MyGet feed</span><br />
<span style="font-family: "calibri"; font-size: 14.6667px;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-r2QzgrmZ_aI/VqipvtWomYI/AAAAAAAAkVk/KZEBsSmPySI/s1600/NugetPkgSources.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="371" src="http://3.bp.blogspot.com/-r2QzgrmZ_aI/VqipvtWomYI/AAAAAAAAkVk/KZEBsSmPySI/s640/NugetPkgSources.PNG" width="640" /></a></div>
<br />
<h4>
<span style="font-family: "calibri"; font-size: 14.6667px;">Configuring per-project settings</span></h4>
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;">Developers should have the best F5 experience possible - which means they should be able to checkout source code and run it without any friction. Thankfully we can enable this by configuring settings on a per-project basis.</span></span><br />
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;"><br /></span></span>
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;">The dotnet restore command will look for and load a local project Nuget configuration before it loads the global configuration from the user profile.</span></span><br />
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;"><br /></span></span>
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;"><span style="font-family: "calibri";">Similarly, command will look for a packages setting in the global.json solution configuration to identify where to locate restored packages before defaulting to </span><span style="font-family: "courier new" , "courier" , monospace;">%userprofile%\.dnx\packages</span><span style="font-family: "calibri";">.</span></span></span><br />
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;"><br /></span></span>
<br />
<h4>
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;">My configuration</span></span></h4>
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;">The following files explain my personal configuration for local projects to achieve projects that are self-describing of their dependencies and which assist with reducing developer friction.</span></span><br />
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;"><br /></span></span>
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;">The first task is to create a local Nuget.config in the root folder of your solution.</span></span><br />
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;"><br /></span></span>
<script src="https://gist.github.com/dneimke/ba8aa6f232f761cb8de9.js"></script>
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;">The first line of the Nuget.config clears any package sources that might be configured at another level - e.g. the global user setting. This ensures that the local Nuget.config, defines all sources that are relevant for the project and that these are checked in to version control with the rest of the source code.</span></span><br />
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;"><br /></span></span>
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;">Next step is to configure a separate location for packages that are restored for the project. This ensures that the project is not impacted by other packages that might exist in the global package store which might have come from a feed which is running at a different cadence to the local project.</span></span><br />
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;"><br /></span></span>
<script src="https://gist.github.com/dneimke/7bd3d3323905706bfc95.js"></script>
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;">At this point, running the dotnet restore command will restore all dependency packages from the vNext feed into a local packages folder in the root folder of the solution.</span></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-Y58Fdhcf0Dk/Vqk31IiFzQI/AAAAAAAAkWE/ULrPqSzASso/s1600/LocalPkgs.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="254" src="http://1.bp.blogspot.com/-Y58Fdhcf0Dk/Vqk31IiFzQI/AAAAAAAAkWE/ULrPqSzASso/s640/LocalPkgs.PNG" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;"><br /></span></span>
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;">The final step is to configure Git so that the packages folder is excluded from version control. This is simply a matter of adding a line to the local .gitignore file for the solution.</span></span>
<br />
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;"><br /></span></span>
<script src="https://gist.github.com/dneimke/a95ba96bcf525e1e28b1.js"></script><br />
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;"><br /></span></span>
<br />
<div style="font-family: calibri; font-size: 11pt;">
<h3 style="font-family: calibri; font-size: 11pt;">
References:</h3>
<br />
<ul>
<li><a href="https://github.com/aspnet/Home/wiki/Configuring-the-feed-used-by-dnu-to-restore-packages" target="_blank">Configuring the feed used by DNU to restore packages</a></li>
<li><a href="https://github.com/aspnet/Home/wiki/Package-Locations" target="_blank">Package Locations</a></li>
</ul>
<br />
<br />
<span style="font-family: "calibri";"><span style="font-size: 14.6667px;"><br /></span></span></div>
</div>
Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com3tag:blogger.com,1999:blog-4417089948647936949.post-48007311189467636142016-01-12T03:22:00.001-08:002016-02-01T15:40:30.207-08:00Bootstrap tasks for new Typescript web projectsEarlier this year, after attending a Microsoft conference, <a href="http://neimke.blogspot.com/2015/11/developing-from-command-line.html" target="_blank">I blogged </a>how the momentum of the developer workflow is moving rapidly towards running tasks from the command line. Since then I have continued to develop skills and knowledge in this area.<br />
<br />
This post is a walk-through of my current workflow for bootstrapping new Typescript web projects for development using VS Code. The high level tasks I execute are:<br />
<br />
<ol>
<li>Create a root folder for the application</li>
<li>Acquire development tools using NPM</li>
<li>Acquire software framework dependencies using Bower</li>
<li>Create the VS Code project definition </li>
<li>Start the application and launch it in a browser</li>
<li>Add the project assets to source control</li>
</ol>
<br />
<h4>
Step 1. Create the project Root Folder</h4>
A straightforward step. You could open Windows Explorer and browse to your root working location and create a new folder. However, as we are going to be working inside of the command shell, we can avoid the friction of opening Explorer by running DOS commands.<br />
<br />
<blockquote class="tr_bq">
<b>NOTE</b>: Since moving to the command line for my workflow, I have leaned more and more on <a href="https://conemu.github.io/" target="_blank">ConEmu</a> as my tool of choice for running command line tasks as it is only ever a keystroke away.</blockquote>
<br />
I launch ConEmu (CTRL+~) and type:<br />
<br />
<pre>> cd \code
> md myproject
> cd myproject</pre>
<br />
That gets me a new project folder named myproject in my development working folder and places the location of my command prompt in the new folder.<br />
<br />
<h4>
Step 2. Acquire Development Tools</h4>
<div>
For the purpose of my bootstrapping I grab the following development tools:</div>
<div>
<ul>
<li><b>Typescript</b>: The tsc compiler will compile our Typescript to Javascript</li>
<li><b>Bower</b>: package manager for managing client side dependencies such as Bootstrap and Angular</li>
<li><b>Browser Sync</b>: Use to serve the app and to provide live updates in the browser during development</li>
</ul>
<div>
Command line tasks for installing development tools using npm:<br />
<br /></div>
<div>
<script src="https://gist.github.com/dneimke/6e9f20bc8b674ac87781.js"></script>
</div>
<br />
<br />
Running these commands creates a <i>package.json</i> folder that contains the node configuration information. It also creates a node_modules folder where the packages that get downloaded are stored. <br />
<br />
<blockquote class="tr_bq">
<b>NOTE</b>: Later the node_modules folder is excluded from source control as the packages can be pulled down on demand using the <i>npm install </i>command - typically either on the build server or on another developer machine.</blockquote>
<br />
<h4>
Step 3. Acquire Software Dependency Packages</h4>
</div>
<div>
My standard software frameworks are Bootstrap and Angular so I install them as part of the project setup. As with npm, the first step is to initialize the folder for bower and then run commands to pull down and install the packages:</div>
<br />
<pre>bower init
bower install angular --save
bower install bootstrap --save</pre>
<br />
<h4>
Step 4. Create the VS Code Project</h4>
<div>
For this step, launch VS Code from the current folder using the following command:</div>
<br />
<pre>code .</pre>
<div>
<br /></div>
<div>
<blockquote class="tr_bq">
<b>Note: </b>This assumes that you have VS Code installed on your machine and that it is configured on your PATH variable.</blockquote>
<br />
In the root of the project, add a file named <b>app.cmd</b> and add the following command:<br />
<br />
<pre>browser-sync start --server --port 3001 --index default.html --files="./*"</pre>
<br />
This command launches the app using a web server. <a href="https://www.browsersync.io/" target="_blank">Browser Sync</a> is a node package that was installed in the tooling step. It watches files for changes and then refreshes the browser to show the updates.<br />
<br />
Update the package.json file by configuring the start command to launch the website using the command that was just created.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-qk7k3ihziKI/VpTc3Oxp50I/AAAAAAAAkMI/cfr7iUj7_-s/s1600/npmconfig.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="298" src="http://3.bp.blogspot.com/-qk7k3ihziKI/VpTc3Oxp50I/AAAAAAAAkMI/cfr7iUj7_-s/s400/npmconfig.PNG" width="400" /></a></div>
<br />
With this piece of config in place, the site can now be launched in a browser from the command line using either of the following commands:<br />
<br />
<pre># launch using npm
> npm start
# launch using app.cmd
> app
</pre>
<br />
<br />
<blockquote class="tr_bq">
<b>NOTE</b>: All of these tasks can be automated using VS Code's task runner but I am not yet as familiar with that task runner as I am with the approach shown in this article. </blockquote>
<br />
<br />
Typescript projects require a <a href="https://github.com/Microsoft/TypeScript/wiki/tsconfig.json" target="_blank">tsconfig file</a> that defines compiler settings and identifies the Typescript files to be compiled. Create a file named tsconfig.json in the root of the folder and add the following configuration information.<br />
<br />
<script src="https://gist.github.com/dneimke/5eaa4e40a0d1855e17b6.js"></script>
<br />
As the project is developed, files get added to the files element and further compilation options added as necessary.<br />
<br />
The project will need a suitable default html file and this is the basic template that I have been using.<br />
<br />
<script src="https://gist.github.com/dneimke/031c33da261d85b9aa4a.js"></script>
<br />
<br />
The last task for setting up our VS Code project is to add a build task. This allows us to press CTRL+SHIFT+B to compile the project. To create the initial tasks file, press CTRL+SHIFT+B and VS Code will prompt to create the file:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-kXg1ZUxKSvw/VpTfOIfn5-I/AAAAAAAAkMU/CaZukVmGHC0/s1600/VSBuild.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="163" src="http://2.bp.blogspot.com/-kXg1ZUxKSvw/VpTfOIfn5-I/AAAAAAAAkMU/CaZukVmGHC0/s400/VSBuild.PNG" width="400" /></a></div>
<span id="goog_1146100254"></span><span id="goog_1146100255"></span><br />
After creating the task runner, overwrite the default content following task definition to compile Typescript assets:<br />
<br />
<script src="https://gist.github.com/dneimke/cc5e126764706d135159.js"></script>
<br />
<br />
At this point you should be able to press CTRL+SHIFT+B and see that the project builds - later when you have Typescript files, you will see that they get built into the js folder which is what we configured in the compilation options earlier.<br />
<br />
You should also be able to run npm start and see the default page load up in a browser.<br />
<br />
If that has worked so far... well done!<br />
<br />
<h4>
Step 6. Add assets to source control</h4>
With all of that hard work, the last thing you want is to lose content that has been created. The final step is to configure Git and commit the project to source control. To start with, create a Git ignore file to exclude Typescript generated content, and packages.<br />
<br />
The file should be named .gitignore and contain the following definition.<br />
<br />
<blockquote class="tr_bq">
<b>NOTE</b>: <a href="http://www.hanselman.com/blog/HowToCreateAFileWithADotPrefixInWindowsExplorer.aspx" target="_blank">Read Scott Hanselman's article</a> to learn how to create files that start with a dot in Windows.</blockquote>
<br />
<script src="https://gist.github.com/dneimke/421f8470a9f8c078cda5.js"></script>
<br />
<br />
<br />
With the .gitignore configuration in place, all that is left is to run Git commands to initialise the repository and commit the assets to version control:<br />
<br />
<pre>> git init
> git add .
> git commit -m "Initial Commit"</pre>
<br />
<br /></div>
<div>
</div>
Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com0tag:blogger.com,1999:blog-4417089948647936949.post-53151670421402644632016-01-12T02:01:00.000-08:002016-01-12T02:01:21.599-08:00Testing Gist embeds in BloggerAlthough I've had my blog here for a number of years now, it's largely been inactive. Now that I've started to stir again, it feels as though there is some unnecessary friction in writing posts simply because I don't enjoy the Blogger platform.<br />
<br />
The main gripe I have is the lack of control you have over the HTML that gets generated - it's akin to the old SharePoint platform and what it did to content.<br />
<br />
This post is a test post to see how embedded Gists appear in Blogger.<br />
<br />
<script src="https://gist.github.com/ericelliott/2b624243f030405abe0c.js"></script>Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com3tag:blogger.com,1999:blog-4417089948647936949.post-27830411339809222592015-11-23T14:34:00.002-08:002015-11-23T14:34:34.191-08:00Using Powershell to work with JsonToday I decided to look into working with Json in Powershell. Json is rapidly overtaking Xml as the preferred format for describing projects and build artifacts, so it makes sense to learn how to integrate it with tools such as AppVeyor scripts, <a href="https://www.visualstudio.com/en-us/integrate/extensions/develop/add-build-task" target="_blank">Visual Studio Team Services Build Tasks</a> or <a href="http://docs.octopusdeploy.com/display/OD/Custom+scripts" target="_blank">Octopus deployment steps</a>.<br />
<br />
A quick search online led me to discover the following two Poweshell cmdlets that can be used when working with Json:<br />
<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>• ConvertFrom-Json<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>• ConvertTo-Json<br />
<br />
Using <a href="http://cmder.net/" target="_blank">cmder</a>, I created a new Powershell tab and started typing:<br />
<br />
<pre class="brush: powershell">> cd \temp
> md jsontests
> new-item "testjson.js"
> notepad "testjson.js"
</pre>
<br />
I then added the following content to the file:<br />
<br />
<pre class="brush: javascript">{
Name: "Darren Neimke",
Age: "42",
Gender: "Male"
}</pre>
<br />
Flicking back to the console, I typed the following Powershell command to confirm that I could read the content:<br />
<br />
<pre class="brush: powershell">Get-Content "testjson.js"</pre>
<br />
Piping the raw content to ConvertFrom-Json produced the following:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-MK3_qAAv3bo/VlOR4cTSylI/AAAAAAAAjuY/Pvo5r6yF3i4/s1600/cmder-output.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-MK3_qAAv3bo/VlOR4cTSylI/AAAAAAAAjuY/Pvo5r6yF3i4/s1600/cmder-output.PNG" /></a></div>
<br />
<br />
To expand my use of Powershell, I opened the Powershell ISE and created the following script:<br />
<br />
<pre class="brush: powershell">$path = ".\testjson.js"
$raw = Get-Content $path -raw
$obj = ConvertFrom-Json $raw
$obj.Age = 45 # I always lie about my age!
Write-Host $obj # Dump obj to console
Set-Content $path $obj</pre>
<br />
<br />
The ISE amazed me in how it was able to infer the schema of the $obj instance and provided me with Intellisense after that!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-dmJV1weHIZs/VlOR4WT4BpI/AAAAAAAAjuU/8TwLSPn5f0Q/s1600/powershell-object-variable.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-dmJV1weHIZs/VlOR4WT4BpI/AAAAAAAAjuU/8TwLSPn5f0Q/s1600/powershell-object-variable.PNG" /></a></div>
<br />
<br />
Running that script updated the value of the Age property and saved it back to the file.<br />
<br />
<br />
<br />
<b>Things I Learned:</b><br />
<br />
<ul>
<li>Using ISE to create a Powershell script</li>
<li>How to pass the content of a file to another cmdlet using piping and variables</li>
<li>Updating Json content using variables</li>
<li>Saving a file</li>
</ul>
<br />
<br />
<b>References:</b><br />
<br />
<ul>
<li>Working with Json - <a href="http://powershelldistrict.com/powershell-json/%C2%A0" target="_blank">http://powershelldistrict.com/powershell-json/ </a></li>
<li>Understanding File Content - <a href="https://technet.microsoft.com/en-us/library/ee692806.aspx">https://technet.microsoft.com/en-us/library/ee692806.aspx</a></li>
<li>Updating File Content - <a href="http://searchwindowsserver.techtarget.com/feature/Editing-content-with-Windows-PowerShell">http://searchwindowsserver.techtarget.com/feature/Editing-content-with-Windows-PowerShell</a></li>
</ul>
<br />
<div>
<br /></div>
Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com0tag:blogger.com,1999:blog-4417089948647936949.post-31125917593328945552015-11-23T00:32:00.000-08:002015-11-23T00:32:08.269-08:00EntityFramework and the challenge of Entity Serialization<div>
Let's take the following couple of entities:<br />
<br />
<br />
<pre class="brush: csharp">public class Parent
{
public int Id { get; set; }
public string Name { get; set; }
public List<child> Children { get; set; }
}
public class Child
{
public int Id { get; set; }
public string Name { get; set; }
public int ParentId { get; set; }
public Parent Parent { get; set; }
}
</child></pre>
<br />
<br />
And pass them through an Entity Framework query that looks like this:<br />
<br />
<br /></div>
<pre class="brush: csharp">var parent = db.Parent
.Include(par => par.Children)
.Where(par => par.Name == "Somename")
.FirstOrDefault();
</pre>
<div>
<br />
It's interesting to see that we can then write the following LINQ to query the result:
<br />
<br />
<br /></div>
<pre class="brush: csharp">var result = parent.Children[0]
.Parent.Children[0]
.Parent.Children[0]
.Parent.Children[0]
.Parent.Children[0]
.Parent.Children[0]
.Parent.Children[0]
.Parent.Children[0]
.Parent.Children[0]
.Parent;
</pre>
<div>
<br />
Here, the <i>result</i> variable refers to a Parent type which will have a collection of Children which will have a Parent ... oh never-mind, I'm sure you see where this ends!<br />
<br />
When building a Web API application, we might think of exposing this type of query through a Controller action. In such a case, how should the serializer deal with the cascading references.<br />
<br />
One solution is to use a Serialization solution such as the <a href="http://www.newtonsoft.com/json/help/html/ReferenceLoopHandlingIgnore.htm" target="_blank">ReferenceLoopHandler</a> that is found in the Json.Net library to ignore circular references. This switch tells the serializer to exclude reference properties after they have been found the first time.<br />
<br />
Another solution is to shape the data to return specific fields from the service operation.<br />
<br /></div>
<pre class="brush: csharp">var parentView = new
{
ParentId = parent.Id,
ParentName = parent.Name,
ChildCount = parent.Children.Count,
Children = parent.Children.Select(c =>
new {
Id = c.Id,
Name = c.Name
}
)
};
</pre>
<div>
<br />
<br />
This approach helps to control the shape of the data and to have greater certainty over what is being returned.<br />
<br />
Taking this one step further we would create custom Data Contract classes and return those instead of the loosey-goosey approach of returning anonymous types.<br />
<br />
<br />
<pre class="brush: csharp">var parentDataContract = db.Parent.Include(par => par.Children)
.Select(par =>
new ParentView
{
Id = par.Id,
Name = par.Name,
Children = par.Children.Select(c =>
new ParentView.ChildView
{
Id = c.Id,
Name = c.Name
}
)
}
);
</pre>
<br />
This approach gives us better static checks across the application, allows for reuse of Data Contracts across separate operations, and allows us to see where different contracts are being used. From a versioning and maintenance point of view, this would be the gold standard.<br />
<br />
What is your approach to designing service endpoints? Do you mix RESTful with RPC-style design all in the same Controllers or do you separate them out into their own classes of service?</div>
Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com1tag:blogger.com,1999:blog-4417089948647936949.post-91234278041743312882015-11-21T15:12:00.002-08:002015-11-21T15:12:40.881-08:00Developing from the Command LineAs I have mentioned, the developer workflow has changed quite a bit. In case you haven't heard or kept up, it looks something like this:<br />
<br />
<ul>
<li>From the command line, use Yeoman to generate a new project > yo webapp</li>
<li>From the command line, initialize the folder as a new Git repository > git init</li>
<li>From the command line, open the new project using an Editor of your choice > code .</li>
</ul>
<br />
As you can see, much more is being done from the command line. New tools such as cmder are being used to gain quick access to command windows for Powershell/Node/etc to assist and speed up this flow. Cmder is great because it has transparency, allows you to have multiple tabs, and is easily summoned and hidden away using CTRL+`.<br />
<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-G4emIpMxdh4/VlD5hB_Z_rI/AAAAAAAAjso/0qmwev-OfjA/s1600/cmder.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-G4emIpMxdh4/VlD5hB_Z_rI/AAAAAAAAjso/0qmwev-OfjA/s1600/cmder.png" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
For my task today I decided to initialize a Git repository, add a file, make changes to the file, and commit those files to a Git branch all from the command line. I wanted to use Powershell to create the project folder and the initial file so that I could tick my "One thing per day" goal of using PS for something at least once per day!<br />
<br />
I found the New-Item (alias: ni) cmdlet which allows you to create a variety of item types. To create a new folder, give it the -ItemType of 'directory' and then the name of the folder that you wish to create. E.g.<br />
<br />
<pre>> New-Item -ItemType directory myNewDirectory</pre>
<br />
I then went ahead and used Git to initialize a repo in the new folder:<br />
<br />
<pre>> git init</pre>
<br />
New-Item can also be used to create files, just give it the name of the file that you want to create:<br />
<br />
<pre>> ni "file1.txt"
> notepad "file1.txt"</pre>
<br />
This adds a new file named file1.txt and opens it in Notepad.<br />
<br />
<pre>> git add .
> git commit -a -m "Adding file1.txt"</pre>
<br />
This will commit the changes of to your Git repo. It's easy to visualize what's happening in Git Extensions:<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-ZB4DS7JDI7c/VlD5jKpzwZI/AAAAAAAAjs8/ybhsZyFHNpI/s1600/git-extensions.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-ZB4DS7JDI7c/VlD5jKpzwZI/AAAAAAAAjs8/ybhsZyFHNpI/s1600/git-extensions.png" /></a></div>
<span style="white-space: pre;"> </span><br />
<br />
The folder can be opened using VS Code using code and a dot "." to open the folder that you are currently in:<br />
<br />
<pre>> code .</pre>
<br />
After playing around with Git for a while, I wanted to delete my test folder so I typed Remove- and pressed CTRL-SPACE to find out if Powershell had a Remove-Item command<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-5TOJiywuul8/VlD5i9ODuTI/AAAAAAAAjs4/HObpK_P29gk/s1600/remove-item.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-5TOJiywuul8/VlD5i9ODuTI/AAAAAAAAjs4/HObpK_P29gk/s1600/remove-item.png" /></a></div>
<br />
And sure enough it did. So I finished with the following PS command to blow away my test folder:<br />
<br />
<pre>> rm "\testdir" -force</pre>
<br />
<b>What I Learned:</b><br />
<br />
<ul>
<li>When using cmder, I can start typing the name of a command and then use CTRL+SPACE to find all matching cmdlets</li>
</ul>
Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com0tag:blogger.com,1999:blog-4417089948647936949.post-90278375101327411442015-11-20T04:04:00.001-08:002015-11-20T04:05:59.635-08:00Doing 1 thing each day using PowershellWhile at Ignite on the Gold Coast this week, it became very obvious to me that there are some really key technologies that I need to be across. Watching people develop code and seeing them zip around using the Command line and various package managers highlighted where things are at with the developer workflow.<br />
<br />
Technologies that I have committed to being across are:<br />
<ul>
<li>Yeoman</li>
<li>Powershell</li>
<li>Git</li>
<li>Grunt/Gulp</li>
<li>Chocolatey</li>
<li>Visual Studio Team Services</li>
</ul>
To ensure that I remain curious and stay on track, I'm going to try and do one thing with Powershell each day. Today's task is…<br />
<br />
<b>Delete project.lock.json files from a solution</b><br />
This was a bigger issue in the past than it seems to be now, but I found that I regularly needed to manually delete the DNX lock files that were being generated by dnu.<br />
<br />
The final product:<br />
<br />
<pre class="brush: ps">gci "\repos\dneimke\EF7Demo.CoffeeStore\*" -include "project.lock.json" -recurse | foreach($_) {rm $ _.fullname}</pre>
<br />
<b>What I Learned:</b><br />
<ul>
<li>The Get-Help cmdlet is a great resource for learning about how other cmdlets work</li>
<li>Get-Alias lists the aliases for all cmdlets</li>
<li>Get-ChildItem takes a -Path which makes it easy to list items in a folder - e.g. Get-ChildItem -Path \repos\test</li>
<li>Include seems to be the better way to target a specific pattern of file rather than -Filter</li>
</ul>
<br />
<b>Resources:</b><br />
<ul>
<li><a href="http://blogs.technet.com/b/heyscriptingguy/archive/2014/02/03/list-files-in-folders-and-subfolders-with-powershell.aspx">http://blogs.technet.com/b/heyscriptingguy/archive/2014/02/03/list-files-in-folders-and-subfolders-with-powershell.aspx</a> </li>
<li><a href="http://blogs.technet.com/b/heyscriptingguy/archive/2006/10/23/how-can-i-use-windows-powershell-to-delete-all-the-tmp-files-on-a-drive.aspx">http://blogs.technet.com/b/heyscriptingguy/archive/2006/10/23/how-can-i-use-windows-powershell-to-delete-all-the-tmp-files-on-a-drive.aspx</a></li>
</ul>Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com0tag:blogger.com,1999:blog-4417089948647936949.post-81079162073778648542015-11-18T21:18:00.000-08:002015-11-18T21:29:12.667-08:00Getting Started with EF7 - Adding EF7 to a new ProjectWhile on the Gold Coast at Ignite, I presented on the new version of Entity Framework (EF7) while my colleague Jon spoke about the broader topic of .NET vNext.<br />
<br />
In my talk, I gave 4 demos:<br />
<ol>
<li>Walkthrough showing how to add EF7 to a new project</li>
<li>Using SQL Profiler to show the queries that EF7 generates for various scenarios</li>
<li>Adding Migrations and Seeding to your application</li>
<li>Using the new InMemoryProvider to easily unit test code that depends on EF7 data contexts</li>
</ol>
For the first demo I really wanted to show how simple it is to get started with EF7 and how the new component architecture works with respect to Nuget packaging.<br />
<br />
For my first demo, I started off by creating a new Console Application (Package) project from the Web Templates.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-Uqa_0KWvMkw/Vk1XZg5ErNI/AAAAAAAAjow/Bprw8bxllTk/s1600/vs2015-new-project.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-Uqa_0KWvMkw/Vk1XZg5ErNI/AAAAAAAAjow/Bprw8bxllTk/s1600/vs2015-new-project.PNG" /></a></div>
<br />
The Solution must be configured so that the runtime version is aligned with a runtime that you have installed and Nuget is knows which Package Source contains the versions of the dependencies that you want to use.<br />
<br />
To find which runtime versions you are installed on your machine, use the DNVM list command:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-gSrqcN-J5aY/Vk1Xt10MUKI/AAAAAAAAjo0/MIrRNawfvb4/s1600/dnvm-list.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-gSrqcN-J5aY/Vk1Xt10MUKI/AAAAAAAAjo0/MIrRNawfvb4/s1600/dnvm-list.png" /></a></div>
<br />
<br />
This shows that my machine is currently configured to use the 1.0.0-rc2-16183 clr x64 runtime, so the first thing I do is to change the global.json solution file to match.<br />
<br />
<pre class="brush: javascript">{
"projects": [ "src", "test" ],
"sdk": {
"version": "1.0.0-rc2-16183"
}
}
</pre>
<br />
Nuget needs to know where to look when it restores packages. This can be done by adding it in the Nuget.Config file.<br />
<br />
In this case the ASPNETCIDev source which is hosted on MyGet is where I want to get the EF packages from as contains the most recent packages from the ASPNET daily CI build process.<br />
<br />
<pre class="brush: xml"><?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="aspnetcidev" value="https://www.myget.org/F/aspnetcidev/api/v3/index.json" />
</configuration>
</pre>
<br />
The last thing to do is to add references for the EF7 dependencies that I need. I this case I'm after the following 3 packages:<br />
<br />
<ol>
<li><b>EntityFramework.Core</b>: Contains core logic for DbSets, DbContexts, DataAnnotations, Querying, ChangeTracking, and Configuration among other things. </li>
<li><b>EntityFramework.Commands</b>: A set of commands that can be used to create Migrations, Update Databases, and to scaffold an application from an existing database.</li>
<li><b>EntityFramework.MicrosoftSqlServer</b>: A database provider for using EF against a Microsoft SQL Server database.</li>
</ol>
<br />
Each of these packages represent a single project in the EntityFramework repository which is available to view in <a href="https://github.com/aspnet/EntityFramework/tree/dev/src" target="_blank">this GitHub repository</a>.<br />
<br />
<pre class="brush: javascript">"dependencies": {
"EntityFramework.Core": "7.0.0-*",
"EntityFramework.Commands": "7.0.0-*",
"EntityFramework.MicrosoftSqlServer": "7.0.0-*"
},
"commands": {
"ConsoleApp10": "ConsoleApp10",
"ef": "EntityFramework.Commands"
},
</pre>
<br />
The "ef" command which is added to the project commands can be used to run the EF commands using DNX. <br />
<br />
At this point, EF7 is configured and available to use. To test this, jump to the command line at the root of your project and type dnx ef. You should see the Magic Unicorn splash screen.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-HP4aiWngC60/Vk1ayAFs-2I/AAAAAAAAjpE/YckdLMuRkuU/s1600/magic-unicorn.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-HP4aiWngC60/Vk1ayAFs-2I/AAAAAAAAjpE/YckdLMuRkuU/s1600/magic-unicorn.PNG" /></a></div>
<br />
<br />
<br />
I finished the demo by creating a simple DbContext which contained a couple of DbSet entities and created a Migration using the EntityFramework Commands so that I could start working against a database.<br />
<br />
What I hoped to achieve through this demo was to show the configuration points and how they connect the application to its environment and dependencies. <br />
<br />
It is important to take note of the benefits that are achieved from the EF7 'ground up' rewrite which has delivered multiple, lightweight packages which empowers application developers to take only what they need in terms of dependencies. Don't need Commands? Simple, don't take that dependency! Over time, this will enable more rapid innovation from Microsoft's end and increase flexibility and performance on the applications side.<br />
<br />
If you are interested in taking a look at the sample code from my demos, you can find it in <a href="https://github.com/dneimke/coffeestore" target="_blank">this GitHub repository</a>.<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com0tag:blogger.com,1999:blog-4417089948647936949.post-89114399815079531532013-07-14T00:45:00.003-07:002013-07-14T00:45:50.177-07:00Problem trying to run a Web Application using Visual Studio 2013 Preview <br />
I'm putting this here in the hope of saving some other poor soul the hour I lost this afternoon while playing around with a fresh Visual Studio 2013 Preview installation (Visual Studio Version 12).<br />
<br />
I created a new Web Application (MVC Template) and pressed F5 to start it in debug mode.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://1.bp.blogspot.com/-ClKmOuKFnwM/UeJT3R0XDwI/AAAAAAAAUQ4/HeSUBh9OXOk/s1600/Capture.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="225" src="http://1.bp.blogspot.com/-ClKmOuKFnwM/UeJT3R0XDwI/AAAAAAAAUQ4/HeSUBh9OXOk/s320/Capture.PNG" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Launch a new web application from within Visual Studio</td></tr>
</tbody></table>
I was immediately presented with the following error dialog from within Visual Studio.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-Ym7WutBeph8/UeJUFpXQ7lI/AAAAAAAAURA/oQn1cHvaFyM/s1600/Capture.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="141" src="http://2.bp.blogspot.com/-Ym7WutBeph8/UeJUFpXQ7lI/AAAAAAAAURA/oQn1cHvaFyM/s320/Capture.PNG" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td class="tr-caption" style="font-size: 13px;"><span style="font-size: x-small;">Microsoft Visual Studio. </span></td><td class="tr-caption" style="font-size: 13px;"><br /></td><td class="tr-caption" style="font-size: 13px;"><span style="font-size: x-small;">Process with an Id of xxxx is not running. </span></td></tr>
</tbody></table>
</td><td class="tr-caption"><br /></td><td class="tr-caption"><br /></td><td class="tr-caption"><br /></td><td class="tr-caption"><br /></td><td class="tr-caption"><span style="font-size: x-small;"> </span></td></tr>
</tbody></table>
I also saw the following text in my debug console window: <i>The program '[xxxx] iisexpress.exe' has exited with code 0 (0x0)</i><br />
<br />
The problem turned out to be an incorrect configuration for an IIS Express application pool setting which I found in my <span style="font-family: Courier New, Courier, monospace;">\users{your username}\mydocuments\IISexpress\config applicationhost.config</span> configuration file. <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-QtMbVtWMvMk/UeJW25gi-hI/AAAAAAAAURQ/WLXihdpUtBI/s1600/Capture.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="107" src="http://2.bp.blogspot.com/-QtMbVtWMvMk/UeJW25gi-hI/AAAAAAAAURQ/WLXihdpUtBI/s640/Capture.PNG" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The managedRuntimeVersion was mis-configured by default</td></tr>
</tbody></table>
I needed to change the framework version for the default app pool to match the current framework version that is installed for .NET 4. In my case, that meant changing the version to v4.0.30319.<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com5tag:blogger.com,1999:blog-4417089948647936949.post-14731466089891118792012-09-13T05:22:00.001-07:002012-09-13T05:22:13.693-07:00How to Use Google Plus CirclesA common question I hear is "<i>How can I get value from Circles in Google+</i>" so I thought I'd list a few ways that I find them helpful. Firstly here's an image that shows what my Circle strategy looks like:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-iOohINnMcxo/UE2L83aIOLI/AAAAAAAAGp4/Q2jqDNtX4lQ/s855/Capture.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="478" src="http://2.bp.blogspot.com/-iOohINnMcxo/UE2L83aIOLI/AAAAAAAAGp4/Q2jqDNtX4lQ/s640/Capture.PNG" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<div class="separator" style="clear: both;">
As you can see, I don't have hundreds of Circles - although I wouldn't necessarily be opposed to having that many either. Here are my top 5 reasons for using Circles:</div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<b><span style="font-size: large;">Privacy</span></b></div>
<div class="separator" style="clear: both;">
An obvious initial reason for segregating users into Circles is to limit the scope of information that you share. Again, this is a key driver behind my <b>[Colleagues]</b> and<b> [Family] </b>Circles. Having the ability to post information directly to those groups allows me to limit information from being seen by people that it might not be relevant for. </div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<b>Example</b><b>:</b> I'm at the beach and I use my mobile phone to take some photos. When I get home, the photos are instantly sync'd with my G+ account as soon as my phone hits the Wifi. From there it's just a couple of clicks to share those photos with my family members by posting them to the <b>[Family]</b> Circle.</div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<b><span style="font-size: large;">Noise filtering</span></b></div>
<div class="separator" style="clear: both;">
I know how frustrated I feel when I see other people clogging up my feed with their own personal interests (e.g. excessive posts about cats) and so, I believe that it is really important to be aware of and manage to the amount of "noise" that I emit to other individuals. </div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<b>Example:</b> I'm confident my <b>[Hockey]</b> friends don't mind me posting several updates a day about hockey related stuff (e.g. pictures, embedded YouTube video's, etc.). However add that up with my <b>[Developer Community]</b> related posts, and a few other general posts and suddenly I'm at risk of having people de-circle me because I'm too noisy. </div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
Having a <b>[Hockey]</b> circle allows me to post hockey-specific stuff to just those members and thus reduces the amount of "noise" that I'm sending to people with no interest in hockey whatsoever.</div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<b>Tip: </b>A neat feature is <b>[Your Circles]</b>. <b>[Your Circles]</b> is one step back from <b>[Public]</b> and allows you to easily share information with the widest scoped audience. In <a href="https://www.google.com/settings/plus" target="_blank">Settings</a> you can manage how wide that scope is by managing which Circles are included in the <b>[Your Circles]</b> scope:</div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-mU-tyg5uSz8/UFHNMlNrXkI/AAAAAAAAGrs/-fwoOJ1YIX0/s1600/GPlusYourCircles.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="384" src="http://1.bp.blogspot.com/-mU-tyg5uSz8/UFHNMlNrXkI/AAAAAAAAGrs/-fwoOJ1YIX0/s640/GPlusYourCircles.PNG" width="640" /></a></div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<b><span style="font-size: large;">Scanning</span></b></div>
<div class="separator" style="clear: both;">
The Internet provides us with unlimited opportunities to access information, but managing the signal to noise level is a constant challenge. <b>[News and Information]</b> and<b> [Tech News]</b> are Circles where I've add lots of providers and therefore receive a great deal of information. To deal with the resultant "noise", I then tune the volume of information I receive from them in my main feed by using the following tools. </div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<b>Tune the amount of information displayed in the main feed</b></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-VBgyuSGLEhs/UFHOUYaujbI/AAAAAAAAGr0/IqHNZUl5fCo/s1600/GPlusFiltering2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="98" src="http://1.bp.blogspot.com/-VBgyuSGLEhs/UFHOUYaujbI/AAAAAAAAGr0/IqHNZUl5fCo/s640/GPlusFiltering2.PNG" width="640" /></a></div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<b>Click on filters to display all items for a given Circle</b></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-pfQHfIRVuXU/UFHOeOLrS1I/AAAAAAAAGr8/fqcElMAvXh4/s1600/GPlusFiltering.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="242" src="http://3.bp.blogspot.com/-pfQHfIRVuXU/UFHOeOLrS1I/AAAAAAAAGr8/fqcElMAvXh4/s640/GPlusFiltering.PNG" width="640" /></a></div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<b>Drag Circles to change their order so that most common ones are displayed first</b></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-8nOSEIiniqY/UFHOwFUZjjI/AAAAAAAAGsE/RGvd6tUkkRA/s1600/GPlusFiltering1.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="194" src="http://4.bp.blogspot.com/-8nOSEIiniqY/UFHOwFUZjjI/AAAAAAAAGsE/RGvd6tUkkRA/s640/GPlusFiltering1.PNG" width="640" /></a></div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<b><span style="font-size: large;">Search and Organize</span></b></div>
<div class="separator" style="clear: both;">
In addition to the above mentioned benefits, posting to Circles acts as a way of grouping so that content can easily be found later from among the masses of other posted content. </div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<b>Example:</b> Although I may not remember the exact content of something posted, I may be able to find it by recalling that it was<b> [Hockey]</b> related. Given that knowledge I could filter my main feed by the<b> [Hockey]</b> Circle and then scroll through the reduced amount of information to locate a post I'm after.</div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<b><span style="font-size: large;">Integration across the Google landscape of products </span></b></div>
<div class="separator" style="clear: both;">
Given the integration of G+ across the Google sphere of products, it shouldn't come as a surprise that your investment Circles can be leveraged in other applications. </div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<b>Example:</b> Circles flow through into Gmail, and therefore provide a useful way to find and organize communication from contacts by filtering based on the Circles they belong to. This is a key driver behind having my<b> [Hockey]</b>, <b>[Family]</b>, and <b>[Business]</b> Circles.</div>
<br />
<br />Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com1tag:blogger.com,1999:blog-4417089948647936949.post-15919269190772713402012-09-09T03:19:00.001-07:002012-09-09T03:19:46.614-07:00Getting started with using Pub on Windows – The Dart Package Manager<p>The Dart language is a thriving community that is growing and with it come the tools that assist with doing modern development. One of the key tools that define modern development is a package manager and with Dart, the job of package management falls upon the Pub tool. You can read an <a href="http://www.dartlang.org/docs/pub-package-manager/" target="_blank">overview of the Pub tool</a> on the <a href="http://www.dartlang.org" target="_blank">Dartlang.org</a> website.</p> <p>A common question that I see in new groups is “How do I use pub on Windows?”. In this article I’ll walk through using pub to help get the <a title="An implementation of Minesweeper in Dart." href="https://github.com/kevmoo/sweeper.dart" target="_blank">Dartsweeper</a> application downloaded from <a href="http://github.com/" target="_blank">GitHub</a> and running on your machine. The basic steps that we are about to walk through are:</p> <ul> <li>Install the Dart Editor on your machine</li> <li>Install Git (distributed revision control and source code management (SCM) system)</li> <li>Update some Windows Environment variables</li> <li>Clone the Git source that we want</li> <li>Run Pub to install dependencies</li> <li>Run the application from within Dart Editor</li></ul> <p>OK, let’s get started</p> <p><strong>Get the Dart SDK</strong></p> <p>To get started, you need to have a few things in place on your machine. The first thing is to ensure you have the Dart SDK. The best way to get that is to download the Dart Editor which contains the Dart SDK files. You can get this from the <a href="http://www.dartlang.org/docs/editor/" target="_blank">Dart Editor Download Page</a>.</p> <p>Once you have downloaded the .zip file, simply unzip the files to a location on your local machine. The pub tool ships with the Dart SDK and you can find it at the following location: <strong>dart-sdk\util\pub</strong></p> <p><strong>Configure Windows Environment Variables</strong></p> <p>You’ll need to configure a couple of Windows environment variables which make it easier to work with the SDK tools. First, add an environment called DART_SDK and point it at the root SDK folder in your unzipped Dart download. Next, update your Windows System Path variable and add a path which points to the bin folder of the SDK folder:</p> <blockquote> <p><a href="http://lh3.ggpht.com/-b8BD6HRoMpI/UExs2auZ9eI/AAAAAAAAGm4/g_1pq39rGMQ/s1600-h/image%25255B3%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-JDiawnTHfJ4/UExs4el7XWI/AAAAAAAAGnA/E_sc1-JpQ3o/image_thumb%25255B1%25255D.png?imgmax=800" width="376" height="444"></a></p></blockquote> <p>The reason for pointing the Path variable at the bin folder is because that’s where the main tools that you will need to use are located. The DART_SDK variable however needs to point at the root SDK folder because it is used to access SDK resources other than just the SDK bin tools alone – e.g. Libraries, Packages, and other Utilities.</p> <p><strong>Test that you have configured your environment variables correctly</strong> by opening a Windows Command Prompt and type ‘<strong>pub help’ </strong>and you should see Help text for the Pub tool displayed:</p> <blockquote> <p><a href="http://lh4.ggpht.com/-wfJs5emh1lI/UExs59Mc57I/AAAAAAAAGnI/5JTT7E309t0/s1600-h/image%25255B13%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-t9gZpG528Hs/UExs7vISnsI/AAAAAAAAGnQ/TJTqjaVATww/image_thumb%25255B7%25255D.png?imgmax=800" width="521" height="261"></a></p></blockquote> <p><strong>Install Git</strong></p> <p>Many of the packages that you will want to include will require Git to pull them down. Pub itself has support for working with Git via native protocol handlers which can be declared within the pubspec configuration files. To get Git, <a href="http://git-scm.com/" target="_blank">download the latest stable build from the Git website</a>.</p> <p><strong>Test that you have Git correctly</strong> by opening a Windows Command Prompt and type ‘<strong>git –version’ </strong>and you should see the version number for your Git installation displayed:</p> <blockquote> <p><a href="http://lh4.ggpht.com/-TEpY72KtUEQ/UExs9DELr2I/AAAAAAAAGnY/uMmekI8IvxU/s1600-h/image%25255B14%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-hvkPh2vHRvM/UExs-9_0saI/AAAAAAAAGng/-FJ1DWH5MOc/image_thumb%25255B8%25255D.png?imgmax=800" width="433" height="186"></a></p></blockquote> <p><strong>Grab Dartsweeper from Git</strong></p> <p>Now that we have all of our tools installed, it’s simply a matter of using Git commands to fetch the Dartsweeper files and then we’ll use Pub to update all of its dependencies.</p> <p>Open a Windows Command Prompt and change to a directory where you want to work from and type the following commands:</p> <blockquote> <p><font size="2" face="Lucida Console">> mkdir %USERPROFILE%\dart<br>> cd %USERPROFILE%\dart<br>> git clone </font><a title="https://github.com/kevmoo/sweeper.dart.git" href="https://github.com/kevmoo/sweeper.dart.git"><font size="2" face="Lucida Console">https://github.com/kevmoo/sweeper.dart.git</font></a><br><font size="2" face="Lucida Console">> cd sweeper.dart<br>> pub install</font></p></blockquote> <p>This will make a folder under your user profile called Dart and then clone the contents of Dartsweeper repo on GitHub into it. Finally we run the pub install command from within the newly downloaded Dartsweeper folder.</p> <p>Here you can see the result of running those commands in real time:</p> <blockquote> <p><a href="http://lh4.ggpht.com/-R1R2Tn_Hr20/UExtAUmifYI/AAAAAAAAGno/4kPdlThz0Ng/s1600-h/image%25255B19%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-eXhX1cW0k_o/UExtCbGcqWI/AAAAAAAAGnw/ivRyQssaUDo/image_thumb%25255B11%25255D.png?imgmax=800" width="661" height="486"></a></p></blockquote> <p><strong>Running Dartsweeper</strong></p> <p>Now that we have Dartsweeper installed, it’s time to open it up in the Dart Editor and run it. Open Dart Editor and open the sweeper.dart folder that we just grabbed from GitHub.</p> <blockquote> <p><a href="http://lh5.ggpht.com/-oWoWWFucArA/UExtEChctVI/AAAAAAAAGn4/EjdpheQkfPU/s1600-h/image%25255B23%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-ZnQrdrRnJtE/UExtFnhlt7I/AAAAAAAAGoA/0vPkc8Ywb2s/image_thumb%25255B13%25255D.png?imgmax=800" width="535" height="327"></a></p></blockquote> <p>When you first open the application in Dart Editor, you will notice some red crosses against folders which indicate compiler errors:</p> <blockquote> <p><a href="http://lh3.ggpht.com/-aiXMIQs_0zA/UExtG3N7AJI/AAAAAAAAGoI/JykDvL4d0fA/s1600-h/image%25255B27%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-k_TcOrGZzAs/UExtIjefhkI/AAAAAAAAGoQ/Khn5U3LbZrk/image_thumb%25255B15%25255D.png?imgmax=800" width="342" height="322"></a></p></blockquote> <p>The reason for this is that, currently in the Dart Editor, we need set the location for the packages on a per application basis. In this case, we simply need to open Tools|Preferences and change the location that we want the compiler to look in for packages for this application.</p> <blockquote> <p><a href="http://lh4.ggpht.com/-lBD6n4GNlQ0/UExtKQVazoI/AAAAAAAAGoY/MPsEdn2Xt2o/s1600-h/image%25255B31%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-HHSdvzOqraM/UExtMSMTJAI/AAAAAAAAGog/pR36ZbqjV5c/image_thumb%25255B17%25255D.png?imgmax=800" width="476" height="246"></a></p></blockquote> <p>After doing that, you can right-click on the <strong>test</strong> folder and exclude it by choosing <strong>Don’t Analyze</strong> to remove it from the compilation analysis process. That should remove the remaining compiler error warning.</p> <p>Now press Ctrl+R (or hit the Run button) to run the application in the Dartium build of Chrome:</p> <blockquote> <p><a href="http://lh5.ggpht.com/-xOl_Zx1LZCI/UExtOKTAIjI/AAAAAAAAGoo/a-NpcNjC5Zc/s1600-h/image%25255B36%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-9WB_iO1lMJw/UExtPyj31JI/AAAAAAAAGow/tYPzKqzvHNo/image_thumb%25255B20%25255D.png?imgmax=800" width="494" height="594"></a></p></blockquote> Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com4tag:blogger.com,1999:blog-4417089948647936949.post-23848671282780717322012-09-07T16:58:00.001-07:002012-09-07T16:58:11.139-07:00BingItOn<p><a href="http://lh6.ggpht.com/-ev3K0K_Ptrs/UEqJmsU1UdI/AAAAAAAAGj0/KKekC0R3wns/s1600-h/image%25255B3%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 17px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" align="left" src="http://lh5.ggpht.com/-1BSdBwEogms/UEqJotX8vwI/AAAAAAAAGj8/VjJm_XGBgMQ/image_thumb%25255B1%25255D.png?imgmax=800" width="325" height="211"></a><a href="http://www.bingiton.com" target="_blank">BingItOn.com</a> is another wasteful exercise by the Microsoft Bing team which attempts to con users into believing that its results are superior to those of Google’s Search product. </p> <p>I remember travelling to Seattle 5 or 6 years ago and seeing this tool used internally at Redmond - now finally it appears that the mighty Redmond marketing machine has unleashed it upon the public at large.</p> <p>The premise of this tool is that you run a search and two sets of results are returned - one from Bing and one from Google. You are then asked to make a choice about which set of results is more useful.</p> <p>There are two problems here. First, Microsoft simply needs to turn its back on some of these old Ballmer fights and look instead to the future. Get back to innovating and delighting customers and walk away from this sort of stuff. They really don't need to fight meaningless fights just because Ballmer made some dumb promise all those years ago.</p> <p>Second, how relevant is it to make a choice when you strip away the added value pieces that Google delivers to me in a normal search? Things such as personalized search results and added context through their knowledge graph enhancements. For example, when I run a search using the Microsoft BingItOn tool for AFL Football legend “Buddy Franklin”, I receive two walls of results:</p> <p><a href="http://lh3.ggpht.com/-l2BiW2sdfBc/UEqJr6cxNxI/AAAAAAAAGkE/8PDqIx9ANRE/s1600-h/image%25255B8%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-hfb-jx6unkU/UEqJubu005I/AAAAAAAAGkM/X2wh9Jh7QTU/image_thumb%25255B4%25255D.png?imgmax=800" width="545" height="344"></a></p> <p>Picking through them both to find a winner is tough and quite subjective. But let’s see how the results <em>actually</em> appear when I do the search on the actual site’s:</p> <p>First I use Google and we can see that the results which are presented are far more useful than what is simply presented in the BingItOn tool. I’m given personalized results which are more engaging, presented better, and which have added context and knowledge about the topic.</p> <p><a href="http://lh3.ggpht.com/-d4XExO7sMI4/UEqJw3A1irI/AAAAAAAAGkU/Q1XUXK6c9RI/s1600-h/image%25255B13%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-_zcLtFYQ070/UEqJyiBPoZI/AAAAAAAAGkc/j0TUrpX9Hv4/image_thumb%25255B7%25255D.png?imgmax=800" width="756" height="311"></a></p> <p>Contrast that with a search on Bing.com and we can see Bing doesn’t actually make it much easier than the BingItOn tool:</p> <p><a href="http://lh3.ggpht.com/-xxNp-l_Vj1E/UEqJ0u-eWeI/AAAAAAAAGkk/CC5685IdK6k/s1600-h/image%25255B17%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-4aJ4bu9eatE/UEqJ2qGbf5I/AAAAAAAAGks/jLxo9o0qg4k/image_thumb%25255B9%25255D.png?imgmax=800" width="583" height="330"></a></p> <p>Less engaging, less relevant, and potentially a lot more work to do on my behalf to get a result that I might be interested in.</p> <p>Here I repeat the result by searching for the term “Adelaide Crows Players” and let’s look at the results:</p> <p>Google presents me with a scrollable list of the current players with their playing positions at the head of the SERP.</p> <p><a href="http://lh6.ggpht.com/-gaElb6ZugLc/UEqJ5X6WtcI/AAAAAAAAGk0/X_y8_YC9SUo/s1600-h/image%25255B21%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-yo8rwVFYd0o/UEqJ7VsndeI/AAAAAAAAGk8/1AgPJrpdVn4/image_thumb%25255B11%25255D.png?imgmax=800" width="582" height="269"></a></p> <p>With Bing on the other hand, it appears that the first half dozen results might even be advertisements:</p> <p><a href="http://lh5.ggpht.com/-iPTbcBsXE4E/UEqJ9PWCstI/AAAAAAAAGlE/ASODYQAVqR4/s1600-h/image%25255B25%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-vJhgxm-r6U4/UEqJ-2yID7I/AAAAAAAAGlM/wJyb0l2ItyY/image_thumb%25255B13%25255D.png?imgmax=800" width="592" height="403"></a></p> <p>Yet run it in the BingItOn tool and the results are far less clear:</p> <p><a href="http://lh5.ggpht.com/-Y9JCkfjgxrE/UEqKBT_FPBI/AAAAAAAAGlU/_EdkMYsOn9g/s1600-h/image%25255B29%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-thyLympNCbQ/UEqKD6_ppuI/AAAAAAAAGlc/sDcrbw3z79Y/image_thumb%25255B15%25255D.png?imgmax=800" width="603" height="403"></a></p> <p>So the message that I take away from the BingItOn tool is this... if we strip away all the stuff that makes Google search great and dumb it down to a certain level, which search engine do you prefer. It's not even a valid question to ask! </p> Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com0tag:blogger.com,1999:blog-4417089948647936949.post-43992737436619827762012-08-21T17:51:00.002-07:002012-08-21T17:56:09.257-07:00Are our words really wasted? <br />
<a href="http://www.hanselman.com/blog/YourWordsAreWasted.aspx" target="_blank">Scott Hanselman told us that our words are wasted</a>, and then <a href="https://plus.google.com/108573066018819777334/posts/5x7YKtksadL" target="_blank">went on to ask how his post was controversial</a>? Well...<br />
<br />
<ul>
<li>He said that my words are wasted?</li>
<li>He told me that I'm not blogging enough?</li>
<li>He implied that Google and Facebook will SURELY fail?</li>
</ul>
So, perhaps there is a bit of controversy there :)<br />
<br />
It's not like I don't agree with Scott on a number of points. <a href="http://markitup.com/" target="_blank">I've hosted my own blog</a> in the past and even written my own blogging platform. In terms of portability, <a href="http://en.wikipedia.org/wiki/BlogML" target="_blank">I created BlogML</a> to help allow people to move from service to service. And regardless, controversy is not such a bad thing. I just don't think that the article was his best piece of writing (I hold him to a much higher standard than I hold myself :) One point I have trouble with in the post is the list of things that we apparently find ourselves asking over and over again:<br />
<br />
<table border="1">
<tbody>
<tr><th align="left">Attribute</th><th>G+</th><th>Facebook</th><th>Live</th><th>Other?</th></tr>
<tr><td>Is a free or cheap social network for the people?</td><td>?</td><td>?</td><td>?</td><td>?</td></tr>
<tr><td>Let's me control my content?</td><td>?</td><td>?</td><td>?</td><td>?</td></tr>
<tr><td>Allows export of everything ?</td><td>?</td><td>?</td><td>?</td><td>?</td></tr>
<tr><td>Allows me to own what I type?</td><td>?</td><td>?</td><td>?</td><td>?</td></tr>
<tr><td>Has an open API for my content?</td><td>?</td><td>?</td><td>?</td><td>?</td></tr>
<tr><td>Allows search posts over a month old?</td><td>?</td><td>?</td><td>?</td><td>?</td></tr>
<tr><td>Limits available usernames?</td><td>?</td><td>?</td><td>?</td><td>?</td></tr>
<tr><td>Allows me to be 'verified'?</td><td>?</td><td>?</td><td>?</td><td>?</td></tr>
</tbody></table>
<br />
Is that the full list of 'product attributes' or is it constantly changing. And how do you find a single product which meets those needs while also staying current with constantly changing expanding list of product features that users need. And what is the cost of meeting those needs with any single boxed product?<br />
<br />
The current state of software services is such a moving target and I'm continually rethinking how I use my journal to link it with and help my daily activities. That includes things such as being able to link activities by location, having content delivered to whatever device I'm on, sharing stuff easily through a variety of ways, embedding rich content such as maps and documents through to having a variety of different privacy and sharing options.<br />
<br />
I feel like I'm trying stuff out to help improve my life's process flow.<br />
<br />
So I tend to focus on the benefits of that I get from "renting" an existing service and not so much on the fact that some greedy NASDAQ listed company is making money from my effort. Those benefits include:<br />
<br />
<ul>
<li>I get a fancier "apartment" :)</li>
<li>There are often added perks over the choices I have otherwise</li>
<li>I get to share costs/overheads with multiple tenants</li>
<li>It is generally cheaper and easier to relocate</li>
<li>Boring maintenance work is often removed</li>
<li>For me, I believe that there are reduced risks</li>
</ul>
<br />
So, as with most things in life, there are choices and trade-offs.Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com0tag:blogger.com,1999:blog-4417089948647936949.post-65475944760111389362012-08-14T19:02:00.001-07:002012-08-14T19:17:14.447-07:00Constructors in DartRecently I've started using the <a href="http://www.dartlang.org/" target="_blank">Dart</a> language and tools to maintain my interest in programming. Coming from a .NET and JavaScript background, many of the features of the language are familiar to me but there are also some syntactical aspects that I like and which are particular to Dart.<br />
<br />
One of the areas within the language that I'm enjoying is the <a href="http://www.dartlang.org/docs/language-tour/#constructors" target="_blank">constructor syntax</a>.<br />
<br />
<b>Simple and default constructors</b><br />
Every class will have a default constructor which is provided in case you don't specify your own. To specify your own constructor, simply create a method with the same name as the class.<br />
<br />
<pre>class WordContainer
{
List<string> _wordList;
WordContainer(List<string> words)
{
_wordList = words;
}
void Print()
{
_wordList.forEach((word) => print(word));
}
}
</string></string></pre>
<br />
In the above example, as you might expect, we have a simple constructor which allows us to construct new instances the class by passing in a list of words:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-cyiJURUqQQM/UCr_O0KOWjI/AAAAAAAAFhg/goEGJDB16ZY/s1600/Capture.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-cyiJURUqQQM/UCr_O0KOWjI/AAAAAAAAFhg/goEGJDB16ZY/s1600/Capture.PNG" /></a></div>
<br />
<b><br /></b>
<b>Assignment of constructor arguments to member variables</b><br />
A handy shortcut exists in the Dart language for assigning constructor arguments to member variables which can save keystrokes and time.<br />
<br />
<pre>class Point
{
num x, y;
Point(this.x, this.y);
}</pre>
<br />
<b>Named constructors and default parameters</b><br />
Another nice feature of Dart is the named constructor syntax which is designed to make it easier to identify the purpose for different constructor overloads. In the following example I have created a separate, named constructor which takes a single word and provides an optional parameter to specify the number of times to add the single word to the word list. To differentiate the purpose of this constructor method, I will give it a unique name.<br />
<br />
<pre>class WordContainer
{
List<string> _wordList;
<string> WordContainer.fromSingleWord(String word, [num times = 10])
{
_wordList = [];
for(var i = 0; i < times; i++)
{
_wordList.add(word);
}
}</string></string></pre>
<pre><string><string>}</string></string></pre>
<br />
When calling the overloaded constructor method, it now becomes more readily apparent as to what is happening from where the code is called:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-oHrbYsWLYt4/UCsDIdWj6SI/AAAAAAAAFhw/_vfMXvjq4mk/s1600/Capture.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-oHrbYsWLYt4/UCsDIdWj6SI/AAAAAAAAFhw/_vfMXvjq4mk/s1600/Capture.PNG" /></a></div>
Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com0tag:blogger.com,1999:blog-4417089948647936949.post-55868690604374704922012-03-17T15:05:00.001-07:002012-03-17T15:34:50.724-07:00Serialization ordering causes problems when using DataContactSerializer in WCF services<p>Have you ever created a WCF service and, when you’ve called it from a consuming application, some values appeared to come through just fine while other values were ignored? Perhaps you’ve been stung by the default ordering rules that are applied when using the DataContractSerializer (the default choice in WCF). <p>First up, if you are not aware of how serialization in WCF works, here is a link to a good Msdn article which compares some of the differences between the various serialization techniques that are on offer in WCF: <a href="http://msdn.microsoft.com/en-us/magazine/cc163569.aspx">http://msdn.microsoft.com/en-us/magazine/cc163569.aspx</a> <p>A big issue is the fact that the DataContractSerializer works on the order in which it expects to receive fields in the incoming messages. This can cause <a href="http://theburningmonk.com/2010/08/wcf-be-ware-of-the-field-ordering-when-using-datacontractserializer/">some very unexpected behaviour</a>. <p>To describe the issue, we will first create a data contract to model an incoming message. The contract that we are modelling here contains 4 properties, 3 of which are Integers, and the other is an Enum value (not that that's significant). <p><strong>The Data Contract<br></strong><a href="http://lh5.ggpht.com/-X3CzIXmr8f4/T2UKTl6JMVI/AAAAAAAACtk/WGahjjwJ-KU/s1600-h/clip_image001%25255B4%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="clip_image001" border="0" alt="clip_image001" src="http://lh6.ggpht.com/-qWOUp6S9xM0/T2UKVLtMsPI/AAAAAAAACts/zi2azcRO-C8/clip_image001_thumb%25255B1%25255D.png?imgmax=800" width="414" height="327"></a> <p>Next we create a simple service to receive our message and to do some processing over it. In this case we will receive the message and then simply write out the values that have been set by the deserialization process. <p><strong>A Simple Service</strong><a href="http://lh6.ggpht.com/-Fk4gPOYawqM/T2UKWSLbUWI/AAAAAAAACt0/_ydtJ1JN3Tc/s1600-h/clip_image002%25255B4%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://lh6.ggpht.com/-vq2263sgB3Q/T2UKYM_o0FI/AAAAAAAACt8/ukqWHvZEC1M/clip_image002_thumb%25255B1%25255D.png?imgmax=800" width="580" height="199"></a> <p>When using the DataContractSerializer to handle serialization in your web service, it is important to understand the <a href="http://msdn.microsoft.com/en-us/library/ms729813%28v=vs.85%29.aspx">default ordering rules</a> that it uses and what that means in terms of the order in which elements are expected to appear. <p>Given our fairly simple type above, the main rule that we need to be aware of is that the properties are expected to be ordered alphabetically. If we obey that rule, then the results of our message processing work out just fine. <p><strong>Default Ordering – OK<br></strong><a href="http://lh3.ggpht.com/-hVoTpsbbb44/T2UKZhPPOII/AAAAAAAACuE/8Ljal0CT1C4/s1600-h/clip_image003%25255B4%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="clip_image003" border="0" alt="clip_image003" src="http://lh4.ggpht.com/-Q2evP1k4OQI/T2UKbIX-ygI/AAAAAAAACuM/Gs0YToDaocQ/clip_image003_thumb%25255B1%25255D.png?imgmax=800" width="697" height="192"></a> <p>However look at what happens if we change the order of the elements in our request message. <p><strong>Changed Ordering - Error</strong><a href="http://lh4.ggpht.com/-SUwHzdfxl_Y/T2UKcuTI3pI/AAAAAAAACuU/qiQtkZ0ftgM/s1600-h/clip_image004%25255B4%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="clip_image004" border="0" alt="clip_image004" src="http://lh4.ggpht.com/-OeRJDHsDjWY/T2UKeOT2kgI/AAAAAAAACuc/op-F5lHnuac/clip_image004_thumb%25255B1%25255D.png?imgmax=800" width="731" height="205"></a> <p>In this case, the DataContractSerializer has skipped the elements that were not found in the correct order and then moved on to processing the next element. This can have some pretty disastrous consequences because, not only is the data skipped for the elements that were out of order, but the corresponding properties now have incorrect values set for them! <p><strong>Use the XmlSerializer</strong> <p>The default ordering issue is probably not a big deal if you are in a pure .NET environment and you have WCF at both ends of the communication. But how often does that happen these days? In our environment at work it is typical to have all types of clients that want to connect to our service - Classic ASP, Client Side Web Pages, and External Vendor applications. <p>In each of these scenarios, it is likely that the consumer of the service will craft the messages in such a manner that it is difficult to enforce and verify that the correct order is always obeyed. And the resulting bugs may not get picked up unless you have a very sophisticated and well disciplined UAT process! <p>A solution to this problem is to configure your service to use the XmlSerializer approach which has been around since the early days of .NET. This is achieved by simply annotating your service contract with an attribute to tell WCF that you want to override the default serialization technique. <p>Overriding the default serialization technique <p><a href="http://lh4.ggpht.com/-Og8WPELGW6o/T2UKfPwqAYI/AAAAAAAACuk/8VrHUdRf3b8/s1600-h/clip_image005%25255B4%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="clip_image005" border="0" alt="clip_image005" src="http://lh6.ggpht.com/-yTNOzTUAFxI/T2UKguGSFFI/AAAAAAAACus/bBWmSiwMcoU/clip_image005_thumb%25255B1%25255D.png?imgmax=800" width="550" height="161"></a> <p>Once we do this, elements can appear in any order because of how the XmlSerializer uses names to do element mapping. <p><a href="http://lh6.ggpht.com/-pQ0jP4qLVok/T2UKih4mrVI/AAAAAAAACu0/cTS9PnjyVws/s1600-h/clip_image006%25255B5%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="clip_image006" border="0" alt="clip_image006" src="http://lh6.ggpht.com/-Ou39V3Fm0W4/T2UKjwUNZlI/AAAAAAAACu8/Uy3HJY7_xHA/clip_image006_thumb%25255B2%25255D.png?imgmax=800" width="718" height="209"></a> <p>The downsides of using the XmlSerializer are: <ul> <li>Using the XmlSerializer incurs additional performance costs because it generates strongly typed assemblies for the classes that are subject to the serialization process. However this can be avoided by pre-generating the assemblies that you need using the <a href="http://msdn.microsoft.com/en-us/library/bk3w6240%28v=vs.80%29.aspx">SGen tool</a>. <li>DataContactSerializer has some additional attributes (Order and IsRequired) that can help with certain versioning scenarios.</li></ul> <p>The benefits or using XmlSerializer are: <ul> <li>Get around the ordering issues which results in less fragility in consuming applications. <li>Ability to easily work with Xml attributes as part of the serialization mapping on .NET types can aid interoperability and makes it easier to adopt a “contract first” approach to service implementation</li></ul> Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com0tag:blogger.com,1999:blog-4417089948647936949.post-4342749172952031152012-03-01T13:28:00.001-08:002012-03-01T13:28:34.481-08:00Article Stack 2nd March 2012<p>Capturing AUDIO & VIDEO in HTML5</p> <p><a href="http://www.html5rocks.com/en/tutorials/getusermedia/intro/">http://www.html5rocks.com/en/tutorials/getusermedia/intro/</a> <p>A good introduction to getUserMedia in modern browsers which allows you to capture video and audio and to optionally stream their captured output to HTML5 audio and video elements. This is available in Chrome by enabling MediaStream in <a href="chrome://flags/">chrome://flags/</a> <h2>Nobody Understands REST or HTTP</h2> <p><a href="http://blog.steveklabnik.com/posts/2011-07-03-nobody-understands-rest-or-http">http://blog.steveklabnik.com/posts/2011-07-03-nobody-understands-rest-or-http</a> <p>Another article which explains REST/HTTP stuff. There's some stuff in here about versioning using an Accepts HTTP Header value. There's a lot of good stuff in here and I'd love to have the time to prototype some of these concepts using ASP.NET Web API as a sample technology. <p> <h2>ASP.NET Web API Articles</h2> <p>Speaking of Web API, there's heaps of good content about it coming out now on a daily basis in blogs. Here's links to some good articles that I've read recently about Web API: <ul> <li>Introductory walk through of an end to end sample by Scott Hanselman - [<a href="http://www.hanselman.com/blog/OneASPNETMakingJSONWebAPIsWithASPNETMVC4BetaAndASPNETWebAPI.aspx">link</a>]. Note: I loved the use of MvcScaffolding and Nuget here. I hadn't seen that before but it looks pretty useful for prototyping stuff quickly, particularly when you are going against a database.</li></ul> <ul> <li>A two part series of articles which explains how Content Negotiation works in Web API [<a href="http://blogs.msdn.com/b/kiranchalla/archive/2012/02/25/content-negotiation-in-asp-net-mvc4-web-api-beta-part-1.aspx">part 1</a>], [<a href="http://blogs.msdn.com/b/kiranchalla/archive/2012/02/27/content-negotiation-in-asp-net-mvc4-web-api-beta-part-2.aspx">part 2</a>] <li>Controller names for Web API controllers, the rules that they conform to, and the extensibility points for customizing the selection of controllers [<a href="http://blogs.msdn.com/b/carlosfigueira/archive/2012/02/29/supporting-different-controller-names-in-asp-net-web-apis.aspx">link</a>]</li></ul> <p> </p> <h2>Scott Hanselman about The New Visual Studio Look and Feel</h2> <p><a href="http://www.hanselman.com/blog/ChangeConsideredHarmfulTheNewVisualStudioLookAndFeel.aspx">http://www.hanselman.com/blog/ChangeConsideredHarmfulTheNewVisualStudioLookAndFeel.aspx</a> <p>Version 11 of Visual Studio is out and it has had a significant update to its look and feel. I think Scott nails it here and I believe that many people's first impression will be to say that they don't like it - change often hurts. In looking at the screenshots in Scott's post I actually quite like the new look. Scott also has some great tips for getting a better theme and for streamlining the look by reducing buttons and toolbars. <h2> </h2> <h2>WinJS Observables</h2> <p><a href="http://stephenwalther.com/blog/archive/2012/02/25/windows-web-applications-understanding-observables.aspx">http://stephenwalther.com/blog/archive/2012/02/25/windows-web-applications-understanding-observables.aspx</a> <p>Finally, there's also been a new release of Windows 8 this week so it's timely to get an article from Stephen Walther about how Observables work in the WinJS Binding library.</p> Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com0tag:blogger.com,1999:blog-4417089948647936949.post-77924124710891843632012-01-29T23:39:00.001-08:002012-01-29T23:39:25.508-08:00My experience in updating to Bootstrap V2<p>Over the weekend I updated <a href="http://skillslibrary.net/" target="_blank">SkillsLibrary</a> to use the newer version of <a href="http://markdotto.com/bs2/docs/index.html" target="_blank">Bootstrap from Twitter</a>. You can see the new version which is running on AppHarbour (which I’m using as my UAT environment) <a href="http://skillslibrary.apphb.com/">http://skillslibrary.apphb.com/</a> and compare it to the older version running in production: <a href="http://skillslibrary.net/">http://skillslibrary.net/</a>. <p>Bootstrap V2 is going to be released on 31st Jan. 2012 and you can read about the changes from the official source <a href="http://markdotto.com/bs2/docs/upgrading.html" target="_blank">here</a>. <p>In this article I’ll go through some of my own personal experience in terms of upgrading. <p><strong>Configurable Download</strong> <p>From the outset, the Bootstrap team have improved the deployment of this resource by allowing you to <a href="http://markdotto.com/bs2/docs/download.html" target="_blank">configure your download</a> and receive it as two single CSS and JS files. <p>The first thing to notice as an unauthenticated user is that I’ve removed the “Hero Unit” from the home page and replaced it with smaller title text and a carousel of images. Part of the reason for that change was that, the previous version of Bootstrap had a Hero Unit CSS class which has not been carried forward: <blockquote> <p><a href="http://lh5.ggpht.com/-ycjJ6hiJx2Q/TyZIyxi3ECI/AAAAAAAACg0/gnqhfI21OAs/s1600-h/image3.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-FEzUPvOXAQY/TyZI0Ory5iI/AAAAAAAACg8/90dfGZo8jwU/image_thumb1.png?imgmax=800" width="312" height="154"></a></p></blockquote> <p><strong>Home Page Carousel</strong></p> <p>Another reason was that I had always planned to implement a carousel of images and now that it’s a core component in Bootstrap, it seemed like a good time to make that change:</p> <blockquote> <p><a href="http://lh6.ggpht.com/-WyApgOl5Lh4/TyZI25BAVKI/AAAAAAAAChE/boH6C1gUMMU/s1600-h/image8.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-_jDbYsIjLEs/TyZI4tIC3xI/AAAAAAAAChM/kX8yqyWzCfE/image_thumb4.png?imgmax=800" width="500" height="293"></a></p></blockquote> <p>Most of the other changes are not visible until you log in although there were some other smaller tweaks that I had to make across the site to accommodate the new base styles.</p> <p><strong>Re-styled Forms</strong> </p> <p>The most significant site-wide change involved updating the layout of forms and their controls to match the new V2 component styling. Forms in V1 were really nice but the semantics have been significantly improved in V2. The following image highlights some of the differences that I made to upgrade the Registration form:</p> <blockquote> <p><a href="http://lh4.ggpht.com/-T0700e7LIqY/TyZI6ZNoCYI/AAAAAAAAChU/BKp_AVr1eQ0/s1600-h/image13.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-QoEXJ5Y-HPQ/TyZI8Z9CoMI/AAAAAAAAChc/rQhPMArA3dc/image_thumb7.png?imgmax=800" width="814" height="305"></a></p></blockquote> <p>You can see that the rows in the form have had their class name changed from <em>clearfix</em> to the more semantically sensible name of <em>control-group</em>. Likewise, the area at the bottom of the form has changed from <em>actions</em> to <em>form-actions</em> and labels now have a class name to distinguish them. There were other changes as well, but these were the ones that I had to make to all of my forms.</p> <p><strong>Navigation</strong></p> <p>When you log in to the application, there are lots of changes that become apparent, starting with the <strong>Global Navbar</strong>. The following image compares the previous version with the current one:</p> <blockquote> <p><a href="http://lh6.ggpht.com/-k4HdkT_LHDE/TyZI9SoSDVI/AAAAAAAAChk/rFZfT6a57bE/s1600-h/image18.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-rsx7XzeNnGc/TyZJA7ls9oI/AAAAAAAAChs/OPx1LV2ctmM/image_thumb10.png?imgmax=800" width="776" height="312"></a></p></blockquote> <p>From a purely visual perspective, you can see that the <strong>Search box</strong> has altered to display more rounded corners and that the <strong>dropdown menu’s</strong> have received a significant upgrade to their appearance. But the HTML semantics have also changed but have remained very simple. </p> <p>One thing that I have not yet implemented as yet, but which I will definitely be doing is to make use of the <a href="http://markdotto.com/bs2/docs/base-css.html#icons" target="_blank">sprite images</a> that have been bundled with Bootstrap to make my menu’s and buttons look much snazzier! Using those sprite images makes it easy to achieve results such as this with the ‘out of the box’ experience:</p> <blockquote> <p><a href="http://lh3.ggpht.com/-ofoVf4iecfA/TyZJC8Mt4II/AAAAAAAACh0/WUmkYyh05aI/s1600-h/image22.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-FDXNGQNGAf8/TyZJEEqEGsI/AAAAAAAACh8/TeUOEwDT2Rw/image_thumb12.png?imgmax=800" width="412" height="150"></a></p></blockquote> <p><strong>Split Button Dropdowns</strong></p> <p>A key improvement for SkillsLibrary was the introduction of the new <a href="http://markdotto.com/bs2/docs/components.html#buttonDropdowns" target="_blank">Button Dropdowns</a> which have been introduced. Prior to these I had hacked together a rough user experience for performing additional actions against Activities by using the V1 dropdowns but now they have bundled them to create a beautiful Split Button Dropdown experience:</p> <blockquote> <p><a href="http://lh4.ggpht.com/-y2ytOwD6Pso/TyZJE68SG5I/AAAAAAAACiE/GJEmnTChGko/s1600-h/image26.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-YPv9BesqsPc/TyZJF9P_IEI/AAAAAAAACiM/rZNGkwsnWi0/image_thumb14.png?imgmax=800" width="260" height="414"></a></p></blockquote> <p>It’s lots of little things such as this which have really tightened up the user interface a lot.</p> <p><strong>Dialogs</strong></p> <p>Probably the other major UX feature that I implemented was the <a href="http://markdotto.com/bs2/docs/javascript.html#modals" target="_blank">Modal Dialogs</a>.</p> <blockquote> <p><a href="http://lh6.ggpht.com/-elmbgrargEQ/TyZJHauibuI/AAAAAAAACiU/2ai2bGwTYsE/s1600-h/image30.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-RExYwpeq5i8/TyZJIrxdsTI/AAAAAAAACic/cqxUjUIGe_M/image_thumb16.png?imgmax=800" width="601" height="319"></a></p></blockquote> <p>These existed in the V1 version of Bootstrap but have again been improved to include enhancements such as dark background when the modal is displayed and cleaner styling and semantic HTML options for closing the dialogs.</p> <p><strong>Other</strong></p> <p>There were several other smaller changes to styles and HTML syntax. Some of the component class names changed and other components have had improved UI. One of these was the popover controls which now make it easier to display a prominent title and description text as a single component.</p> <blockquote> <p><a href="http://lh6.ggpht.com/-4sjLXNcp2Hw/TyZJJh6JJeI/AAAAAAAACik/sAv6WbZg0kE/s1600-h/image34.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-jmwZwMvSYoo/TyZJKhtYILI/AAAAAAAACis/YhM4WJt8LdQ/image_thumb18.png?imgmax=800" width="447" height="171"></a></p></blockquote> <p><strong>Conclusion</strong></p> <p>SkillsLibrary is a moderately complex web application with about 30-40 pages. All up, it took me about 4 hours to upgrade from V1 to V2 of Bootstrap. Having done so I feel very satisfied that the UX improvements that I’ve discussed in this article have made it worthwhile but I also feel happy that implementing further components (such as the Typeahead and Collapse) controls will allow me to reduce my overall 3rd party JS dependencies.</p> Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com2tag:blogger.com,1999:blog-4417089948647936949.post-66170465440639004042012-01-16T19:27:00.000-08:002012-01-16T19:31:31.067-08:00The A,B,C,D's of an enterprise SOAThis is a big year for us at work as we mobilize our resources to bring about some really sweeping changes in our technology platforms. Coupled with the major technology will come a change in the way we build software. <br />
<br />
One of the major changes for us is to change the way that we manage inter-application communications. We are moving towards a more formalized version of SOA which involves a greater number of web services which interoperate via distinct messages over HTTP. As we retire old systems and replace them with newer ones, we will undoubtedly take the time to modernize and move more of our communications into the newer way we do things.<br />
<br />
All change uncovers challenges that can cause pain and will likely see us stumble. This, is an inevitable side-effect of changing, of moving from one place to another. It is also a great opportunity to learn new things and as such it presents a good vehicle for personal development and growth.<br />
<br />
To simplify the job of capturing and communicating the knowledge that we gain from our excursion down the enterprise SOA path, I have identified 4 key subject headings that act as boundaries for different knowledge areas. They are described as the <b>ABCDs of SOA</b> knowledge base.<br />
<br />
<b>A is for Accessing (Authentication and Authorization)</b><br />
Knowledge about:<br />
<ul>
<li>Standards based protocols for managing access and trust (WS-*). </li>
<li>How to use our technology to implement those standards (.NET, WCF, Https).</li>
</ul>
<b>B is for Building</b><br />
Knowledge about:<br />
<ul>
<li>What technology to choose when we are dealing with services (e.g. WCF Web API, ADO.NET Data Services, WCF, etc)</li>
<li>How the respective technologies work</li>
<li>Designing RESTful architectures</li>
</ul>
<b>C is for Consuming</b><br />
Knowledge about:<br />
<ul>
<li>Browser security policies for accessing remote origins</li>
<li>Libraries for making AJAX calls</li>
<li>Working with JSON and XML in the consumer</li>
<li>Consuming HTTPS with untrusted certificates</li>
<li>Composing SOAP messages from the consumer</li>
<li>Composing oData formatted queries from the consumer</li>
</ul>
<b>D is for Deploying</b><br />
<ul>
<li>Configuring SSL</li>
<li>Designing a homogeneous environment for hosting application services</li>
<li>Configuring application endpoints and security accounts</li>
</ul>
<br />
It's the sum of all this (and more) knowledge that goes into having a successful services-based application environment. Internalizing the knowledge gained and feeding that into process and culture change will be a real but hopefully rewarding challenge.Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com0tag:blogger.com,1999:blog-4417089948647936949.post-44957373439464079152012-01-03T14:14:00.000-08:002012-01-03T14:14:07.859-08:00Decomposition - As as human activityThe other night I watched a great documentary on ABC TV the other night called Slumming It, hosted by Kevin McCloud. You can watch Part 1 of that show at the following link:<br />
<blockquote class="tr_bq">
<a href="http://www.youtube.com/watch?v=VW35myugiMA" target="_blank">YouTube - Slumming It Part 1</a></blockquote>
The documentary was shot in Dharavi (India's largest slum) which has been built on top of a dump. The slum was said to be home to over 1 million people. The footage showed scenes which were, to a first-worlder... pretty horrific!<br />
<br />
In one scene, people washed their clothes in water into which fed an open sewer. Another scene showed a new load of raw garbage being unloaded into the slum and then you saw loads of slum dwellers climb over the garbage looking for anything of value.<br />
<br />
Yet amid all of this, the people looked happy and, amazingly, the clothes they wore were immaculate.<br />
<br />
While watching the show I couldn't help but ask myself whether this is where we have come from, where are headed, or, is it where we are now? These people live amid sewers and scavenge through rubbish to survive and yet they just think of it as life. How hard it must be to evaluate the quality of your existence when it is all you know?<br />
<br />
I also thought of the decomposition - of breaking things down and extracting anything of value from them - as being analogous with the human activity. In a shrinking economy, could it be that this could be a more valued skill in developed economies too? The ability to pour over quantities of products and decompose them into their constituent parts to find valuable elements?<br />
<br />
In the past, we have been a very wasteful society. Filling our houses and sheds with old, unused PCs, TVs, clothes, everything. In a more scarce future, could it be that decomposition and recycling the old into new things of value could be a more vital human activity? <br />
<br />
Is this what Prince Charles meant <a href="http://www.dnaindia.com/india/report_dharavi-is-a-model-for-uk-prince-charles_1449993" target="_blank">when he referred to Dharavi as a model for sustainability</a> and as a model for "cities of the future"?<br />
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com2tag:blogger.com,1999:blog-4417089948647936949.post-27484927323352486732012-01-02T11:46:00.001-08:002012-01-02T11:46:48.879-08:00Using Javascript to query the Google APIs<p>Tonight I decided to see how easy it would be to query Google+ programmatically using the <a href="https://code.google.com/apis/explorer/" target="_blank">Google APIs</a>. All up, it took me about 20 minutes from beginning to end to get the following screenshot running in a browser. </p> <blockquote> <p><a href="http://lh5.ggpht.com/-pE5r8HfSigw/TwIJYOZSEBI/AAAAAAAACcs/vcUIEX7pKrE/s1600-h/image%25255B5%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-CSZjVEwWmZQ/TwIJZoV4EKI/AAAAAAAACcw/32fEytKiFic/image_thumb%25255B3%25255D.png?imgmax=800" width="436" height="351"></a></p></blockquote> <p>The first thing you need to do is to create an account and get yourself an API Key. You do this through the <a href="https://code.google.com/apis/console" target="_blank">API console</a>. This allows you to select which services you would like to work against and then assigns you a key that you use to access those services. In my case, I just selected the Google+ service but there’s some really useful services that I need to look at in future such as Translate and Url Shortner. Here’s an image of part of that screen:</p> <blockquote> <p><a href="http://lh3.ggpht.com/-gFuyJVFM7W8/TwIJbvF2XUI/AAAAAAAACc8/9T6QwCnZXg0/s1600-h/image%25255B10%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-rwNQhBTWFio/TwIJcyPgnvI/AAAAAAAACdE/zLXWgsxMTy0/image_thumb%25255B6%25255D.png?imgmax=800" width="447" height="218"></a></p></blockquote> <p>Once I set up my access, I headed to the <a href="https://code.google.com/apis/explorer/" target="_blank">API Explorer</a> to get a feel for the API that I would be querying. The API Explorer is an awesome tool which lets you explore each of the APIs and run queries against them to get back results. Here is a screenshot of the Google+ API running inside of the API Explorer:</p> <p><a href="http://lh6.ggpht.com/-rlK3bb34RfE/TwIJezZsW_I/AAAAAAAACdM/XBI8CzFV-UU/s1600-h/image%25255B15%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-HsD07qjzqsA/TwIJhJ1dDpI/AAAAAAAACdU/2fyQBcRNcaU/image_thumb%25255B9%25255D.png?imgmax=800" width="704" height="258"></a></p> <p>Basically, you select the API, and then choose which method you want to execute, you fill in the parameters and then hit Execute to get back the results. Running the activities.list method with my parameters returned some JSON in the results view so that I could see what data would be returned:</p> <blockquote> <p><a href="http://lh5.ggpht.com/-i3H1Uje_sH8/TwIJiNUakoI/AAAAAAAACdc/w-UrXcn2shE/s1600-h/image%25255B19%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-7EsYp1ZHCG4/TwIJj_vIhgI/AAAAAAAACdk/s9-3TaiaJOY/image_thumb%25255B11%25255D.png?imgmax=800" width="507" height="453"></a></p></blockquote> <p>As you can see in the above image, the query returns an items collection with properties for each item returned. For example, in the image above, you can see the title for the first G+ entry is <em>“Nice, easy workflow”</em>, and that the URL for that entry is displayed just below that.</p> <p>Armed with my API Key and some knowledge about the API, next I created a web page and started coding. The following Javascript executes a query against the <strong>activities.list</strong> method of the <strong>Google+ API</strong> for my userId.</p> <p><a href="http://lh5.ggpht.com/-89Ogi-g4f_U/TwIJlJPGa5I/AAAAAAAACds/QVxiyOZiyeo/s1600-h/image%25255B23%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-bHq2BbXbq34/TwIJm7eEiKI/AAAAAAAACd0/lH5KeeFI7pw/image_thumb%25255B13%25255D.png?imgmax=800" width="593" height="489"></a></p> <p>As you can see, the steps are pretty straightforward.</p> <ol> <li>Load the Google API client script and supply a callback to handle the loaded event for the API</li> <li>In the callback, set your API key and load the API you want to use</li> <li>Configure a request and execute it</li></ol> <p>The final method to display is the method that I used to display the list of results on the page called <em>enumerateResults</em> in the image above. That method simply takes the list of results and appends them to a HTML list element using some of the properties that we saw in the API Explorer for that API’s results:</p> <p><a href="http://lh4.ggpht.com/-xWFxG_m8efQ/TwIJnxc-n7I/AAAAAAAACd4/RmUcWgcqqkA/s1600-h/image%25255B27%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-adrjDmloX1E/TwIJpot86VI/AAAAAAAACeE/NlknYEe_SnU/image_thumb%25255B15%25255D.png?imgmax=800" width="564" height="281"></a></p> <p>So that’s it. 20 minutes from beginning to end. Some other useful links that you might find handy if you want to work against the Google API’s are:</p> <ul> <li><a href="https://code.google.com/p/google-api-javascript-client/wiki/Samples" target="_blank">Google API Client Library Wiki</a> – A wiki with examples and explanations for working with the Javascript library (<a href="https://developers.google.com/+/downloads" target="_blank">there are other SDK’s that you can work with</a>).</li> <li><a href="https://code.google.com/apis/explorer" target="_blank">Google API Explorer</a> – Explore Google APIs interactively</li> <li><a href="https://code.google.com/apis/console" target="_blank">Google API Console</a> – Get access to use the APIs</li> <li><a href="https://groups.google.com/forum/#!forum/google-plus-developers" target="_blank">Google Groups</a> – There are groups for each API where you can ask questions and get help</li></ul> Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com0tag:blogger.com,1999:blog-4417089948647936949.post-32410714759814413842011-12-28T23:36:00.001-08:002011-12-29T02:36:56.066-08:00ASP.NET MVC 4 Bundling and Minification - Composing Child ViewsOf <a href="http://www.asp.net/mvc/mvc4" target="_blank">the upcoming ASP.NET MVC 4 features</a>, one that I am really excited to see is the Bundling feature contained within the Microsoft.Web.Optimization assembly in the current Developer Preview release version. You can get a standalone version of this assembly direct from Nuget: <br />
<ul>
<li><a href="http://nuget.org/packages/Microsoft.Web.Optimization">http://nuget.org/packages/Microsoft.Web.Optimization</a></li>
</ul>
In this article I want to discuss some of the basics of Bundling and also to outline some thoughts that I have for organizing scripts and code when composing views in your application.<br />
<h3>
MVC4 Bundling Primer</h3>
The Bundling features allows you to easily combine and minify resources within your application. Take for example an application which contains the following Javascript files:<br />
<blockquote>
<a href="http://lh6.ggpht.com/-3NkHcbzR6Ak/Tvv19rjMU9I/AAAAAAAACCU/REOVWwfMAis/image%25255B111%25255D.png?imgmax=800"><img alt="image" border="0" height="320" src="http://lh3.ggpht.com/-k1xW0Q9bobk/Tvv1-2XsR8I/AAAAAAAACCc/cZlfLBvR-hY/image_thumb%25255B109%25255D.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="201" /></a></blockquote>
In the ‘bad old days’ we may have emitted each of those script files separately, this means that the client would have to make lots of requests to pull down the content.<br />
<blockquote>
<a href="http://lh4.ggpht.com/-BZu0TMXDFLQ/Tvv2AiN-kOI/AAAAAAAACCk/61hHo83DT5w/image%25255B116%25255D.png?imgmax=800"><img alt="image" border="0" height="323" src="http://lh4.ggpht.com/-WGQnZT0IOdU/Tvv2CGT8I3I/AAAAAAAACCs/nHisVfoGj4c/image_thumb%25255B112%25255D.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="603" /></a></blockquote>
Emitting the files as above would result in the following network traffic on the client:<br />
<blockquote>
<a href="http://lh5.ggpht.com/-wUVRIIKBuiY/Tvv2DCMZ5CI/AAAAAAAACC0/1VQfw5blLXw/image%25255B120%25255D.png?imgmax=800"><img alt="image" border="0" height="91" src="http://lh4.ggpht.com/-uN3VbPI4YuE/Tvv2D-ztPpI/AAAAAAAACC8/wEUUYO-gxNY/image_thumb%25255B114%25255D.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="605" /></a></blockquote>
As you can see at the bottom of the image, 30 separate requests have been issued.<br />
<h3>
Default Bundle Behaviour</h3>
Using Bundling is as simple as registering the files that we want to optimize with the BundlingTables feature. To achieve that, we can pretty much add the following line of code to Application_Start in Global.asax to register all of the files shown above:<br />
<blockquote>
<pre class="csharpcode">BundleTable.Bundles.EnableDefaultBundles();</pre>
</blockquote>
This default behaviour will register all of the .js and .css files located in their default locations and create routes so that they can be served up by the application. Rendering them out in the page is then as simple as pointing a script tag as the route that has been registered to display them – in the default case, that would result in the following script tag being added to the bottom of your main layout file:<br />
<br />
<pre class="csharpcode"><span class="kwrd"><</span><span class="html">script</span> <span class="attr">src</span><span class="kwrd">="@Url.Content("</span>~/<span class="attr">Scripts</span>/<span class="attr">js</span><span class="kwrd">")"</span> <span class="attr">type</span><span class="kwrd">="text/javascript"</span><span class="kwrd">></</span><span class="html">script</span><span class="kwrd">></span></pre>
<h3>
Dynamic Bundles</h3>
For finer-grained control over the ordering of resources within a Bundle you can create a dynamic bundle and manually add files in the order that you want them to be rendered.<br />
<blockquote>
<pre class="csharpcode">Bundle bundle = <span class="kwrd">new</span> Bundle(<span class="str">"~/CoreBundle"</span>, <span class="kwrd">typeof</span>(JsMinify));
bundle.AddFile(<span class="str">"~/Scripts/jquery-1.7.1.min.js"</span>);
bundle.AddFile(<span class="str">"~/Scripts/jquery-ui-1.8.16.js"</span>);
bundle.AddFile(<span class="str">"~/Scripts/jquery.validate-vsdoc.js"</span>);
...
BundleTable.Bundles.Add(bundle);</pre>
</blockquote>
And then, in the page, emit the path that was just registered:<br />
<pre class="csharpcode"><span class="kwrd"><</span><span class="html">script</span> <span class="attr">src</span><span class="kwrd">="@Url.Content("</span>~/<span class="attr">CoreBundle</span><span class="kwrd">")"</span> <span class="attr">type</span><span class="kwrd">="text/javascript"</span><span class="kwrd">></</span><span class="html">script</span><span class="kwrd">></span></pre>
<strong>Note: </strong>I needed to register the Twitter Bootstrap scripts dynamically like this because I was getting errors when using the Default registration. The errors resulted because of the order that the default registration behaviour was adding the scripts to the bundle. In the case of Twitter Bootstrap, I needed to order the scripts specifically because of dependencies beteen Twipsy.js and Popover.js<br />
<blockquote>
<a href="http://lh3.ggpht.com/-lJXD1GS6FG8/Tvv2E7VcC5I/AAAAAAAACDE/DSiRUHOR6lc/image%25255B124%25255D.png?imgmax=800"><img alt="image" border="0" height="186" src="http://lh5.ggpht.com/-TeKI6gGFkHw/Tvv2F29Ww8I/AAAAAAAACDM/jjqdnB7cWfU/image_thumb%25255B116%25255D.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="522" /></a></blockquote>
<br />
<h3>
File Organization for child views</h3>
So far we have seen how to register all of the core scripts for our application but, as our application grows, we will typically introduce lots of individual scripts to manage the behaviour of specific pages. In my case, I adopt a convention where I separate all of the Javascript and CSS code out of the View files and into a CSS/JS file with a name which mirrors the view that they represent. The following Table illustrates how this mapping works:<br />
<br />
<table border="0" cellpadding="2" cellspacing="0" style="width: 486px;"><tbody>
<tr><td valign="top" width="211"><strong>Resource Location</strong></td><td valign="top" width="273"><strong>JS Location</strong></td></tr>
<tr><td valign="top" width="240">Home/Index.cshtml</td><td valign="top" width="291">Scripts/Views/Home_Index.js</td></tr>
<tr><td valign="top" width="248">Shared/ChildView.cshtml</td><td valign="top" width="296">Scripts/Views/ChildView.js</td></tr>
</tbody></table>
<br />
To give a concrete example of how this works, let’s consider that the shared partial view listed in the above table contained the following code which allows a user to click on a link:<br />
<blockquote>
<pre class="csharpcode"><span class="kwrd"><</span><span class="html">h2</span><span class="kwrd">></span>Child Content<span class="kwrd"></</span><span class="html">h2</span><span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">a</span> <span class="attr">href</span><span class="kwrd">="#"</span> <span class="attr">id</span><span class="kwrd">="clickerLink"</span><span class="kwrd">></span>Click Me<span class="kwrd"></</span><span class="html">a</span><span class="kwrd">></span></pre>
</blockquote>
The corresponding JS file would have behavioural code to handle the click event of the anchor tag like so:<br />
<blockquote>
<pre class="csharpcode">$(<span class="kwrd">function</span> () {
$(<span class="str">"#clickerLink"</span>).click(<span class="kwrd">function</span> (e) {
e.preventDefault();
alert($(<span class="kwrd">this</span>).text());
});
}); </pre>
</blockquote>
When it comes to rendering the output to the browser it will be desirable to have the JS emitted as part of the Core Bundle thus allowing us to have all scripts combined, minified, and in one optimal location at the bottom of the page.<br />
<br />
To achieve this desired outcome we simply register the child script from the partial view that depends on it like so:<br />
<pre class="csharpcode">@{
var bundle = Microsoft.Web.Optimization.BundleTable.Bundles.GetRegisteredBundles()
.Where(b => b.TransformType == <span class="kwrd">typeof</span>(Microsoft.Web.Optimization.JsMinify))
.First();
bundle.AddFile(<span class="str">"~/Scripts/Views/ChildContent.js"</span>);
}</pre>
For the sake of completeness, you would probably abstract that messy BundleTable logic out into a helper which would reduce your child registration code down to the following line of code:<br />
<pre class="csharpcode">Html.AddJavaScriptBundleFile("~/Scripts/Views/ChildContent.js", typeof(Microsoft.Web.Optimization.JsMinify));</pre>
And here's some example code for what the extension class might look like: <br />
<br />
<style type="text/css">
.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }<br />
</style><br />
<br />
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">class</span> HtmlHelperExtensions
{
<span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> AddJavaScriptBundleFile(<span class="kwrd">this</span> HtmlHelper helper, <span class="kwrd">string</span> path, Type type)
{
AddBundleFile(helper, path, type, 100);
}
<span class="rem">/// <param name="index"> </span>
<span class="rem">/// Added this overload to cater for switching between </span>
<span class="rem">/// different Script optimizers more easily</span>
<span class="rem">/// e.g. Switching between Microsoft.Web.Optimization </span>
<span class="rem">/// bundles and ClientLibrary resources could</span>
<span class="rem">/// be done seamlessly to the application</span>
<span class="rem">/// </param></span>
<span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> AddBundleFile(<span class="kwrd">this</span> HtmlHelper helper, <span class="kwrd">string</span> path, Type type, <span class="kwrd">int</span> index)
{
var bundle = BundleTable.Bundles.GetRegisteredBundles()
.Where(b => b.TransformType == type)
.First();
bundle.AddFile(<span class="str">path</span>);
}
}</pre>
<br />
<br />
<style type="text/css">
.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }<br />
</style>Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com6tag:blogger.com,1999:blog-4417089948647936949.post-48934058859595802822011-12-22T18:39:00.001-08:002011-12-22T19:34:44.238-08:00Social Internet Computing Fabric - Activity Streams<p><a href="http://initiatives.kreeo.com/#cbok/IT_Spending/contents" target="_blank">According to Gartner</a>, we are currently experiencing 4 mega trends in the world of internet computing that will change the shape of the IT landscape forever. Those key trends are: Social, Mobility, Cloud, and Context aware computing. </p> <p>If this is true, then I believe that for any application being developed today, it should be considered how each of these aspects will be woven into the core fabric of the application. In this article I will touch on what I believe is a core piece of the social computing fabric – Activity Streams.</p> <p>We’ve come to know of Activity Streams through their implementation in common social web applications such as Facebook and LinkedIn. Twitter has recently started exposing Activity Streams through their <a href="https://twitter.com/#!/activity" target="_blank">Activity Tab</a> and Facebook even offers <a href="http://developers.facebook.com/docs/reference/plugins/activity/" target="_blank">an extensibility plugin to embed their Activity Feeds</a> outside of their own website.</p> <p>As you plan your own architecture you may come to think of designing a custom Activity Stream to display recent activities to users of your site. You would start planning by thinking about the different types of activities that can occur like so:</p> <blockquote> <p><a href="http://lh6.ggpht.com/-_nh6IiEkp2M/TvPpqanx9nI/AAAAAAAAB_E/7H9d3AZU9og/s1600-h/image%25255B8%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-ar4admpgU1w/TvPprhapt-I/AAAAAAAAB_M/wAhwo2OM3VU/image_thumb%25255B6%25255D.png?imgmax=800" width="482" height="306"></a></p></blockquote> <p>Here we see that a user can perform many actions within the site and that we may wish to display each of these in an Activity Stream. When the user performs an activity, the details of that event are captured and stored in a database. When you combine the overall amount of activity from many users within a social network, you can see that the Activity Stream becomes a useful barometer of what’s going on. </p> <p>You could also add other activities such as Favourite’ing, Liking, Member Profile updates, etc. There is no limit to the number of types of different activities that you might want to display it all comes down to the type of application that you are developing and what it would make sense for the members of the social networks contained within your application to see.</p> <p>As you design your Activity Stream, many questions will arise. One of the questions that you will come across is that of permissions – which activities should members be able to see?</p> <blockquote> <p><a href="http://lh4.ggpht.com/-E4xdJW-Jy-4/TvPps3xNWQI/AAAAAAAAB_U/1G7TzFwkWgQ/s1600-h/image%25255B14%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-z-Vhnt9VPBs/TvPpuJpwXII/AAAAAAAAB_c/ptIUMnQcFiA/image_thumb%25255B10%25255D.png?imgmax=800" width="527" height="390"></a></p></blockquote> <p>Some of the constraints surrounding permissions might be whether the two users are members of the same group, or whether one of the users has set specific content constraints on an individual content item.</p> <blockquote> <p><a href="http://lh4.ggpht.com/-0M1BPPKRDsg/TvPpvcH3M4I/AAAAAAAAB_k/HMgU47EfLFE/s1600-h/image%25255B19%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-nEBK1OZmer4/TvPpwo7hWlI/AAAAAAAAB_s/rT1gEywuCwM/image_thumb%25255B13%25255D.png?imgmax=800" width="476" height="398"></a></p></blockquote> <h2>Data Structure</h2> <p>A way to deal with this is to raise events consistently throughout your application and have a set of listeners log the details of those events into a table with columns that describe attributes for each permission boundary that you might want to filter on. This might include filtering on attributes such as:</p> <ul> <li>IsPublic – a flag which determines whether the content is visible to everybody <li>UserId – the identity of the user who posted the item <li>GroupId – the identity of the group that the content was posted to <li>FolderId – an optional identity value indicating which folder within the group that the content was posted to</li></ul> <p>Other columns that I would suggest including in your Activity Stream table are:</p> <ul> <li>RSS Fields – Fields that allow you to display a title, date created, and description without having to run separate queries to get at that information. <li>Item Type – A value which indicates the type of item. This could be used to display a custom icon to represent the item in the Activity Stream when rendered on a web page for example. <li>Item Id – The underlying identity of the item being represented.</li></ul> <p>The Activity Stream data will end up looking something like the data in the following image:</p> <blockquote> <p><a href="http://lh3.ggpht.com/-3NszK1_9S_s/TvPtbaDO71I/AAAAAAAAB_0/IyMaLYkrqFg/s1600-h/image%25255B23%25255D.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-J-xGYHeXkHU/TvPtdPCz91I/AAAAAAAAB_8/hbdAqgOqyV4/image_thumb%25255B15%25255D.png?imgmax=800" width="490" height="243"></a></p></blockquote> <p>And from this data can be crafted a query which has the logic to enforce permissions based on your application’s logic. An example of such a query might look like this:</p> <blockquote><pre class="csharpcode"><span class="kwrd">CREATE </span><span class="kwrd">PROCEDURE</span> [dbo].[GetStreamItems] <br /> @accountId <span class="kwrd">int</span><br /><span class="kwrd">AS</span><br /><span class="kwrd">BEGIN</span><br /> <br /><span class="kwrd">SELECT</span> <span class="kwrd">top</span> 100 [StreamItemId] ,[Title] ,[Description] ,[ItemId] ,<br /><span class="str">'Item Type'</span> = <br /><span class="kwrd">case</span> <br /> <span class="kwrd">when</span> [ItemTypeId] = 1 <span class="kwrd">then</span> <span class="str">'Post'</span><br /> <span class="kwrd">when</span> [ItemTypeId] = 2 <span class="kwrd">then</span> <span class="str">'Comment'</span><br /> <span class="kwrd">else</span> <span class="str">'System Message'</span><br /><span class="kwrd">end</span>,<br />[IsPublic] ,[AccountId] ,[GroupId] ,[FolderId], [CreatedDateTime]<br /><span class="kwrd">FROM</span> [StreamItems] <span class="kwrd">as</span> A<br /><span class="kwrd">WHERE</span> IsPublic = 1<br /><span class="kwrd">OR</span> (AccountId = @accountId)<br /><span class="kwrd">OR</span> (GroupId = <span class="kwrd">ANY</span>(<span class="kwrd">SELECT</span> GroupId <span class="kwrd">FROM</span> dbo.AccountGroups <span class="kwrd">WHERE</span> AccountId = @accountId) <span class="kwrd">and</span> A.FolderId <span class="kwrd">is</span> <span class="kwrd">null</span>)<br /><span class="kwrd">OR</span> (FolderId = <span class="kwrd">ANY</span>(<span class="kwrd">SELECT</span> FolderId <span class="kwrd">FROM</span> dbo.AccountFolders <span class="kwrd">WHERE</span> AccountId = @accountId))<br /><span class="kwrd">order</span> <span class="kwrd">by</span> CreatedDateTime <span class="kwrd">desc</span>;</pre></blockquote><br /><style type="text/css">.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }<br /></style><br /><br /><p>Here we see that the permission logic is encoded in the WHERE clauses at the bottom of the query. The logic here only displays items if any of the following rules are true:</p><br /><ol><br /><li>The item is <strong>public</strong>ly visible</li><br /><li>The item was <strong>created by</strong> the user who is invoking the query</li><br /><li>The user who is invoking the query is a <strong>member of a group</strong> that the item was posted to</li><br /><li>The user who is invoking the query is a <strong>member of a folder</strong> that the item was posted to</li></ol><br /><p>The other thing to notice about the query is that only the Top N rows are retrieved and that the query is ordered by the date of the item. The reason for this is performance. Note also that, for performance reasons your would create an index on the CreatedDateTime column so that the ordering would be done via an index seek and not by a table scan.</p><br /><h2>Performance Characteristics</h2><br /><p>For many smaller applications, performance will not be a significant factor to designing your architecture. And, as they say, in the world of the web, performance constraints are generally a nice problem to have (because it means that you have lots of users <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://lh6.ggpht.com/-KCfqByFHT58/TvP1fKRiHDI/AAAAAAAACAE/LZMW4n53OCg/wlEmoticon-smile%25255B2%25255D.png?imgmax=800">). But it pays to do some analysis to see the rate at which your data will grow. To consider this, let’s assume the following set of user profiles for our website:</p><br /><blockquote><br /><p><a href="http://lh5.ggpht.com/-FAE4ijznrQU/TvP1hSMccJI/AAAAAAAACAM/mzlUNWbgBGY/s1600-h/image%25255B6%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-b4nmTYHX8lE/TvP1iW0aBLI/AAAAAAAACAU/XY04LsZmQqg/image_thumb%25255B3%25255D.png?imgmax=800" width="576" height="235"></a></p></blockquote><br /><p>This shows user profile data for an application which has 3 segments of users:</p><br /><ol><br /><li><strong>Low Use</strong> (avg. 2 activity items per day) – account for 40% of the total user base</li><br /><li><strong>Medium Use</strong> (avg. 10.7 activity items per day) – account for 40% of the total user base</li><br /><li><strong>High Use</strong> (avg. 23 activity items per day) – account for 20% of the total user base</li></ol><br /><p>Given these usage profile ratios, we can then start to calculate how many items our Activity Stream table will grow to over time based on the total number of users that we expect to have.</p><br /><blockquote><br /><p><a href="http://lh3.ggpht.com/-ytxAKftRqc8/TvP1jWtWouI/AAAAAAAACAc/pxhPiIzoYo8/s1600-h/image%25255B12%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-RWz-gFZ1sRI/TvP1kj31FiI/AAAAAAAACAk/crVeIhEwrYQ/image_thumb%25255B7%25255D.png?imgmax=800" width="583" height="203"></a></p></blockquote><br /><p>Here we can see the calculation of expected activity based on total site users of 50, 100, 1,000, and 10,000. At 1,000 users per day we can see that our profile user base would generate around 2,050 database entries per day and, at 10,000 site users, this would grow to around 20,500 entries per day.</p><br /><p>So, at the top end of these numbers, our Activity Steam database would accumulate around 2.5 million rows of data every 120 days. This is where the optimization benefit of indexing and only returning the most recent N entries would really pay the most dividend as you would still be fetching data in a few hundred milliseconds and returning it to your user in an acceptable amount of time.</p> Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com0tag:blogger.com,1999:blog-4417089948647936949.post-57455964158199865912011-12-13T19:40:00.000-08:002011-12-27T15:49:12.696-08:00Problem Updating Nuget - Online Gallery Offline<br />
While attempting to update to the <a href="http://docs.nuget.org/docs/release-notes/nuget-1.6" target="_blank">recently released 1.6 version of Nuget</a> at work, a few of us were having trouble connecting to the Online Extension Gallery in Visual Studio. As you can see in the following image, the Online Gallery was listed as being 'Offline'.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-ys0JgnlF2-o/TugZQsuslbI/AAAAAAAABzk/e1PR4h7j4oE/s1600/Capture.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="136" src="http://1.bp.blogspot.com/-ys0JgnlF2-o/TugZQsuslbI/AAAAAAAABzk/e1PR4h7j4oE/s640/Capture.PNG" width="640" /></a></div>
<br />
Thankfully one of my colleagues solved the problem by applying a tweak to the <b>devenv.exe.config</b> which is located at <em>C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE</em><br />
<pre><blockquote class="tr_bq">
<configuration>
....
<system.net>
<settings>
.....
<span style="background-color: yellow;"><servicepointmanager expect100continue="false" /></span> </settings>
</system.net>
</configuration></blockquote>
</pre>
Other things to consider if you are having troubles applying the Nuget update:<br />
<ol>
<li>If the package won't update, consider un-installing and reinstalling it</li>
<li>You should run Visual Studio as Administrator</li>
<li><a href="http://rpeck.co.uk/post/4336758008/unable-to-access-vs2010-extension-manager-online" target="_blank">It could be a proxy issue</a></li>
</ol>Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com0tag:blogger.com,1999:blog-4417089948647936949.post-81250710041858403082011-12-12T16:14:00.000-08:002011-12-12T16:14:00.440-08:00A result message format for asynchronous web operationsOver the past year I've been working on developing <a href="http://skillslibrary.net/" target="_blank">SkillsLibrary </a>as a cloud-based application for doing sports analysis through video on the web. During that time I've learned a lot about the many and various challenges of building a modern web application. Nowadays things such as mobility, page speed, and asynchronous operations rank high on the list of 'must have' requirements. In this post I thought I'd touch on a simple little standard that I've used to help make the job of handling asynchronous operations simpler.<br />
<br />
Let's start by looking at a typical piece of code for invoking an asynchronous operation:<br />
<blockquote class="tr_bq">
<pre>$.post("/members/remove", data, function (result)
{
}</pre>
</blockquote>
This method is used to invoke a server side operation by passing a JSON data object to a controller action at the path '/members/remove'. As we see from that code, the abstractions in modern Javascript libraries such as jQuery have made really simplified doing such operations.<br />
<br />
The problem I set out to solve was to provide a consistent way to handle the response which comes back from the server.<br />
<br />
Think about it for a moment... after we invoke the above operation, typically we will need to update a piece of user interface to reflect the result. And that result may not have necessarily succeeded! Let's imagine that the member we attempt to remove is not able to be removed because of a business rule. Or if our logic fails and an exception occurs somewhere in the processing logic. Or, perhaps it did succeed after all?<br />
<br />
In SkillsLibrary I've developed a simple little 'interface' pattern for results which get returned from asynchronous operations which looks like this:<br />
<blockquote class="tr_bq">
<pre>{
bool Success;
object Model;
string Message;
}</pre>
</blockquote>
Having a common structure for returning messages has a few benefits:<br />
<ol>
<li>You can create helper code to create the return messages</li>
<li>You can create common client-side code for handling return messages</li>
</ol>
<div>
Focussing on the second of these benefits, think again about what can potentially happen when an async result is invoked. In the first case, let's consider that the operation fails for some reason. Your client-side code will need to know that the operation failed and be able to give the user some information about the failure. In such a case it's as simple as querying the Success property and displaying the Message to the user like so:</div>
<blockquote class="tr_bq">
<pre>$.post("/members/remove", data, function (result)
{
if( !result.Success )
{
UIHelper.displayErrorElement(result.Message);
} else {
...
}
}</pre>
</blockquote>
Whereas, if the operation succeeds, we might want to do an operation to manipulate the DOM in some way to add or remove an object from the UI. Again, this is easily achieved by using the Model property of the return message which will contain an object that represents a data item for the operation that was executed.<br />
<blockquote class="tr_bq">
<pre>$.post("/members/remove", data, function (result)
{
if( !result.Success )
{
UIHelper.displayErrorElement(result.Message);
} else {
UIHelper.removeDOMItem($"#rootDOMElement", result.Model.Id);
}
}</pre>
</blockquote>
You can see that, having a consistent way of returning messages from the server we are able to streamline our client-side handling code which improves maintainability by having less code that is more readable.<br />
<br />Anonymoushttp://www.blogger.com/profile/07856436580130258988noreply@blogger.com0