Monday, November 21, 2011

I donated and so should you.

I read Wikipedia at least once a day.  Usually many times a day.  So...

Support Wikipedia

You have taught me so much that I was curious about and so much about what I didn't know I wanted to know. Keep up the good work.

Monday, November 07, 2011

My professional philosophy: "The General Problem" from xkcd

I don't think anything could describe my professional philosophy more succinctly or clearly than this xkcd comic:

"The General Problem"
"I find that when someone's taking time to do something right in the present, they're a perfectionist with no ability to prioritize, whereas when someone took time to do something right in the past, they're a master artisan of great foresight."

Wednesday, July 13, 2011

It's not easy being green

I had once been directly involved with the development team for an automotive market software product.  As a result, I worked with resources from the Automotive Aftermarket Industry Association and ended up on their mailing list for their publication: "Aftermarket Insider" which I receive monthly.  Volume 70 arrived recently.  I noticed, as often happens with periodical advertising supplements, that the issue was wrapped in a plastic sleeve containing a loose insert along with the primary publication.  I thought nothing of it until I noticed the content of the insert.  It was very nice, recycled card stock with a printed gloat about how "The automotive aftermarket industry was green long before being green was mainstream."

Really?  You tell me this by including it on unnecessarily thick paper enshrouded in plastic?

Instead, you could have emailed that to me in one of your regular blast mails from which I still can't seem to unsubscribe...

*sigh*

Monday, June 13, 2011

1 Year = 2.6 Million Keystrokes

A look back at my last year of typing.

Having mild OCD is advantageous to being a programmer.  But it has its drawback, such as forgetting to take breaks, use the bathroom, eat and sleep.  In April 2010, after seeing a coworker using it, I installed Workrave on my work desktop to help my effort to be better about taking breaks.  Workrave is a task tray tool that pops up reminders to take micro-breaks (to stretch your various appendages and eyes), longer breaks and can alert you to help limit your overall daily computer use, in whichever combinations you so choose.  All of this is an effort to help reduce repetitive stress injuries common among heavy computer users.  Along with these features, Workrave tracks your key-presses and mouse movement distance.  Since my "mouse" is a trackball and thus never really moves, the mouse movement figures are generally useless.  (However, it does track movement time which could be helpful for tracking how long your hand is working the mouse.)  The keystroke count is much more concrete, which gave me an idea.

I started recording the daily keystroke stats and now have some impressive numbers.  Since April 9th 2010, 2,899,821 keystrokes have been recorded.  Excluding those after April 9th of this year, the total is 2,599,992.  That's 2.6 Million keystrokes for one calendar year.

I moved the stats from post 4/9/2011 to the beginning to create one complete calendar year, and came up with the following detailed figures:

  • Grand Total: 2,599,992
  • Monthly Average: 216,666
  • Highest Month: 291,506 (Feb)
  • Daily Average: 11,255
  • Highest Day: 29,110

Some additional information that influences the numbers (positively and negatively):

  • Sometimes I work from home.  Occasionally I use remote desktop and work on my desktop where the count is recorded.  Some days I don't.  This could account for a lower count.
  • My work setup includes a laptop.  The laptop screens are set up next to the desktop screens and I use Synergy to control both machines from a single keyboard/mouse, giving me a single, contiguous desktop (another tool I highly recommend).  The desktop serves as the Synergy server, acting as the input master which allows all input control going to the laptop to pass through the Workrave counters running on the desktop.  Occasionally, due to a glitch or a reboot, I won't have primary control so I'll physically switch to the laptop keyboard/mouse.  This could account for a reduction in keystroke count, though probably not much.
  • I haven't really been doing much programming lately, certainly not as much as in years past.  I do a lot of systems administration, infrastructure and other tasks that require less typing.  On days that I am actually writing code, my numbers jump significantly.  A safe estimate is an average in the 10,000 to 20,000 range, usually towards the high end.

