Maintaining The Scroll Position On An ASP.NET Page After Postback

I had a requirement today for an ASP.NET page to jump to the same part of the page once a form was submitted via a postback.

Qudos to my fellow developer Andy Howell for leaping in and pointing out that functionality was already in ASP.NET 2.0 and above, so there would be no need for me to write any funky JavaScript.

You need to set MaintainScrollPositionOnPostback to true. I did this in the Page tag on the ASP.NET page.

<%@ Page MaintainScrollPositionOnPostback="true" %>

Although I’ve not tested it yet, you should also be able to set it globally in the web.config file in the pages section.

<pages maintainScrollPositionOnPostBack="true" />

Or programmatically in the code behind.

System.Web.UI.Page.MaintainScrollPositionOnPostBack = true;

For more information on this, see the MSDN page for System.Web.UI.Page.MaintainScrollPositionOnPostBack.

The Null-Coalescing Operator In C#

One bad habit that can occur when using a different programming language than the one you are used to, is writing code that looks very similar to the old language you are used to.

I found myself in this trap earlier, and only spotted it during a code review.

I had been using the ternary operator to compare and return results something like this in C#.

string currentStation = (selectedStation != null ? currentStation : "Q Radio");

It works, but C# provides something far nicer called the null-coalescing operator, ??, which lets you set a default value when you try to assign a nullable type to a non-nullable type.

The example above could be rewritten like this…

string currentStation = selectedStation ?? "Q Radio";

You can read more about the ?? operator for C# on the MSDN website.

Uploading Files To A LAMP Server Using .NET

We had to setup and run a webcam for the Q Awards red carpet earlier this week.

The original plan was to have an old Axis ethernet webcam, connected to a wifi network using a Dlink bridge. After a nightmare of not being able to get the Dlink to work, we gave up and went for a USB webcam connected to a laptop approach.

I had to write some software to handle the capture of the image and the upload to the webserver. Because we wanted to do a few custom things on the way we weren’t able to use out of the box software.

I’ll post on how to use a webcam with .NET another time. What I wanted to document was how to upload a file using .NET to a LAMP server.

It turns out to be easier than I thought for .NET, one line of code can achieve this using the My.Computer.Network.UploadFile Method.

For example, to upload test.txt to http://www.robertprice.co.uk/asp_upload.pl we can do the following (in Visual Basic)…

My.Computer.Network.UploadFile("C:test.txt","http://www.robertprice.co.uk/asp_upload.pl")

Now we need some code at the other end to store this upload. As I was building a webcam application, the uploaded file, an image in this case, was always overwritten.

The uploaded .NET file uses an bog standard HTTP upload as described in RFC 1867.

If we use Perl to read this file, we can use the standard CGI.pm module to do most of the hard work for us.

The uploaded file is passed a parameter called file, so we can create a CGI object and get a reference to this using the param method. Once we have this, we can treat it as a filehandle and read the date off it. Then all we have to do is to write it out to a file.

The following code achieves this.

#!/usr/bin/perl -w
use strict;
use CGI.pm;
my $CGI = new CGI;
my $file = $CGI->param('file');
open(FILE, ">/path/to/my/file/test.txt") or die $!;
while(<$file>) {
print FILE $_;
}
close(FILE);
print "Content-type: text/htmlnn";
print "OKn";

Atom WSSE Authentication Using C# .NET

I received an email asking for a hand with a C# .NET implementation of the WSSE atom authentication for Nokia’s Lifeblog.

I took a look at this as I’m brushing up on my C# at the moment for work, and I relish a challenge.

As there are two different methods of authentication depending on the version of Lifeblog being used, the code has to handle this.

The first method is to append the nonce, timestamp and password together, create a SHA1 hash with this and Base64 encode the result. The second way is almost the same, but the nonce has to be Base64 decoded first before being appended with the timestamp and password.

See my previous article on WSSE Authentication For Atom Using Perl for more details on how this works.

The first method can be calculate a digest value using code like this.

string mystring = nonce + created + password;
SHA1Managed SHhash = new SHA1Managed();
string mydigest = Convert.ToBase64String(SHhash.ComputeHash(System.Text.Encoding.ASCII.GetBytes(mystring)));

My first attempt at the second method looked very similar.

string mystring = (System.Text.Encoding.ASCII.GetString(Convert.FromBase64String(nonce))) + created + password;
SHA1Managed SHhash = new SHA1Managed();
string mydigest = Convert.ToBase64String(SHhash.ComputeHash(System.Text.Encoding.ASCII.GetBytes(mystring)));

