Here’s a cool gem I discovered when running the ReSharper 5.0 EAP. Clicking CTRL+B on “return View()” in a controller action has the option to navigate directly to the view that belongs to the action. No more trying to find the _right_ “Index.aspx” file.
Monthly Archives: December 2009
Latest release of Cropper works great on Windows 7 x64
Cropper is still alive and well and has a new release on November 27, 2009. It works great on Windows 7 x64 Ultimate. I use the built-in Snipping Tool, but Cropper is just more friendly to use because it automatically drops captures into a defined folder. When writing articles, books, and blog posts, I can grab my shots and pick them up later. Here is a shot of the MvcContrib GitHub page:
And Here is a shot of the download section on the CodePlex.com project site:
AltNetConf email list is back!
Today, December 2009 is roughly 2 years after the AltNetConf list was changed to “cli_dev”, effectively killing the list. Just look at the graph of activity for this list:
The AltNetConf in October of 2007 kicked off a flurry of discussion about ALT.NET. The discussion was essentially talk about best practices for .Net. You can see that this list has been completely dormant since April of 2008.
Jeff Atwood’s recent post about OSS parenting got me thinking about this list. I started it for the AltNetConf and announced it during the conference (which as largely led by Scott Bellware and David Laribee). I have largely neglected this list and let spam remain. I went through the work of cleaning the list of lots of spam and banning the spammers. I’ve also put moderation in place to prevent spammers from joining, and now the list is groomed and ready to resume serving the community.
As with open-source, I expect the community to vote with its feet. Either this list will bustle with activity again, or this post will be the only mention of it. Either way, I’ll try to be a good parent, Mr. Atwood.
You can find the AltNetConf list here: http://tech.groups.yahoo.com/group/altnetconf/
What is the purpose of the list now? The purpose is stated in the group description, and it is as follows:
“This groups serves as a hub of discussion about ALT.NET conferences, user group meetings, meet-ups, and other "conferencing" of people around the topic of ALT.NET.
This list has a colorful history, and if you have time, please read the archives. It started during the original AltNetConf in October of 2007 and now serves as a way to collaborate on future ALT.NET conferences and the like.”
CodeCampServer Call for Participation
I just posted this message to the discussion list.
Right now on http://codecampserver.com/, there are two active user groups
that are hosted with the platform: http://www.adnug.org/, and
http://www.c4mvc.net/. CodeCampServer is a multi-tenant application, and
the routing handles knowing which user group the data is for.
We need volunteers in two main areas:
1. Expanding and maintaining CodeCampServer.com
– Evangelizing CodeCampServer.com
– Onboarding new .Net user groups
– Production server monitoring
2. Creating and driving CcsContrib (CodeCampServer-Contrib).
– Organizing and moderating this new open-source project
– Producing builds that can be deployed with CodeCampServer.com
– Evaluating and accepting patches to this project.
Overall, we have two companies who have pledged ongoing funding for
CodeCampServer:
ORCSWeb <http://www.orcsweb.com/> is maintaining a dedicated server on which
CodeCampServer runs. They have graciously donated this server so that .Net
user group might have a website hosted for them for free.
Headspring Systems <http://headspring.com> is maintaining the core
multi-tenant application. Headspring will continually enhance the core as
well as the CcsContrib plugin model, which is MvcContrib’s Portable
Areas<http://www.lostechies.com/blogs/hex/archive/2009/11/01/asp-net-mvc-po…>.
In this way, CcsContrib will contain perhaps many portable areas that add
lots of new functionality on top of the CodeCampServer core.
If you are interested in contributing either as a CcsContrib developer or a
project manager/facilitator, please reply here. Based on replies and
interest, I will schedule a conference call to discuss the formation of a
CodeCampServer committee. All the interest in CodeCampServer has been
organic, and I want to somewhat get out of the way so that the community can
get the most out of this project.
Best regards,
Jeffrey Palermo
Bank deposits via iPhone are here
Party with Palermo: MVP Summit 2010 edition – book flight now
If you are registering travel for the Microsoft MVP Summit in 2010, book your travel so you can attend.
Party with Palermo will be on February 15, 2010 at 7PM. Save the date. More details will be coming.
InfoQ interview on ASP.NET MVC in Action now published
Jon Arild Tørresdal recently interviewd Jimmy Bogard, Ben Scheirman, and I about our recent book, ASP.NET MVC in Action. The interview is published here on InfoQ, and it includes a free chapter download as well.
What training doesn’t teach you about reading from .Net configuration
All the material I’ve seen talking about reading from .Net configuration files concentrates on explaining the API. The API of ConfigurationManager exposes members such as:
public static class ConfigurationManager { static ConfigurationManager(); public static NameValueCollection AppSettings { get; } public static ConnectionStringSettingsCollection ConnectionStrings { get; } public static object GetSection(string sectionName); public static void RefreshSection(string sectionName); public static Configuration OpenMachineConfiguration(); public static Configuration OpenMappedMachineConfiguration(ConfigurationFileMap fileMap); public static Configuration OpenExeConfiguration(ConfigurationUserLevel userLevel); public static Configuration OpenExeConfiguration(string exePath); public static Configuration OpenMappedExeConfiguration(ExeConfigurationFileMap fileMap, ConfigurationUserLevel userLevel); }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
That is a pretty fine-grained API. Every time a developer cracks open that class with intellisense, he is presented with too many choices. Besides that, after getting some functionality working (such as hiding an advanced search criteria based on configuration (for a particular application instance)), the code looks something like this, a jumble of user code and framework call:
public bool ShouldBeVisible(CriteriaName name) { string key = "criterion." + name + ".visible"; string value = ConfigurationManager.AppSettings.Get(key); if (string.IsNullOrEmpty(value)) { return true; } return Convert.ToBoolean(value); }
Given that this code wants to show the criterion by default and let configuration override that, this method needs to be tested. Because of the framework call to configuration, its more difficult to test than necessary. Note, if you aren’t writing automated tests for your code, you probably think I’m crazy right now.
The developer has to run the app three times to ensure this work:
- Once with no configuration setting, should default to true
- Once with a setting that explicity sets to true
- Once with a setting that explicity sets to false
In my experience as a developer and a manager, running the application manually to test these three posibilities takes longer than banging out the three short automated tests for these cases.
There is a problem, through. Because the call to ConfigurationManager (a static class) is embedded in the method, my test code needs to move or modify a REAL configuration file at test time.
The solution: wrap configuration and expose a course-grained interface to may application code. It’s very easy to write your own, but we tend to use the configuration interface defined in the Tarantino project. It’s definition is as follows:
public interface IConfigurationReader { string GetRequiredSetting(string key); int GetRequiredIntegerSetting(string key); bool GetRequiredBooleanSetting(string key); IEnumerable<string> GetStringArray(string key); bool? GetOptionalBooleanSetting(string key); string GetOptionalSetting(string key); }
This may be more than you care to use, so you can trim it down even more very easily. The resulting code is as follows:
public class UiPreferences : IUiPreferences { private readonly IConfigurationReader _reader; public UiPreferences(IConfigurationReader reader) { _reader = reader; } public bool ShouldBeVisible(CriteriaName name) { string key = "criterion." + name + ".visible"; string value = _reader.GetOptionalSetting(key); if (string.IsNullOrEmpty(value)) { return true; } return Convert.ToBoolean(value); } }
Because of the interface, our unit tests are very simple, and the code is simpler as well.
[Test] public void Should_show_criterion_by_default_without_configuration() { var settings = new NameValueCollection(); var configurationReader = new ConfigurationReader(new ConfigurationStub(settings)); var preferences = new UiPreferences(configurationReader); bool shouldBeVisible = preferences.ShouldBeVisible(CriteriaName.LastName); Assert.That(shouldBeVisible, Is.True); } [Test] public void Should_show_criterion_by_configuration() { var settings = new NameValueCollection {{"criterion.LastName.visible", "True"}}; var configurationReader = new ConfigurationReader(new ConfigurationStub(settings)); var preferences = new UiPreferences(configurationReader); bool shouldBeVisible = preferences.ShouldBeVisible(CriteriaName.LastName); Assert.That(shouldBeVisible, Is.True); } [Test] public void Should_hide_criterion_by_configuration() { var settings = new NameValueCollection {{"criterion.LastName.visible", "False"}}; var configurationReader = new ConfigurationReader(new ConfigurationStub(settings)); var preferences = new UiPreferences(configurationReader); bool shouldBeVisible = preferences.ShouldBeVisible(CriteriaName.LastName); Assert.That(shouldBeVisible, Is.False); }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Hard drive is officially the bottleneck on the development laptop
Hard drive is officially the bottleneck on the development laptop. Of course that isn’t news, but on this Dell Precision M4400 laptop (Intel Dual Core, 8GB RAM), I’m still looking for a solution to the hard drive problem. Intel X-25 series looks promising, but if SuperSpeed would hurry up with SuperCache for Windows 7 x64, the problem might be solved through RAM and software while retaining the reliability of magnetic disks. We’ll see.
Running Visual Studio 2010 on Win 7 inside XP Mode
I outlined in an earlier post how XP Mode gives Windows 7 users a very easy way to try out beta software without worrying that the main operating system install might be messed up.
Here is a screenshot of VS 2010 Beta 2 running on my Win7 desktop. Notice that the only way to tell is that it has the blue Windows XP bar at the top instead of the Win 7 Aero bar like Task Manager in front of it.