Posts tagged ‘.NET’

I’m currently working on a project where there are some functional tests that require a SQL Server database. Before in the past I’ve always handled this by using Redgate’s excellent SQL Server tools to create a monolithic script that would deploy the DB Schema, and then another set of scripts to set up the data.  Then it’s pretty trivial to use OSQL.EXE to run the scripts and setup the database.

However, in this case, I’m constrained to use the VS2010 database project and TFS Build.  So, the trick for me became how to use TFS 2010 Team Build to deploy a fresh copy of the database before the functional tests are run.  After a bit of jiggery-pokery, here is what I ended up doing.  I’m sure that at some point in my future, I will have to do this again, and nothing helps my failing memory like writing it down.

First a rough overview:

  1. Declare some variables to hold the physical path of my .dbproj and the default data path for SQL Server.
  2. Convert the source code control path of my .dbproj to the physical path on disk.
  3. To help with debugging and diagnostics, write a build message with the location of the physical path of the .dbproj
  4. Add an MSBuild task to my workflow that would deploy the .dbproj.

Without further adieu, here is more details breakdown of the steps involved.

Declare Variables

So, first things first – declare the two variables I need to hold the physical path to the .dbproj file, and the directory for my SQL Server databases.  This should be pretty simple and straight forward (assuming that the POS that is the “Workflow Designer” isn’t crashing VS2010 constantly).

image

Once that is out of the way I scrolled down the pretty, crashy, workflow designer until I came across the Compile and Test sequence.  At the very start of it I added a sequence that I called Deploy Database.  Inside this sequence I added the following Team Foundation Build Activities:

ConvertWorkspaceItem

The point to this BuildActivity is to figure where the hell on the file system TFS put one of the files.  Pretty straight forward:

image

WriteBuildMessage

Always nice to have a message in your log file to help with troubleshooting.  Here’s what my WriteBuildMessage activity looks like.  Notice that the message makes use of the “DbProjectPath” variable that we set above in the ConvertWorkspaceItemActivity.

image

MSBuild

This the working part of the the sequence.  In here we use MSBuild to call the .dbproj and deploy a fresh copy of the database to SQL Server. Key properties to set:

  • CommandLineArguments : this contains the properties to pass on the command line when deploying.  You’ll want to provide these properties
    • /p:TargetDatabase=YOUR_DATABASE_NAME
    • /p:”DefaultDataPath=DIRECTORY_OF_DATABASE_FILES”
    • /p:”TargetConnectionString=YOUR_CONNECTION_STRING_FOR_THE_TARGET_DATABASE”
    • /p:DeployToDatabase=True
  • Configuration : just specify which configuration in the solution to use.
  • DisplayName : what ever you want, this is how the MSBuild activity will be displayed in your sequence
  • LogFile : the name of the log file for the deploy
  • OutDir : the output directory
  • Project : Notice that this is the value of DbProjectPath, which we set above in our ConvertWorkItem
  • RunCodeAnalysis : Set this to CodeAnalysisOption.Never.  Doesn’t make much sense to do code analysis on a database project.
  • Targets :

Here is what the properties look like for this particuar Build Activity:

image

Now all of this has to live somewhere.  You might want to have this live somewhere else depending on when or how you want the database to deploy.  In my case, as I wanted to deploy the database BEFORE my tests ran, I hunted through the workflow and found the sequence called Run Tests.  I modified one side of the If condition to include a new sequence call Deploy DB and Run Tests:image

Here is an overview of what my Deploy DB and Run Tests sequence looks like

image

 

After Thoughts

To be honest, I found the whole process annoying and awkward.  Sure, I didn’t have to edit a bunch of XML by hand, but the Workflow Designer in Visual Studio 2010 wasn’t exactly a joy to work with either.  I don’t know exactly what the problem was, but it kept crashing while I was trying to edit this Build Process Template. It was always the same error, an Out of Memory Exception.  On a Dell Latitude E6510 with 4GB of memory, this shouldn’t be happening.  As well, the whole editing process for the work flow was awkward at best.

As much as I dislike XML based build tools, at least text editors don’t get all crashy and such.  As well, I found the overall experience of trying to create and piece together the workflow for Team Build to be sluggish and tedious.  It’s great to have a GUI editor to hide the crummy XML, but honestly, I think the way FinalBuilder works is far superior to how VS2010 in terms of easy of use and readability(application crashes aside).

