Thursday, October 04, 2007

Opening .NET

Scott Guthrie's blog entry "Releasing the Source Code for the .NET Framework Libraries" details how Microsoft are finally going to allow access to the .NET framework source code without having to resort to using Lutz Roeder's fantastic Reflector utility - under the terms and conditions of the Microsoft Reference License.

To their credit, Microsoft are not claiming that this is an open source license; although naturally some on Slashdot are seeing this as further proof of that Microsoft == Satan (you'll find the discussion here: http://developers.slashdot.org/article.pl?sid=07/10/03/1626209&from=rss)

Anyway, it does look being yet another compelling reason to move to Visual Studio 2008 when it finally gets released (along with .NET Framework 3.5 support, and the ability to target .NET Framework 2.0/3.0/3.5 from within the same IDE - about time too...)

 Friday, December 08, 2006

Testing Times Concluded

I shouldn't have got myself so wound up about the 70-536 exam I did this morning. The 'real world' questions were not nearly as bad as the Training Kit had me expecting, and there certainly weren't any howlers like the example I posted yesterday, so it came as a great relief to pass comfortably.

Mind you, it looks like I'm not the only one to have issues with the quality of the official Training Kit.

 

 Thursday, December 07, 2006

Testing Times

I'm sitting the 70-536 (Microsoft .NET Framework 2.0 – Application Development Foundation) exam tomorrow, and I sincerely hope that it's of a higher quality than the learning materials Microsoft provide for it. I've been testing myself using the official MCTS 70-536 Training Kit, and running the example tests provided.

What's disconcerting is that some of the questions are just plain wrong; here's an apposite example:

Which of the following code samples is the most efficient and compiles correctly?

  1. string s = null;
    s = "Hello";
    s += ", ";
    s += "World";
    s += "!";

  2. string s = null;
    StringBuilder sb = null;
    sb = "Hello";
    sb += ", ";
    sb += "World";
    sb += "!";
    s = sb.ToString();

  3. string s = null;
    StringBuilder sb = null;
    sb.Append("Hello");
    sb.Append(", ");
    sb.Append("World");
    sb.Append("!");
    s = sb.ToString();

  4. string s = null;
    s = "Hello";
    s += ", ";
    s += "World";
    s += "!";

So what's the correct answer? Not only do we have two identical options (1 and 4), but they also happen to be the only ones that will compile and execute. 2 is wrong because StringBuilder doesn't accept the "=" or "+=" operators, and 3 also shares the problem that the StringBuilder is never instantiated. Guess which option the test exam says is correct?

Can't say it fills me with much confidence for tomorrow...

 Monday, November 20, 2006

Monad Moanin'

Last week, Microsoft quietly released Windows Powershell 1.0 (formally known as Monad) to the world. This is a great piece of technology that's worth taking some notice of - it's destined to become my Windows shell of choice; at least when a version for Vista is released. As it is, I'm stuck using it on my development laptop (running XP SP2). Previously, if I needed to do any form of complex scripting on a Windows box, I'd install Cygwin and knock something up in bash. Powershell will now take preference however; it ties in the .NET Framework with a scripting environment, so it gives me a library that I'm already familiar with (and one that I'm likely to be staying with for some time). As a quick example, how to display the number of days until Christmas using Powershell:

[String]::Format("{0} days until Christmas!", ([DateTime]"25 Dec 2006" - [DateTime]::Now).Days)

That's not to say that Cygwin is coming off my systems any time soon, I like having the GNU toolchain available (I'd be lost without rsync, ssh and wget), but for day to day scripting it'll be Powershell.

When it's available for Vista that is!

 Thursday, June 15, 2006

XML Woes

Amongst the many roles I seem to undertake at my current employer (.NET Evangelist, NHibernate Evangelist, ATLAS Evangelist and so on), I also spend a large amount of my time dealing with XML technologies - whether it be transformation, serialization, querying or whatever.

Over time I've seen some truly awful implementations of so-called XML 'solutions'; one of my favourites involved the DVLA here in the UK. They proudly announced that they'd implemented an XML based system to enable the querying of Driving Licence details (whether the driver was banned, how many points on the licence and so on). So, given an XSD schema describing the object graph required for the query I coded up a simple .NET application to produce the correct XML fragment.

The DVLA instantly rejected it because:

  1. Every element needed to start on a new line
  2. There was an 'encoding' attribute in the XML declaration
  3. Even though the source XSD had specified a target namespace, namespace declarations were not understood

Aaaargh!

Even worse was the size of the response - every single line in the response document was padded to over 200 characters, and with one element on each line this produced a document that was 62,771,702 bytes long.

A simple

cat results.xml | tidy -xml -indent -o parsed.xml

produced a document that was a mere 8,604,602 bytes in length.

Now this is a bit of an extreme example, but I've seen several variations along this theme in active use and nearly all of them stem from one single problem - string concatenated XML, like this:

Console.WriteLine(@"<?xml version='1.0' encoding='utf8'?>");
Console.WriteLine("<root><element attribute='value' /></root>");

XML has a problem in that it is very easy to read and understand, but there are enough pitfalls for the unwary/lazy. I've had documents in the past where the encoding has been specified as UTF-8, but the characters supplied have been ISO-8859-1 which lead to some truly awful hacking with 'awk' and 'sed' later in a complex overnight batch process.

The MSDN article "Five Ways to Emit Test Results as XML" by James McCaffrey provides some interesting XML generation options for the .NET framework which I fully agree with - except for the end of Technique 1.

There are many, many toolkits out there for XML processing and generation - don't resort to string concatenation, you'll get it wrong!

 Wednesday, August 31, 2005

Transfer Completed

If you can read this, my domain has been successfully transferred from wwwserver to Netcetera. Whilst wwwserver provide an incredibly cheap Asp.NET hosting service and a very intuitive management system, their helpdesk support leaves a whole lot to be desired.

When a customer registers a problem on an automated helpdesk system, it is entirely unacceptable that the issue remains unanswered 48 hours later. At the very least acknowledge to the customer that the problem is being looked into, rather than leaving them wondering what on earth is going on.

As it is, I've lost two full days worth of emails in as many weeks due to their Email Forwarding service failing.

Sometimes cheap is not cheerful.

 Tuesday, February 22, 2005

DevWeek 2005

Spent my first day at DevWeek 2005 today, and I have to admit my brain seems fit to burst this evening. John Robbins was the keynote speaker this morning, giving a general talk on the new features in VS.NET 2005. I have to admit that if I was one of the developers behind ReSharper (the development tool for VS.NET 2003) I'd be seriously worried. All the refactoring tools in VS.NET 2005 seem to be heavily influenced by, if not directly copied from ReSharper (or at a push, Eclipse).

I spent the rest of the day being lectured by (and asking far too many akward questions of) Jeffrey Richter. His first two sessions were connected with the new features in C# 2.0 of which I'll blog about more later.

What was more worrying was what was mentioned almost in passing during his Exceptions lecture (which was in itself fascinating); .NET Remoting is dead - or at least not promoted any more by Microsoft. I'll have to get Ingo Rammer's take on this tomorrow as he's one of the speakers here. It's a shame if this is correct, as the last major project we completed at IS Solutions would not have been possible (or at least would have been even more painful than it was already) if .NET remoting wasn't as well designed as it is.

 

 Tuesday, October 12, 2004

Adventures In Url Rewriting

A project I'm currently working on for my employer using ASP.NET 1.1 requires a coherent mechanism to maintain a consistent look and feel throughout the entire site. Now, as ASP.NET 2.0 isn't here yet (Master Pages would have been a perfect fit for this project) I decided to use a mechanism based on URL rewriting.

In short, all the main 'page' functionality is contained within User Controls. There is a single .aspx page that loads the required user control and instantiates it for display within the HTML template. Using a regular expression based url rewriter mechanism this templating system is hidden from the end user; for example, a request for:

http://localhost/MyApplication/MyPage.aspx

is mapped under the hood to:

http://localhost/MyApplication/Template.aspx?UserControl=Controls/MyPage.ascx

All well and good - I had the basic URL rewriting mechanism in place in a couple of hours, and the start of a working template mechanism a couple of hours after that. However, then the problems started cropping up.

The first major issue cropped up with postbacks. In short, they didn't work. The reason for this is that the ASP.NET framework fills in the action attribute with a canonicalized path to CurrentExecutionFilePath, which is not what's wanted here.

Easy then - change the action in the template page. Wrong; whichever brain dead idiot designed the System.Web.UI.HtmlControls.HtmlForm class hid the implementation of the action attribute. So, you've got to jump through hoops to change the functionality.

My eventual solution was to subclass the HtmlForm and replace the instance in my template page with my new class, ActionForm. ActionForm overrides the RenderAttributes function, which creates a new HtmlTextWriter, my own subclassed ActionFormHtmlTextWriter. This class in turn overrides WriteAttribute which checks to see what attribute it's writing out - if it's "action", then the value is changed to the originally requested Url. Control is then passed back to the original HtmlTextWriter to write the value out. Anyway, if it gets someone else out of the mire, then great.

public class ActionForm : HtmlForm
{
    protected override void RenderAttributes(HtmlTextWriter writer)
    {
        string action = (string)Context.Items["VirtualUrl"];

        if (action == null)
        base.RenderAttributes(writer);

        using (ActionFormHtmlTextWriter virtualWriter = new ActionFormHtmlTextWriter(writer))
        {
            virtualWriter.ActionUrl = action;
            base.RenderAttributes(virtualWriter);
        }
    }

    private class ActionFormHtmlTextWriter : HtmlTextWriter
    {
        private string actionUrl;