I took a look back over my daily numbers and journal entries for those high count days.  I found that the days I'm writing code, I average around 20,000 keystrokes.  So I can make a fairly safe prediction that if I spent most days writing code I would probably have numbers closer to these:

  • Daily Average: 20,000
  • Monthly Average: 418,333
  • Yearly Total: 5,020,000

That figure seems pretty crazy to me.  I never would have estimated in the millions if I'd been asked how many keystrokes I think I make in a year.  Considering that I've been a developer for a solid 11 years, and until recently, most of that has been spent programming, I would venture a guess that I have over 55 million keystrokes under my fingertips.  I have trouble fathoming that.  My typing teacher in high school would be proud.

Wednesday, May 11, 2011

Where I put my extension code

In a comment on my "ASP.NET MVC - Excluding Model Validation Rules" post reader @wow0609 asked:
Where do you put something like this in your MVC project? This is a specific extension method, probably in a file by itself. Do you have a specific structure (directory / folder) you use for this? Do you have a generic /common folder or something?

I felt this question was worthy of a dedicated post. I break it down this way.

Sharable Code
If the code I've written is not specific to a particular application (as is the case of excluding model validation rules) then I will most likely put it into one of the shared libraries used by my development group.  Those libraries have lots of utility functions and such that are generic to the platform/stack they support.

Application Specific Code
When the code is really only applicable to one application then I'll put it into the application's project.  For a web project I'll typically put them in a class under a "Components" directory.  Often, code will start here and then I'll refactor it to be more generic and move it to a shared library.