Looks OK on the surface, but it fails to validate when posting from my Nokia N93 phone.

What’s gone wrong?

Well looking in the debugger, the process of converting the nonce back from the array of bytes Convert.FromBase64String() produces and appending them to form mystring corrupts the data compared with the Perl version in my previous article.

We know the approach is basically right, so we need to cut out this corrupting step.

The best way to do this is to keep the data in byte arrays as we need the data in this format anyway to computer the SHA1.


System.Text.Encoding enc = System.Text.Encoding.UTF8;
byte[] noncebytes = enc.GetBytes(nonce);
byte[] passwordbytes = enc.GetBytes(password);
byte[] createdbytes = enc.GetBytes(created);
byte[] code = new byte[nonce.Length + password.Length + created.Length];
Array.Copy(nonce, code, nonce.Length);
Array.Copy(created, 0, code, nonce.Length, created.Length);
Array.Copy(password, 0, code, nonce.Length + created.Length, password.Length);
System.Security.Cryptography.SHA1Managed SHhash = new System.Security.Cryptography.SHA1Managed();
string digest = Convert.ToBase64String(SHhash.ComputeHash(code));

I’m sure there is a nicer way to achieve the appending of the 3 arrays together in C#, but this works for now.

We can tie this up to form a nice static class to handle our WSSE authentication.

/// <summary>
/// Computes WSSE codes from input for validation.
/// </summary>
public static class WSSE {
/// <summary>
/// Calculate the digest.
/// </summary>
/// <param name="password">A string with your unencrypted password.</param>
/// <param name="nonce">The nonce the digest is to be created with as a string.</param>
/// <param name="created">The timestamp as a string.</param>
/// <returns>A string containing the digest.</returns>
public static string GetDigest(string password, string nonce, string created)
{
return GetDigest(password, nonce, created, System.Text.Encoding.ASCII);
}
/// <summary>
/// Calculate the digest.
/// </summary>
/// <param name="password">A string with your unencrypted password.</param>
/// <param name="nonce">The nonce the digest is to be created with as a string.</param>
/// <param name="created">The timestamp as a string.</param>
/// <param name="enc">The System.Text.Encoding to use.</param>
/// <returns>A string containing the digest.</returns>
public static string GetDigest(string password, string nonce, string created, System.Text.Encoding enc)
{
byte[] noncebytes = enc.GetBytes(nonce);
byte[] passwordbytes = enc.GetBytes(password);
byte[] createdbytes = enc.GetBytes(created);
return generatecode(noncebytes, passwordbytes, createdbytes);
}
/// <summary>
/// Calculate the alternative digest.
/// </summary>
/// <param name="password">A string with your unencrypted password.</param>
/// <param name="nonce">The nonce the digest is to be created with as a string.</param>
/// <param name="created">The timestamp as a string.</param>
/// <returns>A string containing the digest.</returns>
public static string GetDigestAlt(string password, string nonce, string created)
{
return GetDigestAlt(password, nonce, created, System.Text.Encoding.ASCII);
}
/// <summary>
/// Calculate the alternative digest.
/// </summary>
/// <param name="password">A string with your unencrypted password.</param>
/// <param name="nonce">The nonce the digest is to be created with as a string.</param>
/// <param name="created">The timestamp as a string.</param>
/// <param name="enc">The System.Text.Encoding to use.</param>
/// <returns>A string containing the digest.</returns>
public static string GetDigestAlt(string password, string nonce, string created, System.Text.Encoding enc)
{
byte[] noncebytes = Convert.FromBase64String(nonce);
byte[] passwordbytes = enc.GetBytes(password);
byte[] createdbytes = enc.GetBytes(created);
return generatecode(noncebytes, passwordbytes, createdbytes);
}
private static string generatecode(byte[] nonce, byte[] password, byte[] created)
{
byte[] code = new byte[nonce.Length + password.Length + created.Length];
Array.Copy(nonce, code, nonce.Length);
Array.Copy(created, 0, code, nonce.Length, created.Length);
Array.Copy(password, 0, code, nonce.Length + created.Length, password.Length);
System.Security.Cryptography.SHA1Managed SHhash = new System.Security.Cryptography.SHA1Managed();
return Convert.ToBase64String(SHhash.ComputeHash(code));
}
/// <summary>
/// Validates password, nonce and created create the same digest code as digest.
/// </summary>
/// <param name="password">A string with your unencrypted password.</param>
/// <param name="nonce">The nonce the digest is to be created with as a string.</param>
/// <param name="created">The timestamp as a string.</param>
/// <param name="digest">The digest to validate the password, nonce and created strings against as a string.</param>
/// <returns>true or false depending on wether the digest validates</returns>
public static bool IsValid(string password, string nonce, string created, string digest)
{
return digest == GetDigest(password, nonce, created) || digest == GetDigestAlt(password, nonce, created);
}
/// <summary>
/// Validates password, nonce and created create the same digest code as digest.
/// </summary>
/// <param name="password">A string with your unencrypted password.</param>
/// <param name="nonce">The nonce the digest is to be created with as a string.</param>
/// <param name="created">The timestamp as a string.</param>
/// <param name="digest">The digest to validate the password, nonce and created strings against as a string.</param>
/// <param name="enc">A System.Text.Encoding encoding.</param>
/// <returns>true or false depending on wether the digest validates.</returns>
public static bool IsValid(string password, string nonce, string created, string digest, System.Text.Encoding enc)
{
return digest == GetDigest(password, nonce, created, enc) || digest == GetDigestAlt(password, nonce, created, enc);
}
}

