Wednesday, August 31, 2011

This has always annoyed me in Star Wars


Click for full res image


Friday, September 3, 2010

How Far Computing Has Come:1970-2010

Back in the 1970s the first Cray Supercomputers were the be-all and end-all of computing. They were like the Bugatti Veyrons of computer processing and here are some photos of these behemoths… giant mofos that could chew through bits and bytes like nothing else.


Well over the decades computers have obeyed Moore's Law and processing power has vastly improved while the space required has lessened and to demonstrate just how far we've come check out this guy's replica Cray as a PC… with soft leather “seats” for tiny programmers!


But then this guy takes it one step further and not only made a tiny replica, it actually EMULATES the Cray!!!

Description: http://www.blogcdn.com/www.engadget.com/media/2010/08/100831-cray-01.jpg Description: spartan3_1600

There are still Crays in service today but they're the newer more complex machines, not these old (albeit still complex) dinosaurs. We sure have come a long way!

Thursday, September 2, 2010

"Endless Scrolling" With An ASP.Net DataPager

On the front page of MotorShout we have quite a complex news feed which allows you to filter the feed by news type (e.g. news, new photos/videos, forum posts etc.) and even further filter that by selecting one or more manufacturers. I've managed a lot of the messy stuff with views in SQL Server and a stored procedure that brings it all together. Until this morning the feed would display 20 items sorted by date depending on your filter settings but now, now you can get much more.

The Challenge

Make this tricky mess of data sources be able to display more than the 20 top records if the user wants to see more.

How I Did It

Now, the existing news feed was based around a ListView inside an UpdatePanel and I didn't want to go down the path of totally rewriting in AJAX as everything was already in place and working nicely. That lead me down this path.

My first thoughts were to use some kind of paging in SQL Server to get it to throw the web server 20 records at a time or to grab a large set of records and cache them on the web server and serve them up to the user 20 records at a time. But in the end I went with something much easier to implement and actually quite speedy as it turns out.

The idea I ran with was quite simple and was just a matter of increasing the PageSize on a DataPager in the ListView with each PostBack until I ran out of records. This may cause problems if you are displaying thousands of results but I've limited my results to the top 100 but that's still 5 times the original page size. I may increase in future if it's not too big a performance hit.

The first step was to add a DataPager to the ListView with a PreRender event handler (we'll get back to this later). Pretty straightforward. This is my LayoutTemplate in the ListView, note the lack of a PageSize set on the DataPager. Also, the content in the news feed is static so I've disabled the viewstate.

<asp:ListView ID="NewsFeedListView" EnableViewState="false" OnDataBinding="NewsFeedListView_DataBinding" runat="server">
<LayoutTemplate>
<asp:DataPager ID="DataPager" OnPreRender="DataPager_PreRender" runat="server" />
<asp:PlaceHolder ID="ItemPlaceholder" runat="server" />
<LayoutTemplate>

The next step was to add a button somewhere outside the ListView but still inside the UpdatePanel to trigger a PostBack to get more records. I also added a Literal for when we've run out of records (see the PreRender method on the DataPager below for what I do with this). For the sake of brevity I've left out some fiddly stuff to display a spinner next to the button so the user knows something is happening.

<asp:LinkButton ID="GetMoreResults" OnClick="GetMoreResults_Click" runat="server">Get more results...<asp:LinkButton>
<asp:Literal ID="NoMoreResults" EnableViewState="false" Visible="false" runat="server">No More Results </asp:Literal>

I also added a HiddenField (you can use whatever you like but this keeps it simple) control for keeping track of how many records we are currently displaying. This needs to be inside the UpdatePanel!

<asp:HiddenField ID="CurrentPageSize" runat="server" />

OK, now we're ready to do some code. In my Page_Init() I put the initial setting for our HiddenField making sure it doesn't run if we are in a PostBack. Instead of hardcoding the number (like below) I set a global constant but you get the gist of it.

protected void Page_Init(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
this.CurrentPageSize.Value = 20;
}
}

