Monday, August 04, 2008

Binding... and IList<T> does not inherit from IList.

A note to myself, and to others who may find it useful:

Use System.Collections.ObjectModel.Collection<T> (or a subclass) as the return type for properties exposing collections of related items on your presentation model classes if you intend to bind to the relationships with Windows Forms BindingSources.

Collection<T> appears to be the lowest-level type in Framework 3.5 that provides both the non-generic IList implementation as required by the binding system and also provides strongly-typed programmatic access to the elements of the collection. It is used as the base for BindingList<T>, ObservableCollection<T> and many others and you can easily inherit from it yourself.

Using a return type of IList<T> or ICollection<T> instead, which may be preferred for being less concrete, is not sufficient as neither of these inherit from the non-generic IList and will fail to bind correctly (sometimes throwing exceptions) at run-time when the parent list of the bound relationship is empty.

 Saturday, May 24, 2008

Using IDisposable and Lambdas for temporary values

What follows is some code I wrote last week that I couldn't find anywhere else and I thought was useful. First, is a test method demonstrating my use case, followed by the implementation of the TemporaryValue classes to fulfil the requirement.

The property get lambda expression can be an instance or static property as long as it is read-write. In this implementation there is no exception handling and no multithreading considerations.

[TestMethod]
public void Original_property_value_should_be_restored_after_temporary_value_block()
{
    const string OriginalValue = "_original_value_";
    const string NewValue = "_new_value_";
    var f = new Foo {Bar = OriginalValue};

    Assert.AreSame(OriginalValue, f.Bar);

    using (TemporaryValue.For(() => f.Bar, NewValue))
    {
        Assert.AreSame(NewValue, f.Bar);
    }

    Assert.AreSame(OriginalValue, f.Bar);
}

public static class TemporaryValue 

    public static TemporaryValue For(Expression<Func> propertyGet, TValue newValue) 
    { 
        return new TemporaryValue(propertyGet, newValue); 
    } 

 
public class TemporaryValue : IDisposable 

    private PropertyInfo _propertyInfo; 
    private object _target; 
    private TValue _original; 
 
    public TemporaryValue(Expression<Func> propertyGet, TValue newValue) 
    { 
        var memberExpression = (MemberExpression)propertyGet.Body; 
        _propertyInfo = (PropertyInfo)memberExpression.Member; 
 
        var targetExpression = memberExpression.Expression
        if (null != targetExpression) 
        { 
            _target = Expression.Lambda<Func<object>>(targetExpression).Compile().Invoke(); 
        } 
 
        _original = propertyGet.Compile().Invoke(); 
        Set(newValue); 
    } 
 
    private void Set(TValue value) 
    { 
        _propertyInfo.SetValue(_target, value, null); 
    } 
 
    public void Dispose() 
    { 
        if (null != _propertyInfo) 
        { 
            Set(_original); 
            _propertyInfo = null
            _target = null
            _original = default(TValue); 
        } 
    } 
}

After learning to manipulate lambda expressions in this way I decided it would be a good idea to use a similar approach to remove the need for string literals in an INotifyPropertyChanged implementation. Unfortunately, while I was offline for a few days, Paul got a head start.

 Friday, December 21, 2007

Lambda for Regex

A few weeks ago I was trying to put together a quick regular expression for converting an entire English sentence into Pascal (or Headed Camel) Case. What would have been rather trivial in Perl was a little ugly in C#.

Tonight, in a typical midnight haze, I realised I could use a lambda expression to tidy it up a bit. Here is the result, short and simple, presented in unit test form:

[TestMethod]
public void ShouldRemoveSpacesAndCapitaliseWords()
{
   const string original = "Should remove spaces and capitalise words";
   const string expected = "ShouldRemoveSpacesAndCapitaliseWords"

   Regex rx = new Regex(@"(\s*)\b(\w)");
   string result = rx.Replace(original, m => m.Groups[2].Value.ToUpper()); 

   Assert.AreEqual(expected, result);
}

 Sunday, November 18, 2007

Organising the dinner with Preparty

In October I started thinking about organising a dinner to bring Adelaide's .NET developers together. I'd never done something like that before and I wasn't sure about the best way to manage it.

