Tuesday, 17 October 2006

How to program it...

This brief 'essay' on developing a functional algorithm How to program it... is based on a 1945 book describing methods of problem solving.

The four basic steps are:
  1. First, you have to understand the problem.

  2. After understanding, then make a plan.

  3. Carry out the plan.

  4. Look back on your work. How could it be better?


I think it should be required reading for all developers - even pasted on your cubical wall!

Particularly when hiring, one of the "metrics" I try to measure in candidates is their sense of 'logic'. This is easier said than done, however; and actually what I am really interested in their natural ability or inclination to follow such a process.

It's easy to spot less 'logical' developers. They start at (and sometimes only ever do) Step #3! Sometimes, in the process of thrashing about in Step #3 they may accomplish some of Step #1. While fixing the inevitable bugs, they may also accidentally get some Step #4. But it's not an efficient process...

Sunday, 3 September 2006

The best developers are built not bought

The best developers are built not bought

At the very bottom of Bloom's taxonomy of educational objectives for cognitive skills is knowledge. That is recall (or recognition) of data or information. Applied to development terms this means recognizing the C# syntax or recalling the correct syntax to execute a loop.

At the top of the cognitive taxonomy is synthesis and evaluation. Synthesis is to be able to bring together diverse elements to form a new whole solution. Evaluation is the ability to make judgments about the value of ideas, approaches, or materials. Developers need to consistently apply these higher levels of cognitive ability to effectively perform their work.

Most people find the idea expressed as thinking more natural than describing the difference as cognitive process. In general, the more thinking that is being done about higher level ideas, such as how to integrate pieces to form a solution, the better the developer.

Sunday, 20 August 2006

Visual Studio 2005 Snippets - literal dollar sign $$$

Been using Visual Studio 2005 snippets since I installed it... double-[tab] is a common keystroke now. Of course, my first attempt to create a Snippet wasn't as simple as it should be thanks to the dollar sign escaping of variables. I wanted a 'standard' VSS region-wrapper as a snippet (yes, I realise I can also add it to our class file template).
#region Page History
/*
* $History: $
*/
#endregion
but the editor interprets $History: $ as a variable and doesn't display it. Tried Google, but not easy to search for '$' and get useful results... after a few false starts trying to Xml entity encode it (ie. >) which also didn't work, I tried the double-dollar-sign $$ at random - and it worked!

Got Snippets is a great place to start when looking for useful snippets (or ideas/samples to build your own). Some of them are pretty complex.

Some other useful snippet links:

Monday, 10 July 2006

Generics, Serialization and NUnit

Latest article Generics, Serialization and NUnit posted on CodeProject.com. The googling I've done so far hasn't turned up much info on Unit Testing and Generics... seems to me that any time you write a class, you want to be able to test it, and Generic classes should be no exception; but there's not much support in NUnit for it at the moment...

Monday, 3 July 2006

NCover 'connection not established' error

I recently tried to set-up NCover 1.5 with a .NET 2.0 project on a new PC, but could not get past the error message Profiled process terminated. Profiler connection not established... the BAT file I was using looked like this (and was working fine on the build server)
@echo off
C:\DevTools2\NCover-1.5\NCover.Console.exe "C:\DevTools2\nunit-2.4.b1\bin\nunit-console.exe" "C:\Projects2\APPNAME\UnitTests\APPNAMEUnitTests.nunit" //a "Common.APPNAME.DataAccess;Common.APPNAME.Common; Common.APPNAME.RulesEngine;Common.APPNAME.Client" //ea "Common.CodeCoverageExcludedAttribute" //w "C:\DevTools2\nunit-2.4.b1\bin" //l "C:\Projects2\APPNAME\Build\NCover\NCover.log.txt" //x "C:\Projects2\APPNAME\Build\NCover\NCover.xml"


Of course, because NCover was working OK on other .NET 1.1 projects, I immediately assumed it was a 'framework' issue and spent fruitless time trying to 'figure out' why NCover couldn't "connect" to my application.

I gave up, only to be embarrassed a day or two later when this
NCover Error Message thread: Profiled process terminated. Profiler connection not established gave me the simple solution: I needed to register one of the NCover components (presumably so it can hook in to the CLR instrumentation or whatever)
regsvr32 CoverLib.dll