Next I added the Click event handler for the "get more" button. Here I just needed to increment the CurrentPageSize value to be used by the DataPager, store that in our HiddenField then rebind the data.

protected void GetMoreResults_Click(object sender, EventArgs e)
{
int currentPageSize = int.Parse(this.CurrentPageSize.Value);
if (currentPageSize > 0)
{
currentPageSize = currentPageSize + 20;
this.CurrentPageSize.Value = currentPageSize.ToString();
}
this.FilterTheNews(); // My method to rebind the listview
}

The penultimate step was to add in a DataBinding (not DataBound!) event handler on the ListView. This is where I set the PageSize of the DataPager to the new larger number.

protected void NewsFeedListView_DataBinding(object sender, EventArgs e)
{
var pager = NewsFeedListView.FindControl("DataPager") as DataPager;
int currentPageSize = int.Parse(this.CurrentPageSize.Value);
if (pager != null && currentPageSize > 0)
{
pager.PageSize = currentPageSize;
}
}

And now the cherry on top, the PreRender method for the DataPager I mentioned above, which simply hides the "get more" button if we are out of records and shows the "no more records" literal. It checks if the current page size is more or equal to the total number of records and if so, we've maxed out our records.

protected void DataPager_PreRender(object sender, EventArgs e)
{
var pager = sender as DataPager;
int currentPageSize = int.Parse(this.CurrentPageSize.Value);

if (currentPageSize >= pager.TotalRowCount)
{
this.GetMoreResults.Visible = false;
this.NoMoreResults.Visible = true;
}
}

So there you have it! Pretty simple stuff and with the help of the UpdatePanel you give the user the impression that they're adding more records to a growing list.

Wednesday, August 18, 2010

Rockin' Visual Studio 2010's Productivity Power Tools

