Thursday, August 19, 2010

Building a Silverlight application under CruiseControl.NET on a 64 bit platform

Yesterday a colleague of mine was trying to get his Silverlight 3 building on our continuous integration (CI) server and was getting an error, 'Silverlight 3 SDK is not installed', even though the SDK was installed on that machine.

It turns out that this is a common error when trying to compile a Silverlight app on a 64 bit platform. Unfortunately most of the solutions out there involved manually editing the appropriate Silverlight .target file to change paths to the SDK.

Another solution was to set the 'MSBuild Platform' to x86 under TFS 2010 (http://blog.benday.com/archive/2010/04/20/23272.aspx). This was a cleaner solution, but not much use to us as we use CruiseControl.NET rather than TFS.

In the end the solution was fairly simple. All we had to do was call the 32bit .NET 4.0 version of msbuild which resides in C:\Windows\Microsoft.NET\Framework\v4.0.30319 rather than the default 64 bit version.

We ended up removing the <msbuild> task from our nant build file, which was calling the 64 bit version, and replaced it with an <exec> task pointing to the appropriate version of msbuild.

Monday, July 12, 2010

ASP.NET MVC2 and the Enterprise Library Security Block Authorization Provider

When I first started with ASP.NET 2.0 I was intrigued by the built-in support for users and roles via the Membership Providers. Unfortunately I quickly found limitations for its use mainly due to the way that I like to structure permissions in my applications.

I overcame some of these limitations by using the Enterprise Library Security block which allowed me to set granular permissions and then roll them up into groups of permissions which map to individual roles.

I recently switched over from ASP.NET, using the MVP pattern, to ASP.NET MVC2 and again found the the way roles are mapped to be too limiting. Therefore I decided to implement my own custom AuthorizeAttribute to check for specific authorization rules using the Enterprise Library Security block.

This article assumes that you know how to use Membership and Role providers in ASP.NET and that we have a role called Administrators already configured. If you aren't familiar with these I'd suggest looking at the following article:

Examining ASP.NET's Membership, Roles, and Profile

I also assume that you know how to use the MVC2 authorization model.

The first thing to do is add a reference to the following assemblies in your MVC project:

Microsoft.Practices.EnterpriseLibrary.Security
Microsoft.Practices.EnterpriseLibrary.Security.Configuration
Microsoft.Practices.EnterpriseLibrary.Common

Next we'll have to configure the security block in the web.config. I'm also going to create a authorization rule which maps a "Can Manage Users" permission into the Administrators role.
<configuration>
<configSections>
<section name="securityConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Security.Configuration.SecuritySettings, Microsoft.Practices.EnterpriseLibrary.Security, Version=4.1.0.0" />
...
</configSections>
<securityConfiguration defaultAuthorizationInstance="RuleProvider" defaultSecurityCacheInstance="">
<authorizationProviders>
<add type="Microsoft.Practices.EnterpriseLibrary.Security.AuthorizationRuleProvider, Microsoft.Practices.EnterpriseLibrary.Security" name="RuleProvider">
<rules>
<add expression="R:Administrators" name="Can See Admin Menu" />
</rules>
</add>
</authorizationProviders>
</securityConfiguration>

Next we have to create our custom AuthorizeAttribute. This will allow us to check against the Enterprise Library Security block. We can do this by inheriting from the standard AuthorizeAttribute and overriding the AuthorizeCore method.
  public class AuthorizeRule : AuthorizeAttribute
{
public string Rule { get; set; }

protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (string.IsNullOrEmpty(Rule))
{
throw new InvalidOperationException("Rule not specified");
}

if (!httpContext.User.Identity.IsAuthenticated)
{
return false;
}

IAuthorizationProvider auth = AuthorizationFactory.GetAuthorizationProvider();
return auth.Authorize(httpContext.User, Rule);
}
}

Finally we mark up the appropriate controller method that you want to secure just as we would using the AuthorizeAttribute.
[AuthorizeRule(Rule = "Can Manage Users")]
public void Index()
{
...
}

It's as easy as that.

Friday, July 2, 2010

When should software be rewritten

Over the last 14 years of my professional software development career, I have often heard developers complain about their existing code-base (including me). These complaints are generally along the same themes; how it has become difficult to maintain; that the code has become a big ball of mud; that changing code causes ripple effects; that no-one likes to touch module X because its so brittle; it takes new developers a long time to get up to speed with the code etc etc.

Normally the team consensus is that the product should be rewritten from the ground up. The idea is that this will sort out all of the design issues that are in the current version, it'll be more maintainable & more stable.

So the team embarks on this quest all the while management still wants new features and bug fixes to the existing version. This causes the original code-base to become a moving target causing the rewrite to take longer. This also ties up resources that could be working on new features, moving the product forward and adding value to the business.

In my experience the only time to rewrite a code-base is when moving to a new platform or technology. For example moving from Winforms to WPF. A rewrite is normally a lengthy and costly affair which rarely ends up with the clean design that was sought. New bugs are introduced which aren't covered by existing regression tests.

Rather than rewriting the entire application, the strategy I would recommend is to refactor it.

To get the most benefit from refactoring a code base, you'll need to increase testability. This will involve moving to a more loosely coupled design. I've chosen to use Behaviour Driven Design (BDD) which is an extension of Test Driven Design (TDD). Though you could bolt on tests after code but I wouldn't recommend that for many reasons which I won't go into here.

I have found that provided your code is loosely coupled and designed for testability, you are able to move towards an incremental design model in which developers can feel confident making changes and with greater speed.

So what happens if you have a tightly coupled application which might be tested by a QA team but doesn't have any unit tests?

Over the next few articles I'll be outlining some strategies for refactoring your legacy ASP.NET apps

Wednesday, March 3, 2010

Calculating when a MultiScaleImage has reached 1:1 scale of the original image.

For a project I am working on I'm using a Silverlight MultiScaleImage to display an exceptionally large tiled image. As part of this I wanted to enforce a maximum zoom when the image was displayed at 1:1 scale. After some Googling I wasn't able to find any immediate solutions so I had to tackle it myself.

The solution I came up with in the end was fairly simple. I already had the original image width in pixels, so all I had to do was to compare that against MultiScaleImage.ActualWidth divided by MultiScaleImage.ViewportWidth before zooming.

e.g.

if(_msi.ActualWidth / _msi.ViewportWidth > OriginalImageWidth)
{
return;
}
_msi.ZoomAboutLogicalPoint(...

Note: I'm still pretty new to the MultiScaleImage so if there's a better way feel free to comment.

Friday, January 15, 2010

Migrating relational data into a SQL Server XML datatype column

Recently I needed to take the data from a SQL Server table, convert it into XML and insert it into an xml datatype column of a related table. In the past I would have used a scripting language such as Perl to achieve this, but since SQL Server 05/08 has native XML support I decided to give that a go.  I did this because I thought it would be more efficient, and less error prone, to do everything at the database level. It turns out that it was easier than I thought.

I was already familiar with SELECT .. FOR XML syntax from previous experiments with SQL Server's XML functionality, so was able to convert the existing table data to XML as follows:
SELECT part_id, part_name, part_description
FROM parts FOR XML AUTO, ELEMENTS
This generated the following XML:
<parts>
<part_id>4</part_id> 
  <part_name>Widget</part_name>
  <part_description>Widget to do something</part_description>
</parts>
Note: The XML generated by FOR XML AUTO was good enough for my purposes. If you need more control over the XML output you can use FOR XML EXPLICIT instead.

The next step was to insert this into the appropriate row of a related table. I achieved this using a sub-query on an UPDATE.  The resulting SQL was as follows:
UPDATE orders SET bio_sample_aliquot_info = ( 
SELECT part_id, part_name, part_description FROM parts 
WHERE order.id = part.order_id FOR XML AUTO, ELEMENTS)
FROM orders
Normally I don't like using sub-queries as they can be inefficient, but this ended up been fast enough for my needs.

After running the above query I had the XML I wanted in the appropriate XML datatype rows of the related table.

Note: I've changed all of the names of the tables and columns in the example above.  Also I tested this on SQL Server 08, but not 05.