Doing an install of NCover from the .MSI would also have worked, but I've gotten so used to .NET applications being able to be 'xcopied' that I had just moved the NCover files from one PC to another and expected them to work.

Thursday, 22 June 2006

atlas:UpdatePanel Cancel/Abort UpdateProgress

Thanks to this blog Trabalhando com o ASP.NET Atlas Framework - Parte III for finally giving me the hint on how to add a Cancel/Abort option to the atlas:UpdatePanel UpdateProgress template.

Just add an <input runat="server" type="button"> <asp:LinkButton id="abortButton" runat="server">

The trick is id=abortButton! You don't need to add any further client or server code/jscript/whatever. The presence of that control id is enough. When the UpdateProgress is displayed, you can click to cancel the Ajax XmlHttpRequest.

Why was this so difficult to figure out? I guess because if you use the Designer to create the ProgressTemplate it adds the button for you... but i was creating the controls in Source view, and it was NOT immediately obvious how the Abort/Cancel should be implemented.

EDIT 22-Feb-07 This post is out-of-date; the released version of ASP.NET AJAX doesn't work this way... just one of the breaking changes - check the Migration Guide: Converting Applications from “Atlas” CTP to ASP.NET AJAX RTM

Sunday, 18 June 2006

,NET 3.0!

How did I not already know this... .NET Framework 3.0 will be released with Vista, and available for Windows XP and Windows Server 2003.

Interestingly (I think) it will just compile with the existing FX2.0 CLR, so I guess WinFX is just a mass of managed code? Still doesn't include LINQ or ObjectSpaces, so for database-focussed (ie. business) applications, what benefit does the renamed WinFX provide?

OT: great discussion-starter on Who needs value types anyway?, and this on .NET Framework 3.0 Naming...

Monday, 12 June 2006

RefreshPanel: precursor to Atlas

The Atlas UpdatePanel control seems to have it's genesis in the April 2005 RefreshPanel on gotdotnet.

The UpdatePanel has it's own 'book lite' on OReilly.com - USD9.99 doesn't seem to bad, although the fact they want to charge 'delivery' for overseas customers is very frustrating! The PDF itself is like an extended CodeProject article...

Sunday, 4 June 2006

Migrating to *ASP*.NET 2.0... from a Class Library project

In ASP.NET 1.1, Web Projects and the way they bind to Visual SourceSafe and a specific website make it *very* difficult to manage. I have always followed this advice to use
ASP.NET without web projects: the Project becomes a class library, and with a few minor VisualStudio configuration changes the source-control integration becomes a LOT easier.

But what happens when you want to migrate to ASP.NET 2.0? Do you:

  1. keep using the 'class library hack', but maybe forgo VisualStudio 2005's cool new features for ASP.NET Designer Support

  2. convert back to a Web Project in 1.1 then migrate to 2.0 (ie undo/reverse these instructions)

  3. migrate the 'class library' project to 2.0 first, then convert it to the new (ie post Visual Studio 2005 released add-in) Web Application Project/li>
  4. create a Web Site Project and copy all the existing pages into it

  5. or something else...



If your website is part of a larger solution (ie other projects such as Business Objects), or you have more than one developer, or you are actually using source-control, let me save you some time and recommend number 3.

  1. First open the Visual Studio 2003 Solution using 2005 and follow the steps to migrate to Framework 2.0.

  2. Then make any code changes to get it to compile

  3. Now for the tricky bit, open the <WebApplication>.csproj in NOTEPAD
    1. Add
          <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
      near <ProjectGuid>

    2. Add
      <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v8.0\WebApplications\Microsoft.WebApplication.targets" />
      near whatever other Import elements exist near the end of the file

    3. Add this to the end of the file (you may need to update some settings)
        <ProjectExtensions>
      <VisualStudio>
      <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
      <WebProjectProperties>
      <UseIIS>False</UseIIS>
      <AutoAssignPort>True</AutoAssignPort>
      <DevelopmentServerPort>2555</DevelopmentServerPort>
      <DevelopmentServerVPath>/</DevelopmentServerVPath>
      <IISUrl>
      </IISUrl>
      <NTLMAuthentication>False</NTLMAuthentication>
      </WebProjectProperties>
      </FlavorProperties>
      </VisualStudio>
      </ProjectExtensions>
      </Project>



  4. If you left the Solution open while editing, Visual Studio will detect the changes and offer to re-load. The first thing you should notice is the little 'world' in the Project icon (instead of the class-library square). The Project-Properties will also have a [Web] item, and all the benefits of ASP.NET Design-time, etc should be available.