In either case, for extension methods I usually name the class/file using this pattern: "[extendedclass]Extensions".  For example: HtmlHelpersExtensions.  I set that class' namespace to the extended class' namespace.  In the case of the MVC model validation rule exclusion extension it would be "System.Web.Mvc".  This eliminates the need to explicitly import/include the custom namespace to discover extension methods which is particularly helpful for shared libraries (or if you are like me and can't remember what you wrote last week).

Friday, February 04, 2011

ASP.NET MVC - Excluding Model Validation Rules

While building a simple MVC app, I came across the problem where I am using one model in several views. The model includes DataAnnotation attribute rules for validation. However, some rules don't apply to certain views. It seems this is a common problem, without a well established solution. After searching a bit, I found this post by Andrew West that nicely summarizes the problem and several solutions. His last suggestion is to remove the items from ModelState that you don't want to participate in the validation. I agreed that this was the simplest and least dependent solution and pursued it.

What I finally came up with was a simple extension method for the ModelStateDictionary that looks like this:
public static void CleanAllBut(
this ModelStateDictionary modelState,
params string[] includes)
{
modelState
.Where(x => !includes
.Any(i => String.Compare(i, x.Key, true) == 0))
.ToList()
.ForEach(k => modelState.Remove(k));
}

The method removes everything in the model state dictionary that doesn't match one of the "includes" strings. Being a params argument to the method, the call to it becomes very clean and readable (unlike the extension method itself). So I added this call to my controller method:
ModelState.CleanAllBut("username", "password");

While we can use the existing ModelStateDictionary.Remove() method for when we only want to explicitly remove one item, for multi-key removal we could make a similar extension method that takes a list of keys to remove.

Thursday, January 27, 2011

Adding MVC view file extension exclusion to T4MVC

Yesterday I wrote about creating razor view engine code behind files. I've been playing with the T4MVC T4 template for ASP.NET MVC that I learned about by watching this video.

Today I discovered that the view code behind files I created are showing up in the MVC.<controller>.Views list because the files (*.cs) are in the views folders next to the actual views (*.cshtml). Due to the naming convention I used, the *.cs file comes first in the directory listing. While the T4 template code gracefully deals with files with the same name portion of the full filename, the consequence of my names resulted in the generation of the following two properties:
MVC.Shared.Views.PlantListPager
MVC.Shared.Views.PlantListPager_cshtml

The first is the result of the code-behind file (PlantListPager.cs) while the second comes from the actual view (PlantListPager.cshtml). Again, the template gracefully deals with a potential name conflict. However, access to the code-behind path is not needed and the resulting extra property looks messy.

I looked through the T4MVC.settings.t4 file and found the ExcludedStaticFileExtensions array of extensions that excludes the specified file extensions from property generation for the files found in the static folders (as specified by the StaticFilesFolders array just above it in the settings). Unfortunately, I didn't find a similar array specifying exclusions for view folder(s)'s files. Presumably, this is because the view folders would typically not have anything other than actual view files. So I added the following block to the settings:
// View file extensions to exclude from the generated links   
readonly string[] ExcludedViewFileExtensions = new string[] {
".cs"
};

In the T4MVC.tt template file, I found the code that excludes the static files in the "ProcessStaticFilesRecursive" method after which I modeled the following block that I added to the "AddViewsRecursive" method:
if (ExcludedViewFileExtensions.Any(extension =>
item.Name.EndsWith(extension, StringComparison.OrdinalIgnoreCase)))
continue; // ignore defined extensions

This checks for extension exclusions when the list of views to create as properties is first built up.

Now I realize that I should probably just contribute this change back into the MvcContrib project. However, I'm going to cop out for the following reasons:

  • I don't have the infrastructure tools and knowledge required (Mercurial & NUnit)

  • I thought it would be valuable to illustrate how relatively simple it is to make a change to an existing T4 template without totally messing it up.


If there's a T4MVC contributor out there reading this who'd like to include this change, by all means, please do.

Wednesday, January 26, 2011

ASP.NET MVC3 - Creating razor view engine code behind files

While code behind files are generally discouraged for MVC views, there are still times when it's helpful to have strongly typed and pre-compiled code to support a view when you have something more than rudimentary logic involved with view processing.

In order for a single Razor view to have a code-behind file, it must be changed to inherit from another class instead of the default view page class, which is defined in the ~/Views/web.config as
System.Web.Mvc.WebViewPage

The view base class is modified with this addition to the view's markup file:
@inherits <class name>

For example, a code-behind class for ~/Views/Home/Index.cshtml would be
@inherits MySite.Views.Home.Index

If you have a model specified for the view using the @model nugget you must remove it from the view code and apply it to the new base class.

Next, create a new class file for the code-behind class. Following convention, it's probably best to put the file in the same directory as the view file itself and name it similarly. I just grab the view's file name and drop the "html" from the extension. Thus, following our example, we end up with:
~/Views/Home/Index.cs
~/Views/Home/Index.cshtml

The generated class file needs to be modified in these ways:

  • Set the base class to WebViewPage, or WebViewPage<model type> if you had a model type specified in the view code.

  • Add "abstract" to the class definition (a concrete implementation of a WebViewPage derived class must implement the "Execute" method)

Continuing with our example we have a code-behind file for the Home/Index view that looks like this:
namespace MySite.Views.Home
public abstract class Index : WebViewPage
{
// ... my super-duper code goes here
}
}

Now code away! Be sure to expose any methods you want to call from the view code as "protected" or "public" so they are visible to the view's derived class.

Just remember that a view code-behind file is not a substitute for proper separation of concerns. Remember to keep the code you place in a view code-behind class limited to only logic required to make the view do what it needs, no more. Any code that starts to smell of business/application logic should be moved to the appropriate place, either a business library or a controller.

Saturday, January 15, 2011

ASP.NET MVC Razor - AJAX partial page updating using views with default layout

ASP.NET MVC controller action methods that return views don't care whether that view is technically implemented as a full view or a partial view. You can just as easily return a view created as a partial as easily as a standard, full view and the controller cares not. Nor, it seems, does the view engine. It will happily render out the content of the view as it is defined in its markup file. This provides a handy mechanism by which a partial view can be used to perform partial page updates via AJAX. An initial load of a full view can include a call to render a partial view, then a subsequent call from AJAX can explicitly return just the partial view. I've used this technique several times with the original ASPX view engine and not had any issues. However, once I started playing with the Razor view engine, I encountered a strange side effect.

