Saturday, May 30, 2009

Intercepting a HTTP call to modify its behaviour

Say you have some application that uses a HTTP call to get hold of some XML data. It could be a web service but might also be an ASHX generic handler, or any kind of server-side HTTP handling code. Say you want to change the behaviour of that code in some way but you don’t have access to the source code but can change the URL that the calling application uses. What to do?

This was my problem to solve. Actually I didn’t realise it was a problem until I thought of the solution, then thought it would be an exceedingly useful thing to do, and may well be useful in other scenarios. The basic idea is to create a generic handler that will replace the original handler and in the simplest case just pass the request onto the original handler and return the response from the original handler. The configuration of the calling app needs to be updated to use the new handler.

There may be other solutions, such as adding a HTTP module to the original handler, if it happens to be an ASP.NET application. This solution may impact performance since two HTTP calls will be made rather than just one, but I still quite like it.

Here’s the code for the ProcessRequest method, that obviously needs updating to make any changes to the response returned by the original handler. It also shows how to deal with POST data, if the call you’re intercepting is a POST call.

    public void ProcessRequest (HttpContext context) 
      context.Response.ContentType = "text/xml";
      // create outgoing HTTP request
      HttpWebRequest req = (HttpWebRequest)WebRequest.Create(
      req.Method = "POST";
      req.KeepAlive = false;
      req.ContentType = context.Request.ContentType;

      // get POST data from incoming request
      string parameters;
      using (StreamReader postReader = new StreamReader(context.Request.InputStream))
        parameters = postReader.ReadToEnd();

      // add POST data to outgoing request
      using (Stream stream = req.GetRequestStream())
      using (StreamWriter streamWriter = new StreamWriter(stream))
      // get response
      using (WebResponse resp = req.GetResponse())
      using (Stream respStream = resp.GetResponseStream())
      using (StreamReader reader = new StreamReader(respStream))
        string response = reader.ReadToEnd();

Thursday, May 28, 2009

Saving a control’s image to a file

Saving a WinForms control’s image to a file, should be pretty straightforward. After all, there is a DrawToBitmap method that should do the trick, right? Well, not quite. Unfortunately DrawToBitmap draws the controls in reverse order, i.e. the top controls are drawn first. So first you need to reverse the z-order of the controls on the form and then reverse them again then after generating the image, something like the following

        using (Bitmap bitmap = new Bitmap(formControl.Width, formControl.Height))
          formControl.DrawToBitmap(bitmap, new Rectangle(0, 0, formControl.Width, formControl.Height));
          bitmap.Save(outputFile, ImageFormat.Jpeg);

Ah, but what about the implementation of InvertZOrderOfControls? You can find that here.

Even after that frigging around, the saved image may not be perfect. The output produced is dependant on the underlying operating system. Vista and XP produce reasonably accurate output, but Server 2003 doesn’t look too good.

Tuesday, May 26, 2009

writing-mode: tb-rl broken in IE8

Vertical text in a web page can be pretty damn handy. I’ve used it in our documenter for Metastorm BPM procedures where we have some grids with columns which would become too wide if the column headers used horizontal text. OK, it only ever worked in Internet Explorer, but given the add-on is for an application that only runs in IE on Windows, I wasn’t too concerned by that.

Now, along comes IE8 and vertical text no longer works properly. Grids are incorrectly sized when they contain vertical text. Try this in a HTML page.

  what the...
  <table border="2px">
      <td style="writing-mode:tb-rl">Some text</td>
      <td style="writing-mode:tb-rl">Some more text</td>
  .. is going on in that grid?

And this is what that will look like (obviously view in IE8 to see the problem)

what the...
Some text Some more text

.. is going on in that grid?

Which is disappointing… Ah but you’re not here to see the problem are you? You want to know how to solve it I guess. The only solution I’ve found is to add the following to your head element, which forces IE8 to render the page in IE7 emulation, which means you miss out on all the new rendering goodness in IE8.

<meta http-equiv="X-UA-Compatible" content="IE=7" />

Update – You’ll probably need to manually force IE to switch to IE8 standards mode to see the problem, seems that MS has decided BlogSpot sites are not ready for IE8, so this is running in compatibility mode.

Sunday, May 24, 2009

To ID or not to ID

Somebody commented on my post about my implementation of a US states table, saying there was a problem with it because there was no ID field. I can understand the comment but don’t necessarily agree with it. The table has a primary key, the state code. In this instance, this seems a reasonable approach, the state code isn’t likely to ever change and non-numeric primary keys can still be used as foreign keys in other tables. In fact using the state code has its advantages since in some queries, joining to the state table won’t be necessary if only the state code is required in the result set, so SQL is simplified and is probably quicker.

But ID fields are almost expected by many people, but is this purely down to habit, or are there good reasons for having an ID field in tables? In many cases, there is no other obvious column (or number of columns) to use as a primary key in the table. Then it clearly makes sense to add an ID column. But are there other reasons to use an ID column? Does it offer better performance? I don’t actually know the answer to this question, but I’m interested to know.

I do have an example where a seemingly sensible unique column was used as a primary key, but this caused problems down the track and an ID column would have been a better solution. It was a user table that used the user name as the primary key. This seems like a reasonable idea, since it has to be unique, but the problem came when users wanted to change their user name in the system. This can be due to any number of reasons, but the main one is getting married. Since the user name was used as a foreign key on lots of other tables, things got somewhat complicated when trying to update them all. Of course with hindsight a user ID column would have been a better solution in this case.

So perhaps that’s the reason people add ID columns by default, since it’s perhaps impossible to guess beforehand whether the natural primary key will need to be updated. That said, it seems pretty unlikely that state codes will change, so I’m happy to keep the state code as my primary key.

Wednesday, May 20, 2009

Google Friend Connect and the back button

If you wait long enough, generally whatever feature you’ve wanted to add to your website gets implemented by somebody in such a way that you can reuse it yourself, so I was pleased to see Google Friend Connect had the ability to let users add comments to web pages, as this is something I’d wanted to add to the Random Pub Finder for a long time, and hadn’t got round to doing, mainly due to laziness. Admittedly Friend Connect may not be the perfect solution, particularly if you want to keep in control of your data, but it looks good as a quick and dirty hack.

So I added it and almost immediately I noticed a bit of a major problem. Hitting the back button didn’t take me back to the previous page, I needed to press it again. In fact, it turns out that for every Friend Connect gadget that you add to a page, another entry gets added to the history list, making backwards navigation even more difficult. It looks like it’s an IE only issue, but given that most web users are still using IE, I think it’s pretty big problem (unless normal users don’t use the back button?). After doing some searching on the internet, I discovered this problem has been around for quite a while but still hasn’t been fixed. Which is a shame, because Friend Connect looks cool. But it looks like I’ll have to remove it until this issue is addressed.

Tuesday, May 19, 2009

Editing authentication scripts in Metastorm BPM

 Editing Metastorm authentication scripts If you’ve ever had problems with SSO in Metastorm BPM, or been required to implement an unusual authentication mechanism, you’ve probably had to go through the jig of removing, editing and re-adding the script through the System Administrator application. Having found this approach less than optimal, I added support for authentication scripts to the FreeFlow Administrator. This works somewhat differently since it allows you to edit scripts directly. This makes the edit, test and debug process much quicker. Edit the script, apply the changes, test the login (the engine picks up the new script without needing a restart) and then debug and start again if necessary. It’s probably not something you’ll use every day but when you do need it, it makes life much easier.

Thursday, May 14, 2009

Is BPM counter cyclical?

There’s a theory going around that has probably been mentioned enough times now to become a mainstream view. The theory is this – BPM is counter cyclical. And the reasons put forth for it are this. During a recession, companies are looking to cut costs and one way to achieve this is by purchasing and implementing BPM software. BPM promises to improve process efficiency thus reducing costs.

It’s a persuasive argument, if a little simplistic, but is it true? To tell you the truth I have no idea. Rashid Khan argues it’s not true and the only arguments I’ve seen that BPM is counter cyclical seem to have come directly or indirectly from BPM vendors. Certainly something that promises to offer a significant reduction in costs is going to be attractive but BPM software is generally an expensive purchase (although there are free options starting to appear) and then there are costs involved in actually getting it up and running. No single company’s processes are exactly the same as another so some analysis and development will be required. And processes change, so there are on-going costs incurred. Finally, it’s difficult to quantify how much money will be saved by implementing BPM. I’ve seen some impressive figures for savings made, but will those figures be replicated in your organisation? There are so many variables involved, it’s probably impossible to know. Again, that may make it difficult to justify the up front cost.    

Next, some anecdotal evidence. The Lombardi conference was cancelled and became a virtual event, but the Metastorm conference was well attended, so it’s difficult to draw any conclusion from that. Metastorm claim their revenues have increased by 16% over the past year which isn’t explosive growth, but any kind of increase should be considered a good thing at the moment. The company I work for has certainly not been unaffected by the downturn but we are still managing to keep our head above water.

That all said, BPM isn’t going away. And if it isn’t counter cyclical, that won’t necessarily be a bad thing. Perhaps, finally, we might see some consolidation in the area. Some of the weaker companies may disappear or merge and the stronger companies can gain more market share and thus have more money when the recovery comes (whenever that maybe) to produce even better software.

Of course, if you are thinking about or are actively implementing BPM in your organisation, Process Mapping is here to help.

Tuesday, May 12, 2009

Lastminute trademarks the colour magenta

When browsing the Lastminute website, I spotted this notice at the bottom.

"", "lastminute" and the colour magenta are all trade marks owned by Last Minute Network Limited and/or its group companies

Bizarrely it turns out that trademarking colours is possible. But we’re OK, we can all continue to use the colour so long as we aren’t in the same business as Lastminute, which is, er, selling pretty much anything. Oh.

Monday, May 11, 2009

A generic error occurred in GDI+ when saving an image

This has to be one of the most useless error message I’ve ever encountered in the .NET framework. It seems that pretty much any problem that occurs when using Image.Save will produce this error message. Looking at the code in Reflector, the error is returned from the GDI+ function GdipSaveImageToFile. For me the solution was pretty simple, the folder I was trying to save my image to didn’t actually exist but it took some head scratching before I realised.

Saturday, May 09, 2009

New look JobStats site

Not sure when it happened, but JobStats has got a new look. This is the best site to find out about the health of the IT job market in the UK. From looking at the site, it’s clear they now have some issues with their data (or calculations) since some of the average rates are clearly ridiculous. And if they’re not, I really should be getting into doing SAP consultancy. That said, the graph showing the number of advertised jobs is truly terrifying, since there are now fewer jobs advertised than at any time in the last ten years. If you consider that probably many more of the total jobs available are now advertised online than ten years ago makes that graph even more depressing viewing. Lets hope I don’t need to to look for a new job any time soon… (and that is really tempting fate)

Sunday, May 03, 2009

Adding trace to ASHX files

This is almost certainly caused by me being an idiot, but I know there are other people out there who are idiots on occasion so I thought I’d post this. I’ve never used Trace.Write in ASP.NET before and the first place I needed to use it was in a generic handler ASHX page. I didn’t look too closely at what was required and assumed that I needed to use Trace.Write in System.Diagnostics. That was my first mistake. This doesn’t add any trace output to the trace.axd page (though it would be cool if it did since I could then add trace to my assemblies that would show up, perhaps adding a custom trace listener could fix this?).

So then I looked at the code for System.Web.UI.Page and realised it has a Trace property but a generic handler doesn’t have this property so I thought that I might be out of luck. Eventually I realised that the HttpContext passed into the ProcessRequest method has a Trace property so I could just use that for all my tracing needs. Problem solved.

Update: I’ve now realised it’s pretty easy to include trace output from System.Diagnostics.Trace calls in ASP.NET apps. Just add the following to web.config

    <trace autoflush="false" indentsize="4">
        <add name="WebPageTraceListener"
            type="System.Web.WebPageTraceListener, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>

Baltimore skyline

Baltimore skyline panorama

There’s an advert for Microsoft on currently that shows a kid taking some photos and with a few clicks stitching them together into a panorama. All thanks to the ease of use of Vista. So when I was in Baltimore this week I took some photographs to attempt to do the same thing. After all, if some kid can do it, I’m sure I should be able to. But when I fired up Windows Photo Gallery I was unable to find any options to make a panorama. So I fired up Windows Live Photo Gallery instead and that did have the option. In fact it was pretty damn simple to create a panorama, as you can see above.

But two things bother me. Why are Microsoft advertising Windows by showing the capabilities of an application that doesn’t ship with the operating system? And why are there two different photo gallery applications which seemingly do the same thing but are subtly different?

Saturday, May 02, 2009

A simple WinForms numeric edit control

There are plenty of controls out there that will allow only numeric entry but they may not meet your needs. If you don’t want the up/down buttons, the built-in NumericUpDown control won’t be of use and using one of those huge libraries just for their numeric control may be overkill. If that describes your position, this uber-simple control may fit the bill.

  public class NumberControl : TextBox
    /// <summary>
    /// Creates a new <see cref="NumberControl"/> instance.
    /// </summary>
    public NumberControl()
      TextAlign = HorizontalAlignment.Right;

    /// <summary>
    /// Triggered when a key is pressed. Swallows all keys except for digits.
    /// </summary>
    protected override void OnKeyPress(KeyPressEventArgs e)
      string decimalSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
      if (e.KeyChar.ToString() == decimalSeparator)
        if (Text.IndexOf(decimalSeparator) > -1)
          e.Handled = true;
      else if (!char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar))
        e.Handled = true;