We can test the code using the following code snippet.

string digest = "nvvHvNuLb+7wGFrop+cC2tjgQqs=";
string nonce = "bgZ4BHcjmWcg7gVhCxyQOg==";
string timestamp = "2006-04-25T19:40:45Z";
string password = "a";
if (WSSE.IsValid(password, nonce, timestamp, digest, System.Text.Encoding.UTF8))
{
Console.WriteLine("valid");
}
else
{
Console.WriteLine("invalid");
}

This gives us the result “valid” as we’d hope.

To save you time, feel free to download the C# code
WSSE.cs.

iTunes Auto Updating Now Playing in VB2005

Previously I’ve covered how to link into the iTunes COM library from VB 2005 to show now playing information. This article assumes you have already read that, or have it to hand.

Taking this application further, wouldn’t it be useful for our application to automatically update itself when a track changes takes place on iTunes?

Well I hope you are saying yes, as it’s what I’m going to cover now.

iTunes can inform our application of changes of track if we choose to listen for it’s OnPlayerPlayEvent event.

If you are not sure what an event is, it’s basically a way for one program to tell another that something has happened in that program and the other program may wish to react to it. In this case, a different track has started playing in iTunes.

So how can we get our application to listen out for this? Well firstly we need to say that our programme is interested in these events. We do this by using VB 2005’s WithEvents keyword when we create our interface into iTunes.

So previously we did this using the following code.

Dim app As New iTunesApp()

Now we have to add in the WithEvents keyword as follows.

Private WithEvents app As New iTunesApp

Now our program can listen out for events from iTunes. You may have noticed I’ve changed Dim to Private. This is because for this example I’m going to use a Windows Application and not a Console application as before.

Next we have to create our event handler so we can react to the events iTunes is sending us.

The easiest way to do this is use the method generator at the top of the code view in Visual Basic 2005 Express Edition. My iTunes object is called app so we select this, then OnPlayerPlayEvent to create our event handler stub.

Creating an iTunes event in VB2005

This passes in the variable iTrack as an Object. We know this is really an IITTrack object, so we need to cast it as such.

Dim track As IITTrack
track = CType(iTrack, IITTrack)

This creates a new varible called track and casts the existing iTrack variable as an IITTrack using CType.
Doing this, we have easy access to the track data passed to us by iTunes in the event.
We need to do something with this information seeing as we’ve gone to all the trouble of asking iTunes for it. The easiest thing to do is to just display a small window with the name of the current track.

MsgBox(track.name)

Obviously this is a simplified version of a real program, but it should give you an idea of how to get events from a remote program into your VB2005 application.

iTunes Now Playing in VB 2005

As I’ve been using VB 2005 a lot more a work the past few weeks, I thought I’d rewrite my iTunes Now Playing console app in VB.

It does the same as the previous C# example, and again I’ve chosen to use the free version of the language and Microsoft’s Visual Basic 2005 Express Edition.

The first thing to do, is to make sure you have downloaded the iTunes SDK from Apple.

In Visual Basic, create a new Console Application. We need to add a reference to the iTunes COM library, so we do this by right clicking over our application in the Solution Explorer, and selecting “Add Reference…”. Select the COM tab, and scroll down to find the iTunes library. Mine was called “iTunes 1.7 Type Library”.

adding the iTunes COM object to VB 2005

Now for some code.

Firstly, like all good programmers we turn on VB’s strict mode to make sure we’re not using too many bad programming practices.

Option Strict On

Next we need to import the libraries we want to use. In this case, System> and iTunesLib.