Luckily, I remembered meeting Jonathon Kresner at the Wagga Wagga Code Camp in March. Jon had told me he was developing a website in .NET to organise parties. I decided to send him an email and ask how it was going.

Coincidentally, Jon had reached the final beta testing stages of his website, Preparty.com, and when I explained that I was interested in organising a dinner for .NET developers, he was kind enough to grant me a login if I don't mind assisting with the testing.

Preparty.com basically provides you with everything you need to organise a party of any kind (dinner, music gig, or wedding reception) from beginning to end with a smooth user experience.

You start by finding an appropriate venue by choosing from many popular places already registered on Preparty, or by entering details of your own. You then enter the names and email addresses of all your guests and complete the details of your event such as date and time, theme, and other relevant information.

Preparty then handles the creation and sending of e-Invitations with all the details and even a map of the venue location and follows up with a place to track RSVPs, You can even organise entertainment via Preparty and send SMS reminders to your guests as the event draws near. And when it's all over you can invite guests to upload photos from the event to create a slideshow.

I exercised almost all the features of the Preparty website and only found a couple of usability issues that Jon corrected very quickly. For a website supposedly in beta testing, it was very stable.

Preparty is free to register but charges a very affordable rate to purchase email and sms credits. I know now that the website is out of beta and has been released to the public I'll be looking to Preparty.com to organise all my future events and I recommend you take a look too.

 Friday, September 28, 2007

Streaming Large Objects with ADO.NET, Properly

It has been a while since I last worked with storing files in a SQL database and I decided to Google around to remind myself of the best way to do it. I was very disappointed with most of the approaches I found. Unfortunately, my Google-Fu didn't return the MSDN articles I've linked to below, and I had to find out the hard way.

To begin, all solutions I found dealt only with reading a BLOB from a SQL Server image or varbinary(max) column in a streaming fashion. Worst of all very few actually understood what streaming should do, and that is not load the entire object into an array in memory.

My whinging aside, streaming a file out of a SQL table is easy. You start by using a DataReader created by passing CommandBehavior.SequentialAccess to a DbCommand's ExecuteReader function. I also find that selecting only the blob column and only the desired row(s) from the table is the most effective.

When you have the DataReader positioned on the appropriate record you repeatedly call the GetBytes method in a loop, retrieving a small chunk each time and writing it to the output stream. The output can be any IO.Stream like a file or even your ASP.NET response. This MSDN article has a good description of the situation with the SequentialAccess enumeration and some sample code.

Writing a stream of data into a SQL table turned out to be slightly less obvious. I'm only working with SQL Server 2005 so I didn't consider supporting older versions but the approach is similar. SQL 2005 provides a Write "method" on the large value data types in the UPDATE statement.

My solution was to first insert the new row into the table providing values for all columns except the blob. Then I had a stored procedure that would take the row's primary key values, an offset, and a chunk of the data to insert and use the UPDATE .Write method to update the row.

Similar to the reading code, my writing code would read a small chunk from the incoming IO.Stream and pass it to the stored procedure, incrementing the offset each time. Once again, there is another MSDN article that describes the process well but their code looks like it will also work with SQL versions prior to 2005.

In both cases tweaking the size of the chunk used in each iteration of the loop will require some testing and measuring to find the best performance but now you can read and write files of almost 2GB into SQL Server without trying to allocate a similarly sized array in memory first.

 Wednesday, September 26, 2007

Business and Data Layer Architectures

Strongly Typed DataSets in .NET 2.0 do many things very well but they fall short in other places. For a new project I have been researching alternative approaches for structuring the model, logic, and data access projects to allow for easy customisation and good testing.

Firstly, there are some features about DataSets that are very useful and would need to exist in any alternative I consider:

  • Collection filtering and sorting by any properties.
  • Collection and item change notification.
  • IEditableObject support (ie BeginEdit, EndEdit, CancelEdit).
  • Excellent encapsulation of SQL commands.

There is also the limitations of DataSets that should not exist in the alternative I choose:

  • Computed values too complex for DataColumn.Expression cannot be bound to.
  • AllowDBNull and MaxLength violations cause immediate exceptions.
  • Restrictive relationship between model and underlying database structure.
  • Does not utilise Nullable<T> to support columns that allow DBNull.
  • Change notification events cannot be completely silenced.

So far I have briefly investigated CSLA, SubSonic, NHibernate, and some existing applications both real (DotNetKicks) and example (MS Pet Shop), and found that they are all very similar in many ways. Rather than commit myself to a particular framework that may have it's own set of issues I have decided to hand code my own solution to the business and data layering problem.

Others have expressed concerns about going with a third party framework and to a point I agree, but I'm not totally sold either way yet.

I intend to watch my own code evolve as I solve the difficulties associated with the task and refactor my work into common classes. I expect that my code will begin to look much like one of the existing frameworks (although that may be biased by what I've already seen) and perhaps I will end up switching to the solution that most closely matches my own.

The last thing we need is yet another framework.

 Wednesday, September 12, 2007

PowerShell Regular Expression Compiler

As an exercise in the mostly useless, I decided it would be interesting to try my hand at writing a PowerShell script to compile a regular expression pattern to a .NET assembly. I sure someone has already created a NAnt or MSBuild task to do this but I felt this would be a good way to increase my familiarity with PowerShell.

The script requires the RegEx pattern and an output type name and full namespace to work. You can optionally pass an AssemblyName but if omitted the type and namespace will be used to form the output file name. You can also specify the -ignoreCase or -multiLine switches to enable that behaviour on your expression. There are other options that probably should be supported but they can be easily added if you actually have a use for this. Without further delay, here is the code:

param
(
    [string] $pattern = "",
    [string] $typeName = "",
    [string] $fullNamespace = "",
    [System.Reflection.AssemblyName] $assemblyName = $null,
    [switch] $ignoreCase,
    [switch] $multiLine
)

if ($pattern -eq "") { throw ("-pattern required"); }
if ($typeName -eq "") { throw ("-typeName required"); }
if ($fullNamespace -eq "") { throw ("-fullNamespace required"); }

if ($assemblyName -eq $null)
{
    $assemblyName = New-Object System.Reflection.AssemblyName `
        ($fullNamespace + "." + $typeName);
    $assemblyName.Version = New-Object System.Version (1, 0);
}

$sysRx = @{};
$sysRx.Namespace = "System.Text.RegularExpressions";
$sysRx.RegEx = [System.Text.RegularExpressions.RegEx];
$sysRx.RegExOptions = [System.Text.RegularExpressions.RegExOptions];

$options = $sysRx.RegExOptions::None;
if ($ignoreCase) { $options = $options -bor $sysRx.RegExOptions::IgnoreCase; }
if ($multiLine) { $options = $options -bor $sysRx.RegExOptions::Multiline; }

$info = New-Object ($sysRx.Namespace+".RegexCompilationInfo") `
    ($pattern, $options, $typeName, $fullNamespace, $true);

$popDir = [System.Environment]::CurrentDirectory;
[System.Environment]::CurrentDirectory = $PWD;
$sysRx.RegEx::CompileToAssembly($info, $assemblyName);
[System.Environment]::CurrentDirectory = $popDir;

Here is an example usage:

./Compile-RegEx.ps1 "\s+" "Spaces" "CodeAssassin.RegEx" -ignoreCase

 Sunday, September 09, 2007

Refactor By Region

The nature of the software development profession is such that you need to be constantly learning new techniques and improving your style. A side-effect of always seeking to be better is that when you revisit old code it suddenly doesn't seem as good as it did when you first wrote it.

I was revisiting a large class recently and was struggling to navigate between all the methods to follow the logic. I decided to make use of #region blocks (something I rarely do) to help group related methods together and hide less relevant code from view.

By arranging groups of methods together by their purpose, a pattern started to emerge. Each region started to look like an ideal candidate to refactor the code into a new class with a single responsibility. I already had a set of unit tests in place for the existing code so I felt confident in being able to refactor and being able to verify I hadn't broken anything afterward.

What was originally one class became eight, resulting in greater maintainability, testability, and of course readability, solving my original problem. For this class the refactoring by region worked well because I had grouped code by it's behaviour and partly by it's call chain.

However, I've seen other approaches to using #region blocks. I've seen all event handlers put in their own region. I've seen collections of overloaded methods grouped by name. I've even seen properties grouped together, method/subs group together, and functions grouped together. In these arrangements not only does a refactoring pattern not automatically emerge but it becomes harder to search for one.

As I mentioned above, I'm not a big user of #regions. This is probably because I try to refactor my code before it gets big enough and because of the region anti-patterns I've wrestled with. I think I might have to give them a second chance.

 Wednesday, September 05, 2007

Rhino.Blocked

I tried using Rhino.Mocks in production test code for the first time the other day. I downloaded the latest version from Oren Eini's website, unzipped it into source control, and added a reference to my project.

I wrote a quick test utilising the interface mocking features and hit Ctrl+Alt+X to run the test. SecurityException! The message, which I've since forgotten, was complaining that the referenced assembly (ie Rhino.Mocks.dll) could not be loaded.

A quick Google provided the solution, you need to ensure you've unblocked any files you have downloaded from the Internet or a network machine. Now I'm happily mocking away.

 Monday, September 03, 2007

PowerCleaning, Part 2

Each day I live with wanting to make full use of excess storage space to keep a record of every file that has ever existed in all it's versions and the conflicting need to have a neat and tidy file system without any junk sitting around.

Recently, the desire to have a ClickOnce deployment folder with only the latest version in it has won. With only the most recently published version within, the folder is a much more manageable size for distributing to other deployment servers.

However, it can be tedious to ensure only the appropriate files are deleted when cleaning a deployment folder manually, and automating the process is infinitely better. I have put together a basic PowerShell function to handle the situation.

function Clean-ClickOnceApplication ([string] $Path = (Get-Location), [switch] $WhatIf = $false)
{
    ($current, $oldList) = Get-ChildItem -path (Join-Path $Path "*") -include "*.application" `
        | ? {$_.Name -match "_\d+_\d+_\d+_\d+\." } | sort LastWriteTime -desc;
    foreach ($old in $oldList) {
        $oldFolder = $old.Name.Substring(0, $old.Name.Length - $old.Extension.Length);
        Remove-Item (Join-Path $Path $oldFolder) -recurse -WhatIf:$WhatIf;
        Remove-Item $old -WhatIf:$WhatIf;
    }
}

Simply pass the ClickOnce deployment folder as the -Path parameter (or omit to assume the current folder) and optionally enable the -WhatIf switch to test which files and folders would have been deleted.

The script currently uses the time stamps of the .application files rather than the version numbers but unless someone has been messing with the digitally-signed files this shouldn't be a problem. If it really needs to be handled by version number, I have some ideas for handling that.

 Tuesday, July 31, 2007

ArgumentNullException: No Message Required

I have been encountering code recently that bugs me. Many methods in classes are testing their arguments for null/Nothing and, if true, throwing a new ArgumentNullException. So far, all good. However, the constructor for the new ArgumentNullException is being passed both the name of the argument and also a message string of the form "_paramName_ cannot be null".

This is totally redundant. The exception being thrown is an Argument *Null* Exception. That about sums it up. Also, if the constructor is passed the parameter name only the message defaults to "Value cannot be null".

Providing a message for an ArgumentNullException requires extra typing, requires maintaining the argument name in three places if it gets renames, and violates FxCop rule CA1303.

Thankfully it turns out it isn't fellow team members doing it. Developer Express' Refactor Pro has a "Create Method Contract" refactoring that is putting the message in.

 Monday, July 30, 2007

Serialization Engine Wish List

Cereal On several occasions I have need to serialize an object graph in memory out to a stream and also needed to read XML data back into objects. Each time I'm confronted by such a task I find myself hunting through the various MSDN serialization topics and becoming increasingly depressed.

Neither the System.Runtime.Serialization namespace nor the System.Xml.Serialization namespace seem to fit my requirements without needing to write large chunks of custom serialization code. It's getting to the point that I'm tempted to write my own serialization engine.

I know that if I do write my own engine, it will consume most of my time, so for now I'm simply going to document what I'd like to see in said engine.

  • Classes should not require a parameter-less constructor to be deserialized. As a simple alternative a class could define a static method which takes a collection of key value pairs from the engine, creates an instance via an appropriate constructor and returns it back to the engine. Ideally the engine would support declarative attributes on an existing constructor defining how to call it.
  • Classes should not need to override their entire serialization process because the engine does not understand one of it's field types. If my class has four integer fields, two string fields, and a complex unserializable Foo field, the engine should handle the integers and strings itself then hand the final stage to my custom serialization function to handle only the Foo field.
  • Classes should be able to override part of the serialization process then return control to the engine to finish the task. Extending my Foo example, I might have custom code to step in and serialize the Foo data but if Foo has a simple serializable member of type Bar, I want to hand serialization of that member back to the engine.
  • Classes should not need public modifiers on members to enable serialization. The engine should make efficient use of reflection to access private and protected members. Ideally the CLR would have a serialization-access level to allow an engine to work with private members in a low trust environment. I think serialization is such a fundamental function that it warrants some cooperation and special treatment by the runtime environment.
  • Classes shouldn't care what format the engine is serializing to or from. If it's binary, SOAP, XML, JSON, or any other new format, the attributes on my class and my custom serialization code should not need to change.

I'm sure there are some other requirements that I've forgotten and I'm sure this is somewhat too late for Visual Studio 2008 but hopefully I'm not the only one that feels this could be improved. What challenges have you faced with the .NET serialization system?

 Monday, July 02, 2007

Dreams and Mistakes

Firstly, in my recent post about the new .Net DateTimeOffset class I mentioned that I would love to see the SQL Server team include this type in databases. My wishes have been answered, we can expect to see this type and some other very interesting additions in the next CTP/Beta of SQL Server 2008. Unfortunately, all of our clients have bought into SQL Server 2005 and won't be interested in upgrading anytime soon so I'll have to find a new project to try all the new toys.

Secondly, also in a recent post I complained about the CollectionBase type being left behind when generics were added to .NET 2.0. I've since discovered the new Collection<T> class tucked away in the System.Collections.ObjectModel namespace. It doesn't offer all the events that the previous equivalent did but it is inheritable and overridable so it should do the job nicely. I obviously didn't search very hard for it all the other times I looked; very embarrassing.

 Wednesday, June 27, 2007

Ecstatic About NStatic

Ecstatic MascotWesner Moise is getting ever closer to public release of his very promising NStatic static analysis tool for .NET. In general static analysis tools are very expensive but as part of Wes' plans, a lower price to achieve market penetration is most likely. In fact, until he finds a suitable publisher he expects to selling independently for a few months, during which time we might be lucky to pick it up for a "bargain" price.

So far I think NStatic only supports C# 2.0 but there are plans to add support for C# 3.0 features and maybe VB.NET too if the demand is there. I, for one, sure hope that VB support becomes a reality, I think our current suite of software could really benefit from some in depth analysis.

Keep a close eye on Wesner's blog for the latest information.

DasBlog Flip Flop

A few months ago I upgraded this web site from the DasBlog 1.8 installed by my ISP to the latest version at the time, 1.9.6. It was remarkably easy to merge my web.config and site.config files and upload all the new binaries.

Yesterday Scott Hanselman announced DasBlog 1.9.7 had been released. Last night I tried to upgrade again, following a very similar procedure as I did the last time. Being a point release, I expected even less effort and was happy to find that very little merging was required with the config files.

Unfortunately, once I had uploaded the new files to my site I found I could no longer log in. I refreshed the browser several times, edited and uploaded the siteSecurity.config file several times and tried the default file with the admin/admin credentials. Nothing would let me login and all I had was a SecurityFailure message in the event log.

This took an hour or so and I eventually gave up and completely restored the backup I made before attempting the upgrade. Guess I'll have to configure IIS locally and experiment until it works.

On a better note, Scott says this is the final release for ASP.NET 1.1 and another release due very soon will be completely ASP.NET 2.0 and support Medium Trust. I was annoyed last time I downloaded the source and discovered that I would need to install VS2003 to work with it but finally I'll be able to contribute to the project.

 Tuesday, June 26, 2007

DateTimeOffset Is The New DateTime

SundialJustin Van Patten neatly summarises the new DateTimeOffset class introduced in .NET 3.5. In short, this new class combines the year, month, blah, blah, second storage of the DateTime with a time zone offset. The most important point to take from Justin's article is that apart from a few exceptions (which he describes), you should always use DateTimeOffset in new code instead of the old DateTime.

Naturally there will continue to be situations where you need to pass a DateTime but the DateTimeOffset will always be able to scale back to suit. It is much harder to infer time zone information from a DateTime to provide a DateTimeOffset. I'd love to see the SQL Server team introduce this data type concept to databases.

CollectionBase and Generics

In .NET 1.1 the Framework included an abstract class System.Collections.CollectionBase. The idea was that you could extend it to create your own custom collections to hold certain types. The Add, Remove, and other methods were overridable (to perform object validation or filter duplicates) and several events also existed to enable listening for changes.

Cardboard Box Most importantly it provided the mind-numbing mapping from the IList, ICollection and IEnumerable interfaces to the internal storage mechanism (which happened to be an ArrayList). When I created a new collection derived from CollectionBase I could override the OnValidate method to only accept a certain type and I was done.

Sadly, I'm left stranded in my .NET 2.0 world with Generics and an untyped CollectionBase. I cannot inherit from List<T> because none of it's methods are virtual and none of it's fields are protected. Ultimately, I'm stuck with writing my own class with a private List<T> field and coding most of the methods on the various interfaces as redirections to the private field. No thanks, that was one of the biggest reasons for moving from VB6 to .NET.

Interestingly, the SharePoint fellows noticed the same problem with CollectionBase's obsolescence in .NET 2.0, and cleverly decided to provide the more up-to-date CollectionBase<T>. Of course, not only did it end up in the Microsoft.SharePoint.Publishing assembly that I'm reluctant to reference and probably unable to distribute, but they also implemented only ICollection and IEnumerable<T>. I was dumbfounded that IList<T> and ICollection<T> had been missed and that they had also removed IList.

Why am I still forced to code this junk myself?

 Wednesday, June 20, 2007

Beware The Evil Shadow

Evil Shadow Object-oriented programming principles have been an excellent addition to software development but one component that inevitably appears in OO languages has confounded me by it's uselessness. In VB.NET it is known as the "Shadows" modifier, in C# it is found in class member declarations sharing the name "new".

The purpose of this modifier keyword is to allow a subclass to redefine a property, field, or method of the base class where the base class has not been declared "Overridable" or "virtual" in VB.NET or C# respectively. Unfortunately it suffers from a major drawback, as demonstrated by the following code:

class Base
{
   virtual public string Extendable() { return "Extend"; }
   public string Locked() { return "Lock"; }
}

class Foo : Base
{
   override public string Extendable() { return "Food"; }
   new public string Locked() { return "Picked"; }
}

Base b = new Base();
b.Extendable(); // returns "Extend"
b.Locked(); // returns "Lock"

Foo f = new Foo();
f.Extendable(); // returns "Food"
f.Locked(); // returns "Picked"

Base bf = new Foo();
bf.Extendable(); // returns "Food"
bf.Locked(); // returns "Lock" !!!

As you can see, if the Foo methods are called via a Foo-typed variable, there is no difference between shadowing and overriding. However, as soon as you call a Foo method via a Base-typed variable, or pass a Foo instance to another class expecting a Base, you lose the functionality of Foo.

If "new" is omitted from Foo's implementation of Locked, Visual Studio reports an error: The keyword 'new' is required on 'Locked' because it hides method 'Base.Locked()'. It is very easy for someone to simply add the keyword as required with realising the consequences.

Occasionally, all you might want to do is utilise some existing behaviour in a base class and add some more features and shadowing or member hiding is fine. The fact that you have used shadowing is not obvious in the calling code though.

Most of the time, I want to alter the behaviour of a base class and pass my new subclass to existing code, perhaps in the Framework, that is only expecting the base type. Beware.

Waste Management

The script in my last post for removing old files from the temporary folder is only necessary because so many applications don't clean up after themselves. Hopefully, if the applications you are developing are doing the right thing they will be using in memory streams where ever possible. Only write to disk when absolutely necessary, creating random temporary files in the environment temp folder, not program folders with restricted access to non-admin users:

string myTempFile = System.IO.Path.GetTempFileName();

However, remembering to track and delete these files when you are finished requires more effort and is often ignored, creating the ever growing temp folder problem. There is a lesser known class in the framework that can help you though:

var myTempColl = new System.CodeDom.Compiler.TempFileCollection();
string myTempImageFile = myTempColl.AddExtension("png");

Excuse the C# 3.0 syntax in the last snippet, I hate the redundancy of repeating long type names, especially on the same line. When you have finished using all the temp files you created with the TempFileCollection, you can dispose it explicitly, automatically deleting the files, or if you're really lazy, let the GC take care of it.

myTempColl.Dispose();

 Monday, June 18, 2007

ClickOnce and Terminal Services

Under just the right conditions that I have been lucky enough to meet, .NET applications deployed by ClickOnce will not start under a Terminal Services session. At the heart of the problem is this error message:

Shortcut activation from http/https or UNC sources is not allowed.

I could not find anything in Google, on the MSDN forums or in the Microsoft Support Knowledge Base. With some trial and error and a little reflection I've tracked it down to this very special combination:

  • ClickOnce offline install mode is enabled
  • and the application is started via the Start Menu shortcut
  • and the user is logged into a Terminal Services session
  • and Terminal Services is redirecting the Start Menu to a UNC.

Changing any one of these conditions is enough to avoid the problem and would probably explain why it is documented anywhere. The error message is triggered by code in the System.Deployment assembly and it it cannot be overridden by a system setting either.

Redirecting the Terminal Services Start Menu to a UNC is also a common practice when running multiple terminal servers, or a shared Start Menu for all users (as was my case).

I will be recommending users simply start the apps via the same ClickOnce deployment URL that was used for the initial install and try to disable TS folder redirection where possible.

It seems ClickOnce uses the shortcut location later in the bootstrap process and the problem exists in Orcas too so I don't think Microsoft will be fixing this one.

 Friday, June 15, 2007

Rounding

In the .NET Framework, the System.Math class has methods for Ceiling, Floor, Round, and Truncate. Round has an overload for specifying the number of decimal places to round to but it doesn't support other intervals, for example: rounding to the nearest five cents.

The mathematics involved for supporting other intervals is quite simple when you know it but getting there and verifying it can take a few moments. Here is the general solution to save time next time I need it, or if someone else is looking for the same thing:

decimal offset = 0.05M;        // interval we are rounding to (5 cents)
decimal value = 1.23M;         // value to be rounded
decimal temp = value / offset;
temp = MyRoundToInteger(temp); // toward zero or banker's rounding function
decimal result = temp * offset;

You can exchange MyRoundToInteger for any of the afore mentioned Math class methods or even one of your own custom rounding techniques, as long as it rounds to zero decimal places

 Thursday, June 14, 2007

Premature Analysation

I was thinking today as I was resolving a few Code Analysis violations that perhaps I should stop. I will assume you are familiar with the quote "Premature optimisation is the root of all evil" and if you're not, you should be.

I've often had the feeling that something wasn't quite right when I adjusted my code to satisfy the various CA performance warnings. Today I have investigated that feeling further:

Winner of Zurich Marathon 2007 CA1809: Avoid excessive locals - Triggers when you have more than 64 local variables in a method because the processor registers can no longer hold them all and some will be moved to and from the stack. If you have this many variables in a single method you have other problems to worry about.

CA1811: Avoid uncalled private code - Triggers when a private method exists that isn't called directly. This is great for finding and removing dead code but this is more about readability and not runtime performance.

CA1812: Avoid uninstantiated internal classes - Very similar to CA1811 but at the class level. Once again, good for removing dead code but not really performance related.

CA1807: Avoid unnecessary string creation - This is for people who still insist of using ToUpper or ToLower on strings before performing comparisons. Embrace the Unicode world and pass the StringComparison enumeration to String.Equals and String.Compare calls. This rule belongs in the Globalization set.

CA1813: Avoid unsealed attributes - This might be the first real performance rule so far but it does apply specifically to reflection on custom attributes. If your application makes heavy use of attributes, you may want to pay attention here. I think though that your personal philosophy on preferring extendable classes versus sealed classes may have more weight here.

CA1801: Review unused parameters - Once again, this is an excellent rule for locating dead code that may be misleading or unnecessarily complicated to maintain. I am beginning to wonder if the Microsoft.Performance CA category is a misnomer.

This covers the first third of the 18 rules on the performance warnings list. So far only one could potentially undermine the performance of your application given the right conditions and I'd run an actual test to time this before I started making big changes.

However, the rules shouldn't be ignored, perhaps they should just be considered from a point of view other than performance. Hopefully investigating the rest of the list, which I plan to do in future posts, will reveal valid rules for improving performance. I'm expecting at least CA1818 to come though for me there.

Strength In Numbers

Since Visual Studio 2005 has made the whole process much easier, I strong name every assembly I work on. It's one of the first things I do when I add a new project to a solution: Choose a name, set strict compilation warnings, enable Code Analysis, assign a strong name key.

I have used a few open source projects lately and have been disappointed that the binaries haven't always been strong name signed. This means I have to get the source instead, setup a new key and adjust their build script to use it before I can even add it as a reference to my own project.

Weight Lifting There are several benefits to using strong names:

  • Optional deployment to the GAC.
  • Satisfy Code Analysis rule CA2210.
  • Use of the InternalsVisibleTo attribute.
  • Reference from other strong named assemblies.

I don't think I've ever deployed any assemblies to the GAC, so only the last three are relevant for me but I'm sure GAC deployment is important to people writing COM interop code or add-ins for unmanaged applications or it will be important one day when their project gets reused in that context.

The counter-argument is that strong names are supposed to provide security and handing out the private key file with rest of the source would defeat the purpose. However, Mike Downen, program manager for security on the CLR team, says this:

They have no revocation capabilities and they don't expire. Nor do strong names inherently provide any way to securely map a public key to a particular publisher. Thus, strong names should be used very cautiously when making security decisions.

For these reasons I think it is a good idea to strong name all assemblies. Perhaps use a different strong name private key for each program. The owner(s) of an open source project could even retain a private key separate from the one distributed by the open source repository and use it for signing official binary releases.

 Tuesday, June 12, 2007

Code Camp Is In Tents

A tent on the beach I was privileged to attend Code Camp Oz 2007 in Wagga Wagga this year and I highly recommend it to anyone working with .NET. Unfortunately not everyone can find the time to drive twelve hours across the country for a weekend.

However, anyone living in South Australia will have an opportunity to attend the upcoming Code Camp SA, a free event sponsored by the University of South Australia, the Adelaide .NET Users Group, and the Australian Computer Society.

It will be held at the UniSA City East West campus for both days of the July 7th and 8th weekend. Specific details and registration can be found on the ACS web site for Saturday and Sunday. When available, the scheduled program will be published on the ADNUG news page.

If the content and quality of Code Camp Oz is anything to go by, this is an event that shouldn't be missed. See you there.

 Monday, June 04, 2007

Capture To Team Foundation

Dudu Shmaya has just released a plugin for Cropper to create TFS work items from screen captures. You can also use it to add screen capture attachments to existing work items. We already use both Cropper and TFS, and this new plugin should be very useful for creating bug reports.

Dudu says he plans to submit the source code for his plugin to the CodePlex project for Cropper plugins soon. Looks like there are some other nice plugins already on their too.

 Saturday, June 02, 2007

Sharpen Your Unit Tests, Forget VB

We are entering a new stage of development at work, we've released betas of three modules and are now beginning the initial iterations for two new modules. We are taking this opportunity to push unit testing into our standard development cycle, which is something I've wanted to do for a long time.

With friend and work colleague, Jim Burger, leading the charge to unit test and document our common libraries, some "best practices" that suit our project model are starting to reveal themselves.

For each project under test, we create a corresponding test project with the same name suffixed by "Tests". This keeps the projects paired together in the Solution Explorer and creates default namespaces for the projects that are just different enough to avoid clashes.

Within the test project we then create a folder for each class under test and within those folders, we create a unit test class for each function under test. We've found that each function usually requires at least three tests (null guard test, common case, edge case) and giving each function it's own file keeps our tests manageable.

Most importantly, while all our production code is in VB, we write our unit tests in C#. One of the main reasons is that the C# compiler respects the InternalsVisibleTo attribute and allows us to test code marked as Friend without resorting to reflection in our tests or putting test-only code in our production projects.

We also get the nice benefit that C# will automatically put classes in namespaces that match the folder structure in the project. This provides a simple mechanism to categorise our tests for running them and viewing the results. C# also tends to produce slightly more succinct code which just feels better as the number of tests grows.

Although both VB and C# have their pros and cons, the majority of the .NET world is C# and so are the job opportunities. As a VB programmer, by using C# for at least some of your work, you make sure you are learning more aspects of .NET and when you get involved in the .NET community you're more likely to appreciate what they're talking about.


This post brought to you by Windows Live Writer Beta 2.