Saturday, 29 November 2008

.Net Repeater - Say it again

Up till recently I’ve been very suspicious of the higher level tools that ASP.Net 2.0 offers. Site Map, Menu controls, the dreaded Web Parts. Be a man – write it yourself. This even stretched to a refusal to use the DataGrid and related controls. I can do better with a small screwdriver and a dynamic control collection. And for years I stuck to that.

Recently though I’ve been working in an environment where they are big fans of Microsoft controls, so as a wise man once said ‘When in Rome use the same ASP.Net controls as the Romans do’. With that in mind I have been getting my hands dirty with DataGrids, DataViews and Repeaters. One of the things that has always put me off of these controls is which control do you use for what. The confusion was so great that often I had 2 or 3 different controls on a page at one time to compare, contrast and moan about. The result of all this moaning/development was

  1. For paging – use a DataGrid
  2. For an easy primary key for each row – use a DataGrid
  3. For multiple columns – use a DataView
  4. For fine control over what is displayed on each cell – Moan a lot then go back to using a dynamic collection of TableCells (that designers will never, ever be able to see).

But then as I was walking on the road to Damascus (a local falafel shop) a bright light shone from the clouds and a wise voice spake unto me and said “don’t mess around with all those other controls – just use Repeaters”. Thus and verily I journeyed back to the promised land and recoded all my grids with repeaters using the following divinely inspired techniques to get over the aforementioned limitations.



Primary Key for each Row
Use a hidden field (i.e. label with visibility set to false) and write the value into that

<asp:Repeater runat="server">
<ItemTemplate>
<asp:Literal ID="lblPrimaryKey" runat="server" Visible="false"
Text='<%# DataBinder.Eval(Container.DataItem, "PrimaryKeyId") %>' />
<%# DataBinder.Eval(Container.DataItem, "Name") %>
<%# DataBinder.Eval(Container.DataItem, "Address") %>
<%# DataBinder.Eval(Container.DataItem, "DoB")%>
</ItemTemplate>
</asp:Repeater>
Once written in the primary key can be accessed through the event handlers of the data grid – see below.
protected void Repeater1_ItemCreated(object sender, RepeaterItemEventArgs e)
{
Control lblKey = item.FindControl("lblPrimaryKey");
Int primaryKey = Int32.Parse(lblKey.Text);
//do something with the primary key
};
Multiple columns
Use divs for the columns and float them to the left (see http://css.maxdesign.com.au/floatutorial/ for float tutorial). The below code shows it in action.
<asp:Repeater ID="Repeater1" runat="server">
<HeaderTemplate>
<div style="width:800px;">
</HeaderTemplate>
<ItemTemplate>
<div style="width:200px;float:left;">
<%# DataBinder.Eval(Container.DataItem, "DisplayField")%></div>
</ItemTemplate>
<FooterTemplate>
</div>
</FooterTemplate>
</asp:Repeater>
The above example gives 4 columns i.e. 800px box surrounding the repeater with divs of 200px floated inside – sooo only 4 can fit before a new row is started. Obviously you don’t need to be a maths genius to work out the numbers for other numbers of columns (e.g. 600px outside, 200px divs – 3 columns etc…).

Fine control over each cell
If you have a requirement to modify each cell depending on the primary key of the row – leverage the On_ItemDataBound event of the repeater grid and modify the contents of each cell as it’s rendered
<asp:Repeater ID=" Repeater1" runat="server"
OnItemDataBound="Repeater1_ItemCreated">
<ItemTemplate>
<asp:Literal ID="lblPrimaryKey" runat="server" Visible="false"
Text='<%# DataBinder.Eval(Container.DataItem, "PrimaryKeyField")%>' />
<%# DataBinder.Eval(Container.DataItem, "Name") %>
<%# DataBinder.Eval(Container.DataItem, "Address") %>
<asp:Button ID="btnGo" runat="server" Text="Details" />
</ItemTemplate>
</asp:Repeater>
The below event is fired when the grid is rendered
protected void rptSurveyListNao_ItemCreated(object sender,
RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item
e.Item.ItemType == ListItemType.AlternatingItem)
{
Control lblSurveyStatus = item.FindControl("lblPrimaryKey");
Int primaryKey = Int32.Parse(lblSurveyStatus.Text);
If(primaryKey > 0)
{
btnGo = (Button)item.FindControl("btnGo");
btnGo.Enable = true;
}
}
}
It the above example we could control the button activity based on the primary key in the repeater row.