Both the ASPX and Razor view engines can define the master page/layout to use at a global level. For ASPX it's in the web.config:
<pages masterPageFile="~/Views/Shared/Site.Master">
...
</pages>
For Razor it's in the view start file for your chosen language, in my case it's C# (_ViewStart.cshtml):
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}

ASPX view engine partial views (*.ascx) include (apart from the obvious file extension difference) a specific directive instructing the view engine that it is a partial view (@ Control) and not a regular view (@ Page). This causes the view engine to knowingly treat it as a partial view, rendering only its contents. However, since Razor views are all the same there is no declaration to indicate that the view code in one .cshtml file is for a partial view versus a full view. Any Razor view will have the same startup rules applied.

When a Razor view is rendered as a partial from another view, such as:
@Html.Partial("mypartialview")
or
<% Html.RenderPartial("mypartialview"); %>

the view engine seems to recognize that the view is being loaded as a partial and (presumably) changes the inner view's Layout property to null and things work as desired.

However, when you make an MVC action call that specifically loads JUST a partial view as the ViewResult with the intent of doing a partial page refresh, the results will differ based on the the view engine. For an ASPX engine partial view (i.e. *.ascx) the view will load and render as is. It contains no references to a master page and the view engine knows explicitly that it is a "@ Control" and thus does not wrap it in any default master page, if one is defined. On the other hand, a Razor view is loaded as any other view and will include the master layout set by default. What is intended as a partial page update will actual return with all of the layout pages HTML around it. In order to keep a Razor view as a partial view, any existing value for the view's Layout property must be negated. This code can be placed in a code block of any view that is intended to be a partial view:
@{
this.Layout = null;
}

This will cancel out any default master layout setting and render the view with only that view's contents. When the same view is included in another view as a partial, the above code will have not effect since the calling view has already nulled out the layout file anyway.

If you wanted to, you could use a view for either a full view (with the default layout's content) or a partial view by conditionally nulling out the Layout property based on some view data set by an appropriate controller action. Combined with a parameter passed in by the AJAX caller, this could provide a useful mechanism for reusing view elements.

Friday, January 14, 2011

Doing 2+ aggregations in LINQ to SQL

I was recently trying to do a simple double aggregation using LINQ to SQL.

Here's the setup:

One table "Plant" containing these two fields of concern:
  ZoneMin tinyint
ZoneMax tinyint

There's a search view on which I want to include the selection of a range for each of those fields. Therefore, I want to select the minimum and maximum of each field. In T-SQL this would be trivial:
SELECT
MIN(ZoneMin) MinMin, MAX(ZoneMin) MinMax,
MIN(ZoneMax) MaxMin, MAX(ZoneMax) MaxMax
FROM Plant

I tried numerous approaches with the .Aggregate() method, grouping and everything else I could think of. No luck. I finally broke down and posted to StackOverflow and got a simple answer. The end result is this LINQ query:
Plants.GroupBy (p => 0).Select (p => new { 
MinMin = p.Min (x => x.ZoneMin),
MinMax = p.Max (x => x.ZoneMin),
MaxMin = p.Min (x => x.ZoneMax),
MaxMax = p.Max (x => x.ZoneMax)
})

This yields the following T-SQL (courtesy of LINQPad):
-- Region Parameters
DECLARE @p0 Int = 0
-- EndRegion
SELECT
MIN([t1].[ZoneMin]) AS [MinMin], MAX([t1].[ZoneMin]) AS [MinMax],
MIN([t1].[ZoneMax]) AS [MaxMin], MAX([t1].[ZoneMax]) AS [MaxMax]
FROM (
SELECT @p0 AS [value], [t0].[ZoneMin], [t0].[ZoneMax]
FROM [Plant] AS [t0]
) AS [t1]
GROUP BY [t1].[value]

Comparing the two execution plans (Query 2 is LINQ and Query 3 is T-SQL) shows that they are the same:



So the lesson here is: remember to try constant value grouping.