Archive for May, 2008
DM-Paperclip released!
Title: DM-Paperclip – Paperclip for DataMapper
Tonight I posted the official release of the DataMapper port of Paperclip that I’ve been slowly working on for while. Paperclip is a Rails plugin by Thoughtbot which makes it really easy to attach files to your models. I’ve been interested in doing some Merb and DataMapper projects, and one of them was going to make use of Paperclip, so I dived into making a port of it.
DM-Paperclip works exactly like the existing Paperclip plugin, with the same options, features, validations, and it even uses the same tests! Rather than rewrite Paperclip, I instead just went in and changed what was necessary for compatibility with DataMapper, slowly working on the number of passing tests.
The module is currently targeting DataMapper 0.9, which is still unreleased. The main reason is because 0.9 is quite different than 0.3, and the current source includes a few fixes and features that were added while I was working on the port. It is also intended to be used with Merb, as the paths make use of Merb.root and Merb.env. It should work with any of the 0.9.x Merb releases, though with 0.9.3 recently being released, that is the build I’ve been using it against.
Last night, I finally got the last couple of tests passing, updated it to be in sync with Paperclip 2.1.2, polished some documentation, and now it is ready for mass consumption! Even managed to get a mention on Thoughtbot’s blog.
You can browse the source tree here: http://github.com/krobertson/dm-paperclip
Download the source yourself:
git clone git://github.com/krobertson/dm-paperclip.git
Install it as a gem:
sudo gem install dm-paperclip
For more information, check out some of the documentation. And of course, check out the original Paperclip.
Hacking ReSharper + NUnit + Benchmarking
This may seem a little bit off the wall, but one thing I’ve been starting to do lately is instead of littering my Projects directory with a bunch of ConsoleApplicationN folders, I’ve started using the unit test runner within ReSharper to fire up quick little sample things I need. Most often, they’re simple things where I just need to see the output of a particular method, or quickly be able to debug into it with some fixed inputs, etc. It is not really what unit testing is for, but I find it to be the simplest way to execute something without having to launch another Visual Studio instance or open Snippet Compiler (nothing against it, but I prefer VS+ReSharper).
Though a few days ago, I found myself wanting to benchmark some code I’d written. And I’ve encountered this a couple of times before… I run some unit tests and what not and I just want to know how long did it take to run. Often when running the entire test suite on the REST API in Community Server, I walk away for a few minutes (its like 800+ tests), so sometimes curious how long particular ones took when I come back. In this case, I refactored a method and wanted to see the improvement (ie, run it a million times to get a discernible difference).
ReSharper’s unit test runner for NUnit doesn’t support this out of the box, but two of the greatest gifts to .NET has to be Lutz Roeder’s Reflector (which we all know and love) and the File Disassembler from Denis Bauer came to the rescue.
Friday afternoon, decided to dive in to do a little hacking. I happened to notice that the JetBrains.ReSharper.UnitTestProvider.nUnit.dll was not obfuscated when reflecting into it. Then it dawned on me: disassemble it, make my own assembly, and add basic run time output to it!
First, run the File Disassembly on the DLL. Open it up in Visual Studio (convert the project if needed), and then try to compile. You’ll likely get a number of errors because it tends to name some variables with a dollar sign ($). Just take out the dollar sign and you’re good.
Second, do a find and replace on the namespace to be your own and change the project output assembly to be your own. Then open up the NUnitTestProvider class and change the value of the NUNIT_ID and the ID property on the class (I used “Invalid nUnit”). You’ll also want to open the ProductInformation class and update some of the strings. This may not be necessary, but I didn’t want any conflicts on anything it would look up.
Now to use your own assembly, you need to go the ReSharper directory and create a PlugIns directory, and then a subdirectory to that (again, I chose “Invalid nUnit”) and put your DLL in there. You also need to create an XML file with the same name as the dll and paste this:
<?xml version="1.0"?>
<doc>
<assembly>
<name>InvalidLogic.UnitTestProvider.nUnit</name>
</assembly>
<members>
<member name="T:InvalidLogic.ProductInformation">
<summary>
Specifies product information
</summary>
</member>
</members>
</doc>
Replace the assembly/name and the member:name with your own namespaces and such.
Now when you launch Visual Studio and go to the ReSharper Options / Unit Testing, you should see your provider.

But now, we need to add benchmarking!
This is admittedly very simplistic benchmarking, but just wanted to know some basic information about how long it took to run. Within your disassembled project, find the NUnitTaskRunner, and in the private static Execute method, update the main try block to the following:
long beginTicks = -1;
long endTicks = -1;
try
{
beginTicks = DateTime.Now.Ticks;
TaskExecutor.Invoke(instance, testMI);
endTicks = DateTime.Now.Ticks;
}
catch (TargetInvocationException e)
...
Then at the end, before it returns, add the following:
if(beginTicks > -1 && endTicks > beginTicks)
server.TaskOutput(test, "Processing Time : " +
new TimeSpan(endTicks - beginTicks).TotalSeconds +
" seconds", TaskOutputType.STDOUT);
return TaskResult.Success;
Compile, update the PlugIns folder, relaunch Visual Studio, and you should be ready to go!