Paging
Use the PagedDataSource following the technique outlined in 4GuysFromRolla. . OK hands up for this one – I’ve never used it but I’ve been assured by real life people that it works



And from that day forward all the HTML coders and designers in the land
came to pay homage to the lowly Repeater because they could easily access the
HTML tags behind the controls and not struggle with the arcane DataGrid styling
properties.

Thursday, 27 November 2008

Accelerando - Serialising Lobsters


I make no apologies about being a sci-fi geek. Being a software geek pays the bills so I think I deserve a bit of extra-curricular sci-fi geekiness. In that vain I just have to recommend Accelerando by Charles Stross – it drips with geeky goodness.

I can’t begin to summarise the plot – all I can do it assure you that the book positively fizzes from page 1. Not enough, you want more of a reason to buy, read and adore this lovely tome. OK
  1. Mr Stross is was a computer scientist amongst other things and it the first sci-fi book that I’ve read to really have that embedded in it. At the start of the book sentient lobsters get serialised and sent up a data stream – Fab.
  2. One of the main characters is a cat. It total catches the animal’s don’t give a damn attitude – double Fab
  3. Charlieboy Stross comes from my hometown, Leeds. I have a LOT of regional pride soooo – Triple Fab.
If I had to categorise it then its cyberpunk without the noir elements and it’s actually well written unlike other so called cyberpunk classics i.e. everything I’ve ever read by William Gibson.

Sunday, 23 November 2008

Website Publishing Gotcha

I was trying to publish a web site in Visual Studio 2005 this week and kept coming across this strange error when browsing to the published website.

Cannot convert type 'ASP.login_aspx' to 'System.Web.UI.WebControls.Login'

After some pen chewing, head scratching and news group ferreting I came across the solution in this posting.

Apparently if you call an aspx page the same as a standard WebControl then the publishing freaks out. Which fool would do that? Well this fool does on a regular basis. I always call my log in pages Login.aspx – the same as the login control. The solution – a quick rename of the page to Default.aspx and stride manfully out of the office declaring that the website is now released into the wild. Job done (and will be done a bit quicker next time).

Wednesday, 19 November 2008

Boring Names

The other evening I was reflecting on past projects I've worked on – as a gentleman often does. When I started work as an IT tadpole I first worked on PEO, graduating to RMS then TMS. I then worked on the CRS Portal, EMISWeb and interfaces to LV and PCS. Lately I have been doing work with BVA, NAO and ePIMS.

Other than suffering under my hand – what have all these applications got in common? Are they all high-transaction wonder apps? No. Are they all shrink-wrapped money spinners? Not that either. Are they all groundbreaking super fast system software? Nope, nope, nope. The real connection is that they all have boring names.

I don’t know if there is something about business type applications that encourages people to give them vague three letter acronym names. Perhaps users of these applications need to be in a sedate state of mind before use so hand them software in a grey box with a vague name. Otherwise hyper stimulation and all kinds of unpleasantness may ensue.

However 7 years of working on apps with generic TLA names is enough. So, starting from tomorrow I’m going to rechristen all my apps. I won’t be working on IPD tomorrow – it will henceforth be called Timux Turbo Polka Fortress Green Hat v5.1. My project manager will be delighted.

Saturday, 15 November 2008

ExecuteNonQuery Gotcha

Here’s something that made me roll my eyes this week. I’ve been trying to get the number of rows executed returned from SQL Server to an ASP.Net data layer. It promised to be straight forward but it had a cheeky little gotcha nestled in the middle of it. To take the simplest example for demo purposes (all error handling type stuff omitted)

The stored procedure

CREATE PROCEDURE usp_TestProc
@PersonId int
AS
BEGIN
Set Nocount On

Update Person
Set
FirstName = 'Willy',
Surname = 'Wonka'
Where
Id = @PersonId
END

The calling business layer

conn.Open();
cmdNonQuery = conn.CreateCommand();
cmdNonQuery.CommandType = CommandType.StoredProcedure;
cmdNonQuery.CommandText = “usp_TestProc”;
cmdNonQuery.Parameters.AddRange(sqlParameters);
numberOfRecords = cmdNonQuery.ExecuteNonQuery();
 

Logic (and the .Net API documentation) dictates that the ExecuteNonQuery method returns the number of rows. But it steadfastly returns -1 no matter what is occurring in the database.