After listening to a recent podcast (sorry, can't remember which one!) on the joys of the Productivity Power Tools for Visual Studio 2010, I thought I'd give them another go. You see, I installed them on the same day I first installed VS2010 but it was all too much for me coming from VS2008 so I immediately removed the tools.

Well, on my second go-around I'm loving the control you now have over the document tabs. Three things in particular: vertical tabs, alphabetically sorted tabs, pinned tabs and regex colored tabs... ok, that was four things.

In the past I used to have to put up with VS2010 being able to show about 5 or 6 open documents via the tabs (I run duel 22 inch LCDs at some weird-ass resolution), anything else and I'd have to go to the annoying little drop down arrow. But check out this screenshot of my current layout with vertical tabs, not sure how many tabs I could get in there but it'd easily be 30-odd and they'd all be easily readable.

Using the regex colored tabs means each different file type has a different color plus I've set parent/child documents to be different shades of the same color (see the aspx and aspx.cs files and the ascx and ascx.cs files?). It ain't pretty but man can I find the file I'm after quick smart!

Having the tabs sorted alphabetically means related documents are stacked on top of each other, again making things easier to get at.

Lastly, pinning tabs means frequently accessed files are always in the same spot. I have my web.config and default.css within easy reach. No more hunting around in the Solution Explorer. Yay!

Here are my settings (click for full res):



Monday, August 16, 2010

Scott Pilgrim vs Big Studio Advertising Budgets

Hey you! Yes you there in the shirt and socks. Stop reading this and go watch Scott Pilgrim vs The World! You can thank me later.

What? You're still here? Sheesh, if you don't believe me maybe you'll believe this person. Go, begone with you! Come back when you're $15 poorer and 100% happier.

OK, maybe you can watch this trailer but don't let it put you off the movie. I was unimpressed by the trailer so I'd prefer you didn't watch it... but you've already proven you don't listen to me.



bye!


Thursday, August 12, 2010

Freddie Wong Meets Spartacus

If you haven’t been following Freddie Wong’s (self-proclaimed B-List Internet Celebrity) crazy series of videos on YouTube then this one might get your attention.

Andy Whitfield of Spartacus: Socks and Sandals Blood and Sand fame saw this video of Freddie’s




...and loved it so much he wanted to get in on the action. So Freddie decided it’d be a good opportunity to do a Time Crisis video in real life and they ended up with this...



This is the behind-the-scenes video with Andy Whitfield who mentions he’s heading off to shoot season 2 of Spartacus.

Some of my favourite videos of Freddie’s in no particular order:

Wednesday, August 4, 2010

English, Consider Yourself Destroyed

As seen in a support email sent to me ...

"when i create my own pic how to do i send it to a freind on face book" [fully sic]

Alas poor English, I knew her well.


Wednesday, June 30, 2010

Riley Freeman is The Karate Kid

I just got some spam from Sony Pictures for the "remake" of The Karate Kid (note: there is no karate in this film, it's all kung fu) and there was a photo of Will Smith's kid Jaden who plays the protagonist alongside Jackie Chan. If you're a fan of Adult Swim's The Boondocks you'll recognise this kid immediately.

Yes folks, that kid is the spitting image of one Riley Freeman, the wannabe gansta youngest grandson of Robert Freeman. Check it...

What makes this even more humorous is that both the film and the TV show are property of Sony Pictures International. Cross promotion maybe?

Friday, June 25, 2010

Excel Formulas are Like Latin

I'm doing a spot of data manipulation and importing for MotorShout at the moment and am currently importing every Mercedes-Benz ever. Sounds like fun? Not really. Anyway, the source data is in an Excel spreadsheet which I'm modifying to match up with our existing SQL Server input table. The input data for Mercedes-Benz is missing the car name’s prefixes. e.g. "CLK500" is missing the “CLK” but I do have the "500" and the “CLK-Class” family name in other columns. I want to merge the “500” with the “CLK” from the family name to get the model name. Easy peasy? Hardly!


Here is the alien Excel formula that rubs my 15 years of coding experience the wrong way:

=CONCATENATE(IF(ISERROR(SEARCH("-Class",B2)),"",SUBSTITUTE(B2, "-Class","")), D2)

Why is this alien? Well for a start a simple Replace() method would have done this job fine except Excel already has a REPLACE() function... which replaces text at the given indexes, WTF? OK, so they have SUBSTITUTE() that does what I want, fair enough, let's get on with it.

OK, now what if the family name doesn't contain "-Class"? I don't want to prefix the model name in that instance so my first thought is I'd use an InStr(), or IndexOf() or Contains() method to check if the string is in the family name, sorry wrong again! I have to use Excel's SEARCH() function. But do you know what makes SEARCH() oh so special? If the string isn't found in the source it THROWS AN ERROR! The endlessly helpful #VALUE! error, fun times indeed. In their wisdom Microsoft therefore ensured Excel has an ISERROR() function which, you guessed it, checks for an error. Sorted!

Finally, a simple IF() statement wrapping that ISERROR() condition and we're almost there. Just need to concatenate (yes, the function uses that name) the newly trimmed out family name with the model name and voila! Simple!

*sigh*

This is what I would have liked to write (C# mashed into Excel please!):

=B2.Contains("-Class") ? B2.Replace("-Class", " ") : "" + D2;


Wednesday, June 23, 2010

What Is Wrong With Alan Wake's Facial Animation

Last night I played the first couple of hours of Alan Wake and the game is good fun. A little bit of Left 4 Dead mixed with a dash of Doom 3's flashlight and other bits and pieces. The game was originally intended to be the big DirectX 10 demo for Windows Vista but somehow wound up being an Xbox 360 exclusive.

The locations and environmental effects in the game look fantastic but there is one thing that stands out as freakishly bad (other than the Lincoln, Sync and Energizer product placements), the facial animation! Every time I watch a cut scene I cringe, here's why.

I've just recently finished Mass Effect 2 and Final Fantasy XIII, here's what their facial animation looks like as a comparison for the horror that follows.

Mass Effect 2

Final Fantasy XIII

Now, my friend says Uncharted 2 on the PS3 looks amazing and who am I to disagree?

Uncharted 2
(not sure if this is ingame but it looks it to me)

...and now Alan Wake *shudder* (make sure you wait to see Rose)

So as you can see... FREAKY! It reminds me of this classic

Thursday, January 7, 2010

Welcome To the Future

I had a taste of the future today, the future that we already live in. It all started when Microsoft's Larry "Major Nelson" Hryb started tweeting about behind-the-scenes goings on at the lead up to Microsoft's CES Keynote. His tweet read, "Steve B is just walked by me...wearing a very red sweater . We are getting ready to start". Steve B in this instance is Steve "Developers, developers, developers" Ballmer, CEO of Microsoft, who was to do the talking at the keynote.

Things got more interesting as I started to watch the live stream of the keynote which was being pushed out across the internet from Las Vegas to anyone with a browser and the Silverlight plugin. The audio level was pretty low and I had to bump my system volume up to maximum in order to hear what was going on. Then Major Nelson tweeted this, "Told the stream dudes about the audio level. They're fixing"... was he in my head? No, other watchers had tweeted back to Major Nelson about the audio level.

The left channel dropped out then came back as the right channel then dropped out. When the audio stream returned in stereo at a much improved level The Major asked, "
Let me know how the audio is....they tweaked it." Myself, and I'm sure many others, replied to say that all was good which prompted Larry to offer up a final tweet on the subject, "I brought the streaming to my PC to see your tweets about audio. You guys helped fix it :)"

It was at that moment that I really thought about what was going on. It might sound like ordinary day-to-day goings on but seriously, I was watching a live video of Microsoft's head honcho half way around the world giving a speech to thousands of people while at the same time I was communicating directly with another Microsoft senior employee who was doing techy stuff in the wings. Can you imagine doing that just a few years ago? We really are living in the future.

Wednesday, November 18, 2009

LINQ To SQL Profiler And How To Swing It

[warning: technical post]

My friend showed me a cool profiler the other day by the smart chaps at Hibernating Rhinos which lets you see what is going on behind the scenes of the magic black box known as "LINQ To SQL" (L2S). I've been using LINQ to SQL for almost 2 years now and while it's far from perfect it makes my job (life!) much easier. Unfortunately by hiding the inner workings away from the developer by the time you come to look at the performance of your website (or desktop app) you're pretty much left in the dark. That's where L2SProf comes in. It hooks into your datacontext and gives you a great view of what's happening back there...


Now, the set up is pretty straightforward with L2SProf and involves adding a reference to a single DLL into your app (web or otherwise) then copying and pasting a single line of code into your startup method (e.g. Application_Start in global.asax for a website). Once you've done that you restart your application, crack open the included L2SProf.exe and voila, your LINQ to SQL datacontext's secrets are no longer secret... unless you're me. I got a big fat nothing.

After trying to sort it out with my friend and failing I jumped onto the support forums and posted a quick message asking for help. There was a bit of to-ing and fro-ing over email with not much accomplished. Then Oren Eini (AKA Ayende Rahien) popped onto the scene (then Skype) to give me some help.

First we tried writing the profiler data to a text file (a slight modification to that single line of code I mentioned earlier) and while the log file was created, nothing was written to it. Next we created a brand new web application from scratch and everything worked with the profiler showing my single datacontext call and its corresponding SQL code. Oren looked over the web.config from my original website and decided the problem wasn't in there. After fiddling around some more we came across a little bit of code I'd put in place to stop Visual Studio from trying to read my connection string from the data model project's app.config. This was our "aha" moment.

Normally you'd either have your DBML file (LINQ to SQL datacontext) in your website or if it's out in another project in your solution, you'd let Visual Studio control the database connections by dropping them into the app.config, that's not how I had it set up. This is the method I had in place in my DataContext.cs...

public MyDataContext() : base(ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString)
{
OnCreated();
}


I'll let Oren explain what was going on here...

"The problem with doing it this way is that you are forcing L2S to build a new model every time that you create a data context, that is quite expensive, from a perf point of view. L2S have to use reflection to get the values each and every time. A side affect of that is that it also kills the way L2S Prof works. Here is how to make it both performance and work with L2S Prof:"

public MyDataContext() : base(ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString, mappingSource)
{
OnCreated();
}


Once we did this everything fell into place, data access information pouring out of my website. So there you go, once again proving that if you don't do what Visual Studio wants you to do you can get into trouble.

Thanks a lot to Oren for his help and patience in helping me solve this problem. Now I need to go see how badly my website is performing.

Monday, October 19, 2009

Using Microsoft Ajax Minifier with Deployment Projects

It's been a while since I did a post here but this is worth it. Yesterday Microsoft's Scott Guthrie announced the new Microsoft Ajax Library (Preview 6) and the Microsoft Ajax Minifier. While I haven't checked out the new Ajax library I have had a bit of a play with the minifier.

Seeing as I was on the look out for a Javascript minifier for my current project this came at quite an opportune time. I found Stephen Walther's immensely helpful blog post about setting the Ajax Minifier to run automatically each time you build your project (you should go read that now before continuing here). The only problem with Stephen's sample is my current ASP.NET solution is set up in such a way as my website is a Website, not a Web Application so I don't have a .csproj file to edit.

Fear not! For I have found that I can simply transpose Stephen's sample code over to my deployment project's .csproj file with similar results. The following is the required markup from my deployment project's csproj file to generate minified scripts on the fly after deploying my website. I placed this at the very end of the markup, just before the closing </Project> tag.

CODE:


<PropertyGroup>
<BuildDependsOn>
$(BuildDependsOn);
MinifyJs
</BuildDependsOn>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\MicrosoftAjax\ajaxmin.tasks" />
<Target Name="MinifyJs">
<ItemGroup>
<JS Include="$(OutputPath)\js\*.js" Exclude="$(OutputPath)\js\*.min.js" />
</ItemGroup><AjaxMin SourceFiles="@(JS)" SourceExtensionPattern="\.js$" TargetExtension=".min.js" />
</Target>


Should look something like this:


The big difference here is the min.js files are generated on the fly in the DEPLOYED website (that'd be the $(OutputPath) location. Also, but not as important, my javascript files are in a folder called "js" unlike Stephen's which sit in the root of the site.

So there you go, minified Javascript files in your target site.

Sunday, April 5, 2009

Monsters vs Aliens' Monster Cast

I took my eight year old daughter out this morning to see the 10am session of Monsters vs Aliens, Dreamwork's latest 3D animated feature. I picked a few of the voices but when I saw the credits roll past at the end (GIANT credits I might add!) I knew almost all the names. It was this that lead me to make this list characters-to-actors so you too can see just who was in the film. You should go and see it by the way, quite entertaining with plenty of monster movie/sci fi in-jokes (there's even a Wilhelm Scream) including a hilarious Close Encounters homage with a genuine Yamaha DX/7 synth.

Susan Murphy/Ginormica - voiced by Reese Witherspoon



B.O.B - voiced by Seth Rogen


Dr. Cockroach Ph.D. - voiced by Hugh Laurie


The Missing Link - voiced by Will Arnett


General W.R. Monger - voiced by Kiefer Sutherland


Gallaxhar - voiced by Rainn Wilson


President Hathaway - voiced by Stephen Colbert


Derek Dietl - voiced by Paul Rudd


Wendy Murphy - voiced by Julie White


Carl Murphy - voiced by Jeffrey Tambor


Spaceship Computer - voiced by Amy Poehler


News Reporter - voiced by Ed Helms


Katie - voiced by Renée Zellweger


Cuthbert - voiced by John Krasinski


This is the 3D Super Bowl trailer for the film: