RESTful Web Services in .NET (Part 1)

A couple of years ago I tossed together a RESTful IHttpHandlerFactory for .NET. It wasn’t amazing, but it was being used long before Microsoft et all decided to create there own. Instead of extending Page you extended RestService and implemented whatever methods you wanted.

public interface IRestService
{
	void Head(RestEventArgs args);
	object Get(RestEventArgs args);
	object Put(RestEventArgs args);
	object Post(RestEventArgs args);
}

As you can probably guess the request’s HTTP Method was transformed into the function name and executed accordingly. If the method wasn’t “known” we would then use reflection to find the method for execution. Not to fansy as you can see, but it worked.

If a request was made for http://localhost/app/users.r the IHttpHandler factory would load users.r and it would tell us what class you assigned to it (much like @Page CodeBehind/Inherits in .aspx). From there we would instantiate the class and call the appropriate method. Whatever you returned would be marshalled for wire transfer based on it’s type.

	class User : IXmlSerializable
	{
		/* ... */
	}
    
	public class UserService : RestService
	{
		public object Get(RestEventArgs args);
		{
			return new User(5, "Matthew", "Metnetsky");
		}
	}
}

Calling http://localhost/app/users.r would execute UserService::Get(..) which would return a User instance. The results are then inspected for a few different interfaces like IXmlSerializable, IJsonSerializable (one of ours), etc. Based on what is supported by the Type, we then check if the requester supports it by interogating their “Accepts” header. This way each requester can receive what they understand how to handle (for instance – don’t send JSON to AS3). The system really worked well, and it’s simplicity made it damn fast.

Like all frameworks however, once it was actually in use we were able to see the pitfalls and issues. Take a look at the following URLs:

  • http://localhost/app/users.r
  • http://localhost/app/users.r/1
  • http://localhost/app/users.r/matthew

In order to handle all of the urls above the Get(RestEventArgs) method turned into one big switch/if/else conditional. Some people made it prettier than others, but the result was the same. So about 14 months ago we upgraded our framework – check back soon to see how we did it, and why I’m bringing it up now.

PMS2 – Coming Soon to an Interweb Near You

A long, long time myself and two friends were working on a college project where the entire goal as I saw it was to “create” stuff. Mono was a wee lad back in 2003, but I still preferred it to Java any day of the week. So myself, Phil Tricca, and Joseph Scaduto created a whole framework for creating what are now called “learning communities” in Mono/Gtk#/mod_mono.

One of the pieces we needed was a databases abstraction layer (we had grand ideas) so we first sought to flush out the ObjectSpaces API for Mono. Sadly, Microsoft couldn’t get their act together so we built our own. So in honor of Microsoft we called it Phil-And-Matt Spaces, shortened to PMS. After it’s original debut it sat on the selves for quite some time until I started working for Konica Minolta Business Solutions and was tasked with creating Printgroove. PMS hit the spot (man that sounds funny) – it was far from bad, but it certainly wasn’t awesome. At the point of its resurrection it needed a face lift, but never got one.

It’s now been years since Printgroove got started and PMS has continued to work well for it and numerous other projects – but I’ve got an itch that must be scratched. So while working on a small web service only project I’ve been adding in a couple dozen extra hours to mature PMS – or basically throw away it’s entire user facing API.

Here’s a sneak peak of whats to come:

// - Pull IDbConnection from pool based on unique name (from config file)
// - This is useful if you have multiple databases to chat with
// - Not specifying a name will load the one marked default or the first one found
using (DbBroker cxt = new DbBroker("name-mapping-to-config-connection-string")) {

    // SELECT member.* FROM member WHERE username LIKE '%a%' ORDER BY id
	// Enumerate through results without storing Member objects in container
	foreach (Member m in cxt.Query<Member>().Like("username", "%a%").OrderBy("id").Exec())
		Console.WriteLine(" : " + m);
    
	// Use raw SQL and ignore chainable methods for generation
	// Store results in List<Member> and then iterate through it
	string sql = "SELECT member.* FROM member where username LIKE '%a%' ORDER BY id";
	foreach (Member m in cxt.Exec<Member>().Objects<List<Member>>(sql))
		Console.WriteLine(" : " + m);

	// get first member
	Console.WriteLine("first: " + cxt.Query<Member>().Exec().First());

	// a short-cut to get the first member since we aren't filtering etc
	Console.WriteLine("first: " + cxt.Exec<Member>().First());

	// SELECT COUNT(member.*) FROM member WHERE id > 50000
	// Use generics to cast the output of ExecuteScalar to an Int32
	Console.WriteLine("count: " + cxt.Query<Member>().Filter("id > 50000").Exec().Count<int>());

	// Directly call ExecuteScalar but use generics to cast the output
    sql = "SELECT id FROM member WHERE username='mimetnet'";
	Console.WriteLine("scalar: " + cxt.Exec<Member>().Scalar<int>(sql));

	// Directly call ExecuteReader() with our generated SQL
	// SELECT id,username FROM member WHERE id > 68665
	using (IDataReader reader = cxt.Query<Member>()
									.GreaterThan("id", 68665)
									.SetColumns("id,username")
									.Exec()
									.Reader()) {
		while (reader.Read()) {
			Console.WriteLine("Member(id={0}, name='{1}')", reader[0], reader[1]);
		}
	}
}