Imports System
Imports iTunesLib

As we’ve created a Console App in VB, we can just drop the following code into the Main sub.

Firstly we need to create an iTunesApp object so we can get talk to iTunes. After that we need to get the current track.

Dim app As New iTunesApp()
Dim track As IITTrack = app.CurrentTrack

We should now have the details of the current track in the track object so we just need to print these to the console.

Console.WriteLine("Current Track: {0}", track.Name)
Console.WriteLine("Current Artist: {0}", track.Artist)

Finally, just so we can see the result we need to wait for the user to press return before we exit.

Console.ReadLine()

Fire up iTunes if it’s not already on and start a track playing. Now start your VB program, and it should tell you the current track title and artist as shown below.

iTunes now playing script

It’s as simple as that. Obviously I’m not checking for exceptions and errors as this is just an basic example.

Your final code should look something like this.

Option Strict On
Imports System
Imports iTunesLib
Module Module1
Sub Main()
Dim app As New iTunesApp()
Dim track As IITTrack = app.CurrentTrack
Console.WriteLine("Current Track: {0}", track.Name)
Console.WriteLine("Current Artist: {0}", track.Artist)
Console.ReadLine()
End Sub
End Module

iTunes Now Playing In Perl

After working on the C# iTunes Now Playing program, I thought I’d give the Perl Win32::OLE module a try.

This module is Activestate Perl‘s COM interface for Microsoft Windows.

After using Perl for nearly 8 years, I’ve never given it a try before, and it turns out to be surprisingly easy to use.

The following script works exactly the same way as the C# version.

Firstly we need to create a new iTunes.Application object.

my $iTunesApp = new Win32::OLE("iTunes.Application");

Next we get the current track and print the name and artist.

my $track = $iTunesApp->CurrentTrack;
print "Current Track: " . $track->Name . "nCurrent Artist: " . $track->Artist . "n"

And that’s it. Obviously we should be checking to make sure the objects were create correctly, but this is just a simple example, not live code.

So to recap, here’s the final working example code.

#!/usr/bin/perl

use strict;
use Win32::OLE;

my $iTunesApp = new Win32::OLE("iTunes.Application");
my $track = $iTunesApp->CurrentTrack;

print "Current Track: " . $track->Name . "nCurrent Artist: " . $track->Artist . "n"

iTunes Now Playing In C#

I’ve been playing about with the COM interface to Apple’s iTunes running on a windows machine with .NET installed.

My choice of language has been C# as it’s a bit more Perl like than VB. I’ve used Microsoft’s “free” Visual C# Express in this case.

The iTunes SDK is available from Apple and has all the documentation needed.

I’m going to run through how to get Now Playing information out of iTunes. The quickest way to do this is as a console application.

Start up Visual C# and create a new console application. I called mine NowPlaying.

You’ll need to add a reference to the iTunes come library. Do this on the righthand side of the C# project window by right clicking and selecting “Add Reference…”, selecting the COM tab, and finding the iTunes library.

The first thing you’ll need to in your code is to import the iTunes namespace to make the code look a little cleaner. We’ll also need the System interface for our console input and output.

using System;
using iTunesLib;

In your Main method, the first thing we need to do is to create an instance of the iTunesAppClass. I’ve rather originally called mine, app.

// Create a new iTunesApp object to use
iTunesApp app = new iTunesAppClass();

Next we need to get the current track. This is a simple attribute call to the app object.

// Get the current track from iTunes.
ITTrack track = app.CurrentTrack;

Finally we need to show the current track. To do this we call two attributes on our track variable, name and artist. There are plenty of other attributes we could call, but these are the two most useful for this example. See the SDK for more choice.

Once we have displayed our name and artist, we need to wait for the user to hit return. This is useful if our program wasn’t launched from a console window as it would end before we’ve had a chance to read any output.

// Display some info on the current track.
Console.WriteLine("Current Track: {0}rnCurrent Artist: {1}" , track.Name, track.Artist);
// Pause until we hit return.
Console.ReadLine();

That’s it, nice and easy.

Here’s the full .cs source code.

using System;
using iTunesLib;
namespace NowPlaying
{
class Program
{
static void Main(string[] args)
{
// Create a new iTunesApp object to use
iTunesApp app = new iTunesAppClass();
// Get the current track from iTunes and return its artist and name.
IITTrack track = app.CurrentTrack;
Console.WriteLine("Current Track: {0}rnCurrent Artist: {1}" , track.Name, track.Artist);
// Pause until we hit return.
Console.ReadLine();
}
}
}