Next is to setup my Release build definition, and to tackle the issue of updated the version number in AssemblyInfo.cs and creating a zip file of all the deployment artifacts.  But first I’ve got to go and buy a bottle or two of Talisker to help numb the pain that will follow as I go done down that path.

I’ve spent a bit of my spare time in the past week looking at Windows Phone 7 from a developer’s point of view.  I’d have started sooner, but honestly, I didn’t see the point until there were actually devices that I could hold and use.  I know that in the U.S., some guys got developer phones from Microsoft, but I don’t think that anybody up here in Canada was that lucky.

So, over the past year or so I’ve been dabbling with Android and I actually like programming for Android.  The biggest issues I’ve run into with Android are my lack of Java skills – I keep doing things the C# way (you really don’t realize how handy Linq is until you don’t have it) and the fact that Android doesn’t have a decent UI designer.  But otherwise, I like Android.

So, I was curious what the developer experience was for WP7.  In a nutshell – it’s not bad, and in some ways better than that of Android.

Things I like about WP7 development:

  • Being a C# guy, it was pretty easy and fast for me to get going with WP7.  Of course, Novell now has MonoDroid which in theory should lessen the learning curve for a C# guy to create Android applications.
  • It’s nice to have good tooling to help with creating my UI’s.  Blend and Cider are pretty decent. Android does have DroidDraw, but I’ve never really found that tool to be good to work with.  Eclipse has some sort of an GUI designer thingy, but again, I’ve found it to be kind of lack-lustre at best.  That, and I don’t use Eclipse – I prefer IntelliJ.
  • The Emulator seems to start up faster to me that the Android emulator – but that could just be me.
  • The MVVM pattern.  I know the theory, and am now learning the more practical side of it.  Was worried that WP7 was going to decent into the path of darkness and pain that was/is Web Forms.
  • I think that the debugger integrates better with the WP7 emulator.  Not that, generally speaking, I spend a lot of time in the debugger, but when you need it, it does seem to be more natural to me.  Again, this could just be because by day I do a lot of C# development so I’m more used to the Microsoft tooling to begin with.

Some things I didn’t like about WP7 development:

  • You have to have Vista or Windows 7.  Yes, I know, XP is almost 10 years old, time to move on.  Call me an O/S curmudgeon.  I don’t mind Windows 7, but Vista sucks/sucked.
  • It seems like to build your apps, you have to use Visual Studio 2010.  Not a problem for a developer, but I’m old school when it comes to compiling applications, and your build server shouldn’t be tainted by your IDE.
  • I’m use to the relatively easy going Google marketplace and the fact I have numerous avenues available to me to distribute Android applications.  No such joy with WP7 apps.
  • Editing XAML by hand.  But, I suppose it’s no worse that the XML resource files that Android uses.
  • Not seeing a lot of projects whose code I can read.  Granted it’s still early, so hopefully that will change.  Or not.  .NET doesn’t seem to have the same OSS community spirit that Java does.

Microsoft has always tried to be pretty good to developers (sometimes to their own detriment), but I think Windows Phone 7 does have some things going for it, from a developer’s point of view anyway.  Here’s to hoping that strategy pays off – that cool apps will get written for WP7, and that it will be commercially viable.  Competition is good – it will keep Apple and Google on their toes.  Smile

If you happen to be a .NET type, knowledgeable/interested in MVC and Agile, QuestionMark is looking for .NET developers (F/T only, no contractors) here in Edmonton, Alberta.  Below is the job description.  If you’re interested, send your resume to Kaitlyn Lardin at QuestionMark (kaitlyn AT questionmark DOT com):

 

Senior Software Developer

Background

Questionmark is a company with a 20 year history recognised global presence in e-learning and assessment automation with software covering all aspects of this field, from authoring to delivery and reporting. Our software is used by over 3 million people in 15 different countries throughout the world. Questionmark is a fast-growing company, with a dedicated, passionate, and global workforce. We have offices in London, UK, Norwalk, CT and Tubize, Belgium. We care about the satisfaction of our employees and we reward them for meeting or exceeding expectations. The company promotes a relaxed, fun and highly productive approach to work. We have recently moved location to a vibrant office in the heart of downtown surrounded by software development companies.

Role of the Senior Developer

We are looking for a talented senior developer to join our development team in designing and creating the next generation of on-line assessment delivery software. This role will work closely with a Product Owner and other team members in a SCRUM environment, and be responsible for delivering potentially shippable functionality each Sprint. It also includes the mentoring of other team members through peer review. Our development team works in a Continuous Integration environment with automated builds and testing.