Please send me your thoughts/concerns/nightmares.

PHP Annoyances: header()

Earlier today, and yesterday in fact, I was successfully downloading generated PDF’s from a FLEX application from an Apache2 server via mod_php5. Tonight however, it kept failing with an IOErrorEvent #2038. There’s lots of fun references to this issue like this one. Sadly downloading via FileReference doesn’t trigger the HTTPStatusEvent event, so I can’t lie to FLEX.

I eventually stopped brute forcing an attempt and intelligently looked at Apache2′s logs and found this wonderful line:

10.10.220.130 – - [10/Feb/2009:20:24:16 -0500] “GET /vrm/Create_Report.php?download=vrm_report_17_10-10-220-130.pdf HTTP/1.1″ 1 68856 “-” “Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; …)”

Do you notice whats wrong? No? Look for the 1 after “HTTP/1.1″ and before the “68856″ – this is where the HTTP Status Code should be. Eh? What happened? Where’d my status go? The server-side looked like this:

if (file_exists($file)) {
	header('Content-Type', 'application/octet-stream', true);
	header('Content-Disposition', 'attachment/filename=' . $filename, true);
	header('Content-Length', filesize($file), true);
	header('Content-Description', 'File Transfer');
	readfile($file);
}

Any one notice the issue – header is being use inappropriately. The first argument should be the entire response header, the second argument is the option to override a matching header, and the third is the status code. “true” evaluates “1″ and thus the status of 1. You might ask as I am right now: Why is he divulging that he’s an idiot? Well folks it goes like this:

It’s 10:55PM and I’ve been programming since 8:30AM to meet a deadline. Things get missed and stupid mistakes happen. The above code worked on (IIS 6 + PHP5) but failed on (Apache2 + PHP5) – and this is one of the many reasons I hate PHP. The second argument should be a boolean and should SCREAM to the error log if you don’t match the type expected. Instead it says nothing, and leaves you to your madness.

Anyways, lets fix the code and go home!

	header('Content-Type: application/octet-stream', true, 200);
	header('Content-Disposition: attachment/filename=' . $filename, true);
	header('Content-Length: ' . filesize($file), true);
	header('Content-Description: File Transfer');

10.10.220.130 – - [10/Feb/2009:22:14:15 -0500] “GET /vrm/Create_Report.php?download=vrm_report_1_10-10-220-130.pdf HTTP/1.1″ 200 68856 “-” “Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; …)”

Gah ;-0

Replacing Flex’s Timer with Event.ENTER_FRAME

One of the projects I’m working on, as you might have guessed, utilizes Adobe’s AIR. After reading a few dozen optimization tips it sounded like I needed to replace four internal Timer‘s because they aren’t very efficient. As I couldn’t find anything off-hand that suited my needs I rolled my own (with some optimizations by Noah Massey).

The original code looked similar to:

private var timer:Timer = new Timer(15000); // run every 15 seconds

private function onCreation(event:Event):void {
	this.timer.addEventListener(TimerEvent.TIMER, this.onTimer, false, 0, true);
	this.timer.start();
}

private function onTimer(event:TimerEvent):void {
	/* do something */
}

I didn’t want to totally refactor all of my code because that would have been an amazing waste of time. So I ran through my usage of “timer” and realized what I needed to be able to do:

  • start
  • stop
  • change interval
  • create run-once functions like setTimeout, but tied to frames

With this in mind I typed up what I wanted and after a bit of tweaking my usage now looks like this:

private function onCreation(event:Event):void {
	FrameActivity.assign('someName', 15, this.onTimer);

	this.addEventListener(Event.ENTER_FRAME, FrameActivity.handleFrame, false, 0, true);
}

private function onTimer(event:Event):void {
	/* do something */
}

If you like what you see, send me a comment and I’ll happily provide the code.