Oh, and don't forget, if IIS is still pointing at the site's directory, you need to map the Framework 2.0 Handlers to it, using the Command Prompt...
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -s W3SVC/1/ROOT

Friday, 2 June 2006

ILMerge is my 'tool of the week'

I've already been using ILMerge to merge output from a number of different projects in a solution into a single EXE or DLL for redistribution (or inclusion in other projects). It works fantastically, particularly via an ILMerge NAnt Task.

There are a few tricks, like remembering that Type info includes the assembly name! If you're directly referring to a Type in code, or a .config file, those references MUST CHANGE if that Type is subsequently merged into a 'new' assembly with ILMerge.

That's pretty basic stuff thought. Both
K. Scott Allen: Using MSBuild and ILMerge to Package User Controls For Reuse
and
David Ebbo : Turning an ascx user control into a redistributable custom control describe another interesting use : packaging up ASCX-type User Controls into redistributable DLLs. Great idea if you find building User Controls with a Design surface to be much easier than programmatically building Server Controls.

Seems like 2.0 has plenty of cool tricks to offer if you can think of them...

Friday, 26 May 2006

ASP.NET Atlas April CTP Installation Error

It was nice to know I wasn't the only one having problems installing Atlas April CTP due to cabinet file '_28942B4D9DE730210E7C27BD4FBAD377'...is corrupt.

I originally downloaded Atlas and did "Save As" (which is my habit, to install on multiple PCs). But as with quite a few others, it didn't work: "The cabinet file '_28942B4D9DE730210E7C27BD4FBAD377' required for this installation is corrupt and cannot be used. This could indicate a network error, an error reading from the CD-ROM, or a problem with this package."

I tried again, in both IE and FF, from my desktop and laptop (so four times) - clearing browser cache, etc (after the first time it broke, and I started googling for answers).

Then I noticed one of the comments on ASP.NET Atlas forum about the Publisher being 'Microsoft' versus 'Unknown', and it seemed like the versions I downloaded [Save As] and 'double-clicked' on were 'Unknown Publisher.
While not believing it would work , I tried again (with IE) BUT clicked [Run] instead... and the first dialog that appeared showed Publisher: Microsoft! The install worked fine from that point.

I don't know how/why the authenticode/whatever process would be different for a saved versus 'run straight away' install^, but after four failures across browsers/pcs and one success, I'd encourage others to at least give it a go -- click [Run] when you download!

^ actually, another post makes an interesting point about the effect of security/permissions in your IE 'downloads' folder versus your /My Documents/, /Desktop/ or wherever you might be placing the file when you [Save As]. I don't know enough about it to comment - but sounds feasible...?

Wednesday, 24 May 2006

Searcharoo v3 is LIVE

Ok, maybe not ALL CAPS exciting, but a new version of my 'basic' C# search engine and web spider Searcharoo is now 'ready'.

There's a pile of stuff I still wanted to add to it: creating interfaces and plug-ins for the Word and Number Normalization, a UK/Australian version of the stemmer, at least putting the 'language/culture' into the Stop/Go/Stemmer/Stopper interfaces so they could be language-specific and a lot more. They'll all have to wait for the next version...

'Support' and 'thanks' emails trickle in fairly regularly, hopefully that will continue.

I think the old articles are still worth reading...
Searcharoo: C# File system indexer and search (version 1)
Searcharoo: C# Search Engine and Web Spider (version 2)

Friday, 31 March 2006

"Cannot find the assembly" for Binary Deserialization

I have an ASP.NET search tool which stores a data structure in the Application cache. This 'problem' relates to the next version so stay tuned for the new code.

The structure is built up via a C# class which is defined in a .CS file. It takes a while to build (it crawls the web), so I don't want the build process to be running all the time.

The .CS file is compiled and executed 'on the fly' because it is only referenced in ASPX page @PAGE SRC=""

The assembly it is compiled into therefore has a random (and different) name every time the 'web application' restarts (eg. IIS is restarted, the computer is rebooted, or ever a change to web.config). The assembly name could be anything from "udlo.dll" to "9pd_.dll".

Rather than re-build the data structure every time the 'web application' restarts, I decided to serialize it to file, and look for the file to deserialize on restart, before rebuilding.

The XML serialized file is 77Mb+. Too big. The Binary serialized file is 4Mb. Better.

Imagine my frustration when - despite all the code looking right, the ASPX kept returning this error System.Runtime.Serialization.SerializationException: Cannot find the assembly ***
where *** was always a different, random dll name (because of the dynamic compilation of @PAGE SRC="" code files).

I already had an inkling that Binary-serialized objects could only be deserialized by the same assembly that serialized them, but I wasn't really sure why. Thankfully, goxman supplied some answers on CodeProject .NET XML and SOAP Serialization Samples, Tips.
Type information is also serialized while the class is serialized enabling the class to be deserialized using the type information. Type information consists of namespace, class name, assembly name, culture information, assembly version, and public key token. As long as your deserialized class and the class that is serialized reside in the same assembly it does not cause any problem. But if the serializer is in a separate assembly, .NET cannot find your class’ type hence cannot deserialize it...
In this case we can write our own class’s binder and tell the deserialization to use our binder while looking for our classes’ types.

As you can see - this is a real problem in my scenario - every time I need to deserialize my objects, it is because the application has restarted, the code is recompiled and by definition the assembly name is different!

Thankfully the CodeProject article goes on to demonstrate how to implement System.Runtime.Serialization.SerializationBinder and attach it to formatter.Binder... and everything worked!

Friday, 24 March 2006

Searcharoo gets some use!

It's cool when you randomly stumble on other people linking back to your code... like this blog linking to a Searcharoo user,
combining Searcharoo with Lucerne.

That, plus some positive comments on the CodeProject Searcharoo article has motivated me to get working on the code again!

Thursday, 16 February 2006

WebRequest/WebResponse and saving a downloaded binary

It took waay longer than I expected to find this code on Google... Sure you can use WebClient with it's DownloadFile() method... but if you want to fiddle with timeout settings, etc. then you need to drop back to the WebRequest/WebResponse classes.

Thanks to this GoogleGroups response download binary file using c# webrequest/webresponse I was able to get it working.
WebRequest objRequest = System.Net.HttpWebRequest.Create(url);
objRequest.Timeout = 600000;
objRequest.Credentials = CredentialCache.DefaultCredentials;
WebResponse objResponse = objRequest.GetResponse();
byte[] buffer = new byte[32768];
using (Stream input = objResponse.GetResponseStream())
{
using (FileStream output = new FileStream (fileloc, FileMode.CreateNew))
{
int bytesRead;
while ( (bytesRead=input.Read (buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, bytesRead);
}
}
}
There are all sorts of red-herrings around this task - BinarySteam, ResponseEncoding, etc... but in the end it was relatively simple.

Tuesday, 14 February 2006

SQL Server Reporting Services RS.EXE (#1)

Automating the deployment of reports (*.rdl) and data sources (*.rds) using NAnt and RS Utility (rs.exe) has been relatively straight forward. There are a few tricks, which I'll post later; but for now, the following error had me stumped for a while, and didn't return anything useful on Google.

The required field DataSource is missing from the input structure

In my case, I tracked it down to sample code I'd copied from
MSDN: ReportingService.SetReportDataSources.

I'm using VB.NET (argh!), and the dataSources array declaration in this sample code is the cause of the error.
Dim dataSources(1) As DataSource
actually creates a two-element array BUT we only set one element
dataSources[0] = ds;
so when this line executes
rs.SetReportDataSources("/SampleReports/Product Catalog", dataSources)
it is actually sending an array where the zeroth element is set to a valid object, but the first element is NULL... hence the (somewhat cryptic) "required field DataSource is missing" error.

The fix?
Dim dataSources(0) As DataSource

Sunday, 5 February 2006

JSON - Wikipedia, the free encyclopedia

Russ pointed me to JSON - JavaScript Object Notation... a Javascript 'feature' which I'd never heard of (but maybe I've seen examples of it, and not understood what they "did").

Seems a lot like the Anonymous types and Object Initializers that are mooted for C# 3.0. Sorta.