Essential skills:

· At least 5 years commercial experience development experience.

· You will be highly skilled in software development using our core technologies of C#, ASP.NET, XML, JavaScript, SQL Server and/or Oracle.

· Experience of jQuery very desirable

· Experience of working with .NET 2.0 or later

· Expertise in object oriented programming and relational databases

· Expertise in T-SQL and/or PL/SQL

· Good written and verbal communication. You must be able to write specifications

· Experience working in a SCRUM environment is desirable

Attributes of the Senior Software Developer:

The successful candidate will be highly skilled in software development using our core technologies, as above. You will be a self starting, self motivated individual who is enthusiastic and passionate about developing innovative software solutions.

Candidates must be eligible to work within Canada and relocate to Edmonton.

The package:

We offer excellent salary and benefits that include flexible working hours, starting 14 days annual leave, company bonus scheme, generous health coverage, and subsidized gym membership.

tumbleweedYeah, I’ve been kind of quiet as of late.  So quiet, I suspect that some people might be wondering if something happened.  I was a bit surprised to see that the last time I had blogged was after TechDays in Calgary.  Well, nothing significant has happened – just a bit of laziness augmented by a touch of tech-burnout compounded by the odd bit of single malt scotch.

So, now that one month is almost up on 2010, I figured that it was time to start blogging about something again.  The first trick to this, of course, was to figure out what I wanted to do in 2010.  It does seem like there will be a lot of interesting things, technically speaking, coming up this year.

A couple of new things I want to look at over the remaining 11 months:

Mobile development, particularly with a focus on Androidandroid-robot-logo1.  For the latter half of 2009 I have been dabbling in Android.  I believe that it’s time to go out on a bender, and in a drunken stupor get some embarrassing tattoo and join the Android Army.  So far, I’m at two out of three.  Not bad, huh?

AndroidArmy 

Ruby is another technology I’d like to explore – particularly Rails.  I can help but think that the opinionated view that Rails development has taken is the way to go for the bulk of web development.  A lot of websites are basically just forms over data, and Rails seems to address that concern rather well.  To bad nobody around here in Edmonton does much Rails development.

.NET 4.0 and ASP.NET MVC2.  I know there is a lot of debate between Web Forms and ASP.NET MVC.  Personally, I think MVC is the better way.  Probably best to keep abreast of what is going on in the ASP.NET MVC world.  And, of course, the DLR in .NET will come to maturity soon.  By maturity I mean widespread acceptance.  If this happens, then maybe developers won’t get so hung up on languages:  i.e. “I’m a C# guy so VB.NET sucks”.

And finally, a guy needs hobbies.  Now granted, my past hobbies of alcohol and guns (no, not together at the same time) have served me well for the past 20 years or so. However, they are hard hobbies to share with my sons at this point in time.  So, at the start of winter I expanded the geek factor of my sons (and myself) by getting back into Warhammer.  Now the last time I played was about 20 years ago, with the 3rd edition rules.  In fact, I still have some of the books in my basement from back then.  Anyway, picked up The Battle for Skull Pass boxed set.  My son rather likes the Dwarfs.  I suspect it’s because he’s similar in stature/height to the stunties.  Myself, while I find the Greenskins amusing, I suspect I might have to move on and get serious with Dark Elves.

Anyway, enough for tonight.

Out of intellectual curiosity, I sparked up MonoDevelop and decided to see what would happen when I tried to compile the ASP.NET MVC source code. I figured that it would Just Work.  After all, I can use the .NET compiled assembly with no problems on Mono, so there really shouldn’t be any problems trying to compile the code.  Bad news is that there is one minor glitch.  Good news is the glitch is easy to work around and has already been fixed so it shouldn’t be a problem for future version of Mono.

When you compile, here is what you get:

Compilation failed: 1 error(s), 0 warnings