So what is happening?? It turns out that the Nocount setting stops this information coming back. Removing the statement – or setting NoCount Off causes the ExecuteNonQuery method to behave as expected. It returns -1 if no rows affected otherwise the number of rows actually affected.

This would probably be too arcane to worry about except the SQL Server standard template for creating stored procedures includes the Set NoCount On statement. In other words – select ‘create new procedure from the SQL Server menu’ and you get this template

CREATE PROCEDURE <Procedure_Name, sysname, ProcedureName>
-- Add the parameters for the stored procedure here
<@Param1, sysname, @p1> <Datatype_For_Param1, , int> = <Default_Value_For_Param1, , 0>,
<@Param2, sysname, @p2> <Datatype_For_Param2, , int> = <Default_Value_For_Param2, , 0>
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

-- Insert statements for procedure here
SELECT <@Param1, sysname, @p1>, <@Param2, sysname, @p2>
END
GO

Very lovely – except it contains the very code that disables the proc return values. Ouch.

Wednesday, 12 November 2008

There are 10 types of people

It’s that rarest of all things – a joke about number bases

There are 10 types of people – those that understand binary and those that don’t.

Hahahahaha – brilliant. Tell you friends, write it on all your Christmas cards, put it on your e-mail signature – spread that joy. Sadly it doesn’t work quite as well in hexadecimal

There are 1A types of people – 1 that understands hexadecimal and 25 that don’t

However I’m convinced it can be made to work in other bases. I’m going to apply for an EU grant to study the application of this joke to other mathematical systems. If they’ll fund the Large Hadron Collider I’m sure they’ll fund this similarly important work.

Friday, 7 November 2008

IT Demographics and Logan’s run


I have a few baseless theories about the IT workplace – here’s one.

Logan’s Run is an old sci-fi film starring Michael York and the much loved (by me anyway) Jenny Agutter. The basic premise is that in a post apocalyptic society youth is prized above all else. So much so that when a citizen reaches 30 they are executed. And don’t try to run off because Michael York will don his leather pants, run after you and shot you to bits. Ouch!

I’ve often thought that software development must work in the same way. When you reach a given age, probably about 40, you’re taken quietly into a room for a bit of professional development and quietly exterminated. What else can explain the lack of older developers in a profession that’s been going in strength for 30 years or more.

Ok, there may be other explanations.
  1. Lot’s of people leave the profession after 5-10 years. The plasterer that did my dining room was an ex-IT worker. I think he was happier with his trowel.

  2. People get rescued into management/project managers etc…. But there aren’t that many management positions.

  3. People go into related position because the rate of change in IT is too much. I’ve known a few testers in that position. There are undoubtedly IT trainers in the same position.
Alternatively maybe Michael York is stalking the older members of the profession. Beware of blond actors in leather pants everyone.

Saturday, 1 November 2008

Recaptcha


It’s very wisdom of the masses, the power of crowds, web 2.0, wikinomics and all that – but your very own website can digitise books without trying. Using captcha’s the little squiggles many of us spend much of the time entering in can miraculously help digitise texts.

It’s all handled by the people at Carnegie Mellon University (http://recaptcha.net/ ) Basically –they provide a plug it to website that provide the captcha display for your website. It’s a few lines to hook it up and then you’re off. I did it in PHP but it available in .Net, Java and more languages than I’ll ever know.

To implement

  1. download the relevant library i.e recaptchalib.php
  2. Sign up to recatpcha for a public and private keys
  3. Code to display the captcha in PHP below

<?echo recaptcha_get_html($publickey, $error); ?>

4. And to deal with the post back – a bit more but not rocket surgery.

if ($_POST["submit"])
{
$resp = recaptcha_check_answer ($privatekey,
$_SERVER["REMOTE_ADDR"],
$_POST["recaptcha_challenge_field"],
$_POST["recaptcha_response_field"]);

if ($resp->is_valid)
{
.. do some processing to the valid form
}
else
{
# set the error code so that we can display it. You could also use
# die ("reCAPTCHA failed"), but using the error message is
# more user friendly
$error = $resp->error;
$displayForm = true;
}
}

I was listening to the leader of the project on a Digital Planet podcast. They use OCR to get about 80% of the words and farm the hardest 20% out to people doing captchas. Apparently they are digitising hundreds of books a day through this. I am genuinely impressed.

Sadly though – it appears that captchas generally are gradually becoming less effective . But I guess so long as your site is more secure that the next guys… (all IT security professional grind teeth at this statement – OK, I realise it’s no better than recommended that I hide my website registration under a stone).