Given that I had to disassemble one of their assemblies, I am not going to be distributing my change at all. I think I’d get in some legal trouble distributing a reverse engineered library. Though I figure sharing this information isn’t harmful. I’m sure they’d like to see more unit test providers for it, and I’m encouraging the use and enjoyment of ReSharper.
Move to Mac is complete
In late December is when I finally took the plunge and bought my first Mac. Since I did most of my work from my desktop, a Mac Pro made better sense. My laptop was much more of an after-hours machine that I used from the living room at night, or on when I travel (which isn’t that much).
I had fallen in love with the Mac, and it really helped me re-realize my love for the command line from my old Linux days. Shortly after getting into Ruby, I had paved my laptop to put Ubuntu on it and had started doing my Ruby coding on it with Gedit. However, it left me with multiple platforms, different programs available for each, and unable to do .NET work on my laptop, since my VMware Workstation license was only for Windows.
So last month, shortly before my trip to TelligentHQ for the Community Server 2008 Launch Party, I decided to finally purchase a MacBook Pro… and I couldn’t be happier.
I ended up buying a slightly used one (ie, <6 months old) off Ebay rather than buy a new one. I had been watching Ebay for a while and finally found the deal I was waiting for. 17″, high-resolution, 4gb ram, 7200rpm hard drive. Near top specs for a good chunk under retail. Additionally, since it wasn’t the newest model, it was cheaper than a new model one with the same specs. I figure with the previous model, all I’m missing is an LED display, the Penren (which maybe adds a few MB CPU cache), and multi-touch. Overall, it still a screaming machine and will last just as long, but saved some good change.
I had been milling over the 15″ over the 17″ for a while, but in the end, I am very happy with the 17″. It is no where near as bulky as I expected, it is actually shorter than my 15″ Thinkpad T60 since Apple makes much better use of the space, and at 1920×1200, the display is magnificent.
Now I am working on my multi-Mac bliss. Some things are a true gem… TextMate is love. I use it for everything. Even drafting up blog posts (like this one). Syntonization with .Mac rocks, as I can share mail account configurations, 1Password entries, Transmit favorites, and more. Having SSH in the OS is revolutionary. With one secure port open, I can tunnel VNC, access command line on my desktop, and even access my files (SFTP or sshfs with MacFUSE).
Even better, can use VMware Fusion on both and have the exact same .NET development environment on both. Development with a VM is so much better. I can have one pristine environment, easily create/manage snapshots and multiple backups of it. If Visual Studio gets testy, can easily reboot without having to close out everything.
Overall, I’ve been very pleased with my move to the Mac. Almost all my everyday programs have been replaced, I’ve gotten into broadening my horizons, and even find developing on .NET better as a result. I think the next stage would be getting a nice development story with TextMate + Mono… ohh, one can dream, can’t I?
How to properly access ASP.NET profile defaults without a profile
Recently, we stumbled upon this indiscrete bug in Community Server with its handling of some things in a user’s profile. While debugging, couldn’t find much about it on Google, so I thought I’d write up a quick explanation so it might help spare some poor sole from losing hair over it.
In summary of it, there were some edge cases where a user record could exist, but they didn’t have a profile record yet (created externally, or for me, created via REST API with none of the profile options set). When a profile record isn’t found, then CS just reads the default values as defined in your web.config.
The documentation on how to do this is quite slim, so in our profile handling, we basically had this method:
public override object GetPropertyValue(string propertyKey)
{
return ProfileBase.Properties[propertyKey].DefaultValue;
}
DefaultValue returns an object, and as the documentation states:
An object containing the default value of the SettingsProperty object.
So when you had a profile entry as so:
<properties> ... <add name = "timezone" type = "System.Double" defaultValue="0" /> ... </properties>
You might assume that when you get the timezone default value, you get a double back. Right? Wrong! Even though DefaultValue returns an object, the actual return value is always a string. The documentation isn’t misleading, it is just rather bare. In our case, we expected it to be a double and would get an invalid casting exception (the bug in CS wasn’t for the timezone setting, it was a different one).
So how do you properly read the default value and get the expected type? Documentation on this is bare as well, but after sifting through Reflector some, found that other places DefaultValue is accessed also make use of a SettingsPropertyValue class. Aha! The SettingsPropertyValue class is used to perform the serialization on the default value. So for the above, you could quickly fix it like so:
public override object GetPropertyValue(string propertyKey)
{
return new SettingsPropertyValue(ProfileBase.Properties[propertyKey]).PropertyValue;
}
Wha-la! Magic! Also to help illustrate it better, can throw this snippet into a .aspx page and run it in your browser. It will spit out a quick list of all your profile properties and their values/type using both methods.
<%@ Page Language="C#" AutoEventWireup="true" %>
<script runat="server">
public void Page_Load(object sender, EventArgs e)
{
Response.Write("<table border='1' cellpadding='3'><tr><th>Name</th><th>Type</th><th>Default Value</th><th>Default Value Type</th><th>SettingsPropertyValue</th><th>SettingsPropertyValue Type</tr>");
foreach (SettingsProperty p in System.Web.Profile.ProfileBase.Properties)
{
SettingsPropertyValue spv = new SettingsPropertyValue(p);
Response.Write( string.Format("<tr><td>{0}</td><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td><td>{5}</td></tr>", p.Name, p.PropertyType.FullName, p.DefaultValue, p.DefaultValue.GetType().FullName, spv.PropertyValue, spv.PropertyValue.GetType().FullName));
}
Response.Write("</table>");
}
</script>
If you encounter something similar, may want to take into account how often you might need to access the value, since in the above, it would de-serialize the value each time. In CS, we actually changed it to lazy-load them and store the value in a dictionary. We also cleaned up some of the profile code so it was more streamlined and could handle the event it was a string (or something else, such as converting an int timezone into a double).