/home/tom/Projects/MVC-MS-Pl-original/MVC-MS-Pl/Mvc/FormCollection.cs(25,6): error CS0246: The type or namespace name `FormCollectionBinder’ could not be found. Are you missing a using directive or an assembly reference?

Build complete — 1 error, 0 warnings

So, this kind of surprised me.  Looking at the code, I did see the FormCollectionBinder in the code, it’s an embedded class within System.Web.Mvc.FormCollection, check out lines 68-88 below:

   1: /* **************************************************************************** 
   2:  * 
   3:  * Copyright (c) Microsoft Corporation. All rights reserved. 
   4:  * 
   5:  * This software is subject to the Microsoft Public License (Ms-PL).  
   6:  * A copy of the license can be found in the license.htm file included  
   7:  * in this distribution. 
   8:  * 
   9:  * You must not remove this notice, or any other, from this software. 
  10:  * 
  11:  * ***************************************************************************/ 
  12:  
  13: namespace System.Web.Mvc { 
  14:     using System; 
  15:     using System.Collections.Generic; 
  16:     using System.Collections.Specialized; 
  17:     using System.Diagnostics.CodeAnalysis; 
  18:     using System.Globalization; 
  19:     using System.Web.Mvc.Resources; 
  20:  
  21:     [SuppressMessage("Microsoft.Usage", "CA2237:MarkISerializableTypesWithSerializable", 
  22:         Justification = "It is not anticipated that users will need to serialize this type.")] 
  23:     [SuppressMessage("Microsoft.Design", "CA1035:ICollectionImplementationsHaveStronglyTypedMembers", 
  24:         Justification = "It is not anticipated that users will call FormCollection.CopyTo().")] 
  25:     [FormCollectionBinder] 
  26:     public class FormCollection : NameValueCollection { 
  27:  
  28:         public FormCollection() { 
  29:         } 
  30:  
  31:         public FormCollection(NameValueCollection collection) { 
  32:             if (collection == null) { 
  33:                 throw new ArgumentNullException("collection"); 
  34:             } 
  35:  
  36:             Add(collection); 
  37:         } 
  38:  
  39:         public IDictionary<string, ValueProviderResult> ToValueProvider() { 
  40:             CultureInfo currentCulture = CultureInfo.CurrentCulture; 
  41:  
  42:             Dictionary<string, ValueProviderResult> dict = new Dictionary<string, ValueProviderResult>(StringComparer.OrdinalIgnoreCase); 
  43:             string[] keys = AllKeys; 
  44:             foreach (string key in keys) { 
  45:                 string[] rawValue = GetValues(key); 
  46:                 string attemptedValue = this[key]; 
  47:                 ValueProviderResult vpResult = new ValueProviderResult(rawValue, attemptedValue, currentCulture); 
  48:                 dict[key] = vpResult; 
  49:             } 
  50:  
  51:             return dict; 
  52:         } 
  53:  
  54:         public virtual ValueProviderResult GetValue(string name) { 
  55:             if (String.IsNullOrEmpty(name)) { 
  56:                 throw new ArgumentException(MvcResources.Common_NullOrEmpty, "name"); 
  57:             } 
  58:  
  59:             string[] rawValue = GetValues(name); 
  60:             if (rawValue == null) { 
  61:                 return null; 
  62:             } 
  63:  
  64:             string attemptedValue = this[name]; 
  65:             return new ValueProviderResult(rawValue, attemptedValue, CultureInfo.CurrentCulture); 
  66:         } 
  67:  
  68:         private sealed class FormCollectionBinderAttribute : CustomModelBinderAttribute { 
  69:  
  70:             // since the FormCollectionModelBinder.BindModel() method is thread-safe, we only need to keep 
  71:             // a single instance of the binder around 
  72:             private static readonly FormCollectionModelBinder _binder = new FormCollectionModelBinder(); 
  73:  
  74:             public override IModelBinder GetBinder() { 
  75:                 return _binder; 
  76:             } 
  77:  
  78:             // this class is used for generating a FormCollection object 
  79:             private sealed class FormCollectionModelBinder : IModelBinder { 
  80:                 public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { 
  81:                     if (controllerContext == null) { 
  82:                         throw new ArgumentNullException("controllerContext"); 
  83:                     } 
  84:  
  85:                     return new FormCollection(controllerContext.HttpContext.Request.Form); 
  86:                 } 
  87:             } 
  88:         } 
  89:  
  90:     } 
  91: }

The version of Mono 2.4.3 I have doesn’t compile the class FormCollection because the FormCollectionBinderAttribute is inside the FormCollection class.  This is the bug, and it has since been fixed.  Easy ways to get around this:

  1. Just use the binary assembly from Microsoft for ASP.NET MVC.
  2. Build your own Mono with the fix included
  3. Move the code for FormCollectionBinderAttribute class outside of the code for the FormCollection class.

One of the nice things about Dependency Injection is that it can really help write a more flexible, modular application.  These days, it seems that there is no shortage of choice in the .NET community when it comes to IoC frameworks:

Ironically, when you first start using an IoC framework, you might find that in trying to make a loosely-coupled, modular, application you end up shackling yourself to the framework you’re using for IoC.

For example, you start off using your own homegrown IoC framework, and then decide at some point in the future to use a different framework, like say StructureMap.  Going through your codebase to make these changes can be quite the exercise in pain.

There are a couple of ways to isolate yourself from this kind of situation.  I won’t get into all of them but instead will focus on the Common Service Locator. What is Common Service Locator?  Well, allow me to cut and paste some text from the web site:

"The Common Service Locator library contains a shared interface for service location which application and framework developers can reference. The library provides an abstraction over IoC containers and service locators. Using the library allows an application to indirectly access the capabilities without relying on hard references. The hope is that using this library, third-party applications and frameworks can begin to leverage IoC/Service Location without tying themselves down to a specific implementation.

Blah blah blah – so what does all that mean?  Well, in my own words, CSL is basically a wrapper around your IoC container which separates how you  initialize/configure your IoC container from how you use it.  This separation allows you to use your IoC container without knowing anything about it.

This separation is achieved by use of adapters for the particular IoC container that you want to use.  These adapters are what do the dirty work of finding the service you need, in their own special way and totally transparent from your application code.  Currently, the Common Service Locator has adapters for StructureMap, Castle Windows, Unity, Spring.NET, and autofac.

Now, allow me an example of using the Common Service Locator with StructureMap. There is no special reason as to why StructureMap – it just happens to be what I find myself using these days.

Now, say I use the the following registry to configure StructureMap:

   1: public class DefaultStructureMapRegistry: Registry
   2: {
   3:     public DefaultStructureMapRegistry()
   4:     {
   5:         ForRequestedType<IDb4oConfiguration>()
   6:             .TheDefaultIsConcreteType<SimpleDb4oConfiguration>();
   7:     }
   8: }

In a nutshell this says that every time StructureMap is asked to provided an object of type IDb4oConfiguration, it should instantiate a SimpleDb4oConfiguration object and return that.  So, to get an instance of IDb4oConfiguration with StructureMap, I would do something like this:

   1: var db4oConfig = ObjectFactory.GetInstance<IDb4oConfiguration>();

Pretty simple, but it does kind of tightly couples me to StructureMap.  If I need/feel like/am forced at gunpoint to change my IoC container to something that is Not StructureMap, you can bet that there will be much wailing and gnashing of teeth on my part as I hunt through my code to make these changes.

Now enter the Common Service Locator.  First, let’s take a peek at some interfaces for CSL.  First an interface:

   1: namespace Microsoft.Practices.ServiceLocation
   2: {
   3:     public interface IServiceLocator : IServiceProvider
   4:     {
   5:         object GetInstance(Type serviceType);
   6:         object GetInstance(Type serviceType, string key);
   7:         IEnumerable<object> GetAllInstances(Type serviceType);
   8:         TService GetInstance<TService>();
   9:         TService GetInstance<TService>(string key);
  10:         IEnumerable<TService> GetAllInstances<TService>();
  11:     }
  12: }

The IServiceLocator is an interface that your application will use when it requests something from your IoC container.

Another thing that CSL provides is a static class that your application would use to use a current IServiceLocator to request services.  That static class looks something like:

   1: namespace Microsoft.Practices.ServiceLocation
   2: {
   3:     public static class ServiceLocator
   4:     {
   5:         public static IServiceLocator Current { get; }
   6:         public static void SetLocatorProvider(ServiceLocatorProvider newProvider) {};
   7:     }
   8: }

So, now lets see how we would request the default implementation of the IDb4oConfiguration service using CSL.  First, we would initialize CSL:

   1: var registry = new DefaultStructureMapRegistry();
   2: var container = new global::StructureMap.Container(registry);
   3: var smServiceLocator = new StructureMapServiceLocator(container);
   4: ServiceLocator.SetLocatorProvider(() => smServiceLocator );

What is going on here? Allow me to provide a quick line by line explanation:

Line 1 we instantiate a new StructureMap registry.  We then feed that registry to a StructureMap container in line 2.  With line 3, we see that StructureMap container is then fed to the StructureMapServiceLocator, which is the SM adapter for the Common Service Locator.  Finally, with line 4 we provide a lambda that CSL will use to fulfill future requests for services.

Now when our application wants to get an instance of IDb4oConfiguration it just politely asks CSL:

   1: var db4oConfig = ServiceLocator.Current.GetService<IDb4oConfiguration>();

Pretty simple and clean, eh?  Now, when radical group the Foundation for Unity as the Dominate IoC Container sneaks into your cube and forces you at the point of a nerf gun to switch to Unity, you can do so with minimal disruption to your application. With a properly layered application, it would be as simple as coding a new UnityConfiguration layer and then using that instead of your StructureMapConfiguration layer on application startup.

Now, granted this is pretty trivialized example.  There are other ways to solve this problem, but CSL does seem to take are of the grunt work for you so that you can just get going with things.

Lately I’ve been experimenting with TypeMock Isolator,  and it’s new AAA syntax.  For the past two years I’ve been a diehard Rhino.Mocks kind of guy, but figured that it’s time to check out other tools.  Anyway, I had a situation where a unit test of mine was failing when I ran it with TestDriven.NET, but would pass when I ran it using the unit test runner in Resharper 4.1.

Usually when I develop, I write individual tests and then run individually with TestDriven.NET and collectively with Resharper.  In this case, as I was writing one unit test, it kept failing with TestDriven.NET.  At first I thought it was just me being stupid (always a good place to start), and then I was worried that perhaps the documentation for TypeMock was to blame.  So, I sent a email to Avi at TypeMock, mostly expecting confirmation of my stupidity.

Turns out the problem in this case was pretty obscure one (to me).  At home, I do my development in a VM running Windows 2008 64 bit.  When Resharper runs your unit tests, it does in a 32 bit process.  TD.NET, on a 64bit OS,  runs as a 64 bit process.  If you get TD.NET to run as a 32 bit process, then your tests will run fine under TD.NET.

To do so, from the Visual Studio 2008 Command Prompt, change to the directory that you have TD.NET installed in.  Then use corflags:

corflags /32bit+ ProcessInvocation.exe

Note that it’s probably best to do this when logged in as the Administrator.

I will say that I was happy with the support I got from the guys (Avi, Gil and Ohad) at TypeMock.  Given the fact that we’re about a half a world apart (western Canada vs. Isreal), they provided prompt, excellent support.  My thanks to them.

Lately I’ve been experimenting with TypeMock Isolator,  and it’s new AAA syntax.  For the past two years I’ve been a diehard Rhino.Mocks kind of guy, but figured that it’s time to check out other tools.  Anyway, I had a situation where a unit test of mine was failing when I ran it with TestDriven.NET, but would pass when I ran it using the unit test runner in Resharper 4.1.

Usually when I develop, I write individual tests and then run individually with TestDriven.NET and collectively with Resharper.  In this case, as I was writing one unit test, it kept failing with TestDriven.NET.  At first I thought it was just me being stupid (always a good place to start), and then I was worried that perhaps the documentation for TypeMock was to blame.  So, I sent a email to Avi at TypeMock, mostly expecting confirmation of my stupidity.

Turns out the problem in this case was pretty obscure one (to me).  At home, I do my development in a VM running Windows 2008 64 bit.  When Resharper runs your unit tests, it does in a 32 bit process.  TD.NET, on a 64bit OS,  runs as a 64 bit process.  If you get TD.NET to run as a 32 bit process, then your tests will run fine under TD.NET.

To do so, from the Visual Studio 2008 Command Prompt, change to the directory that you have TD.NET installed in.  Then use corflags:

corflags /32bit+ ProcessInvocation.exe

Note that it’s probably best to do this when logged in as the Administrator.

I will say that I was happy with the support I got from the guys (Avi, Gil and Ohad) at TypeMock.  Given the fact that we’re about a half a world apart (western Canada vs. Isreal), they provided prompt, excellent support.  My thanks to them.

I know it’s hard to beat my shocking announcement from a couple of days ago, but I feel that this one is even more important:  Mono 2.0 has been released.  Read the full details, go forth, and code.

As I was driving home today, I couldn’t help notice something.  Microsoft’s ASP.NET MVC framework is still in beta, and was only announced last October.  To my knowledge, there are currently three projects in the Edmonton area based off this framework.

Castle Monorail has been around for much longer, three years or so?  It’s still listed as a release candidate on it’s website, but I’d say Monorail is suitable for production.  Currently, I am not aware of any projects in the Edmonton that are based off this framework.

I guess this is anecdotal evidence that you won’t get fired for sticking with Microsoft. :)

The two frameworks have quite a few similarities.  IIRC, in Austin last fall Scott Guthrie did mention that the ASP.NET MVC framework was influenced to some degree by Monorail.

Regardless, it’s good news.  Personally, I like both frameworks, and would prefer either of them to Web Forms.  YMMV.