        public ActionFormHtmlTextWriter(HtmlTextWriter writer) : base(writer)
        {
        }

        public ActionFormHtmlTextWriter(HtmlTextWriter writer, string tabString) : base(writer, tabString)
        {
        }

        public string ActionUrl
        {
            get { return actionUrl; }
            set { actionUrl = value; }
        }

        public override void WriteAttribute(string name, string value, bool fEncode)
        {
            if (value != null && String.Compare(name, "action", true) == 0)
                value = ActionUrl;

            HtmlTextWriter writer = (HtmlTextWriter)InnerWriter;
            writer.WriteAttribute(name, value, fEncode);
        }
    }
}


 

 Monday, February 23, 2004

ASP.NET Focus Component

One of the small irritants in the ASP.NET framework is there is no built-in mechanism to set the focus of a control directly in code - you have to emit javascript to handle the job for you.

This is no problem, as ASP.NET gives you standard methods that allow you to register client script blocks with a page, but most of the solutions I've seen to this problem so far involve adding code directly to the inherited Page object to do the job.

However, this to me is untidy and as it's a common enough function to want to achieve, it would be nice to have a component you can quickly drop onto your page.

The code that follows does exactly that; once added to your toolbox, you can drop this component onto your ASP.NET design surface. From the properties box, simply set the ControlToFocus property to the control you want to, er, focus.

It works by handling the target controls' PreRender event, and injecting a startup script into the associated Page object. Very, very simple.

using System;
using System.ComponentModel;
using System.Web.UI;

namespace EdCourtenay.Community.WebControls
{
    public class FocusSetter : Component
    {
        private Control focusControl = null;
    
        public FocusSetter()
        {}

        public Control ControlToFocus
        {
            get { return focusControl; }
            set
            {
                if (focusControl != null)
                    focusControl.PreRender -= new EventHandler(FocusControlPreRender);

                focusControl = value;

                if (focusControl != null)
                    focusControl.PreRender += new EventHandler(FocusControlPreRender);
            }
        }

        private void FocusControlPreRender(object sender, EventArgs e)
        {
            Control control = (Control)sender;
            Page page = control.Page;

            if (page != null)
            {
                string script = String.Format("<script type=\"text/javascript\">document.getElementById(\"{0}\").focus();</script>", control.UniqueID);
                page.RegisterStartupScript("focusControl", script);
            }
        }
    }
}

 Saturday, February 21, 2004

The format of the file 'VSUserControlHost.dll' is invalid

I've been struggling for a few days with an exception that kept on being raised when authoring my own composite ASP.NET Web Controls:

The format of the file 'VSUserControlHost.dll' is invalid

After spending some time banging my head against a brick wall, it turns out that the cause was the otherwise excellent CodeSmith plugin for VS.NET, which I use to produce things like type-safe collections; disabling it removes the problem immediately.

 Wednesday, April 10, 2002

Lights Out

For those of you who don't remember, there used to be a handheld electronic game made by Tiger Electronics, called LightsOut. I got bored travelling up to London on the train the other day, so I whipped out my laptop and started coding this little bit of fun. I came back to it a couple of days ago, and added the original 50 levels from the handheld unit.

lightsOutHandheld.jpg

Please remember that the whole thing was an elaborate attempt to waste time on the spectacularly dull Yeovil to London journey, so don't expect anything truly amazing. But its plus points are that: it's written in C#, it's got 50 really irritating levels and it demonstrates writing your own owner-drawn user controls. Full source code is in the Zip file.

Oh yeah, and if you haven't got it already, you'll need the .NET Framework to run it. Any questions?

 Wednesday, February 06, 2002

Repton.NET

I've started work on a port of the classic Repton 3 for the BBC Micro - a game that took up far too much of my time when I was younger - to the .NET platform.

repton_001.png

Considering the amount of time I've had to get the project underway (not a lot) and my unfamiliarity with the .NET framework (there's just so much in there...) I'm quite impressed with how far things have progressed.

I started by having a look at the KRepton port, and I've quite unashamedly nicked all the maps and graphics that were supplied with that version! The only difference is that I've converted all the sprite files to PNG as opposed to BMP. As the .NET framework can handle .PNG files natively, and also as I'm injecting all the images and maps into the final executable, it makes sense. At present, with all 21 map sets and related image files, the whole thing is weighing in at 300k.

repton_002.png

At the moment, I've got the basics of the game in working order. Rocks fall correctly, keys open strongboxes, blips fly around the maze following the left hand wall switching cages into diamonds (albeit far too fast at the moment) and the main character is fully animated.

However, there's quite a lot left to do: as yet there's no scoring mechanism, there's no way to complete a level (crowns, bombs and timers don't work at present), monsters are not implemented, eggs don't crack and falling rocks don't kill you. Phew.

Anyway, as soon as there is a slightly more complete version, I'll post it to this site. You've been warned!