Skip Navigation Links

Posts for: Aug 2006

Working with other Virtual workers

At times my family and friends have asked about my job and how I manage to stay in touch with my co-workers.  For example, my mother simply cannot comprehend that we don't share a physical office and argues that I couldn't possibly keep in touch with my workmates... However I'd argue against that though because there are so many ways to keep in touch with people if you know what you're looking for :-)

 Virtual Barometer

For example by looking at Live Messenger I see that Grant is probably looking for help moving into his new house this weekend.

posted on 8/31/2006 8:36:14 PM ( 1 Comments )


Why night programmers look forward to their evenings

Given that I've somewhat stumbled into Open Source development of late - new major release of  BlogML due out this week and new open source project to be announced shortly hopefully - this article is probably right up my alley... well, that's if I ever get to work on code again :-)

Link to What's the difference between working on an open source project and working on a paid job | TortoiseSVN

posted on 8/31/2006 6:57:49 PM ( 0 Comments )


Is this the first sign that you are truly a virtual worker?

I've stopped wearing a watch :-)

Hand of Virtual Worker

posted on 8/31/2006 1:37:01 PM ( 5 Comments )


Live.com and Digital Identity - Part 2

The other day I posted a quick rant about my feelings towards digital identity and Live.com and today I'll add another one - the identity of your Space.

On the Spaces site there is an FAQ article which clearly articulates some of the privacy considerations that you should have when engaging online.  The FAQ is titled "Top tips for safer Windows Live Spaces" and lists the following items as security concerns:

  • Think very carefully about how public your space is
  • Keep identifying details to yourself
  • Know who your friends are
  • Be cautious about sharing your feelings
  • Be smart about your photos
  • Check on what your friends write about you
  • Never meet an Internet “friend” alone in person. It’s dangerous.
  • If you think there’s a problem, report it. Immediately.

In my previous blog article I discussed the first item on that list and described some of the scoping features that Spaces has for limiting your security exposure.  Points 2 and 3 are also items that increase your "attack surface".  After thinking about it for a while I actually changed the name of my Space to remove some personal information.  I know that it's a small thing but anything which puts an abstraction between me and my online identity is probably a good thing. 

Spaces is a cool thing but I think that it's important to understand that the big portals that we see being built today are potentially the dangerous playgrounds of tomorrow.

posted on 8/30/2006 5:45:32 AM ( 0 Comments )


Frank's talking at a corporate blogger conference

I almost fell over when I read Frank's post about his upcoming gig speaking at a corporate blogger conference.  It wasn't the fact that I wondered how Frank gets the time to do this stuff; it wasn't that I was amazed that the corporate types have picked up on blogging; it sure as heck wasn't the $900 per ticket price tag (I knew that Frank wouldn't be cheap :)).  The thing that knocked me over was that this conference starts tomorrow! Now I probably could have found the $900 somewhere but I really doubt that I'll be able to get things organised to be there at that short notice.

Frank, I'll be interested to hear what the corporate types think about blogging and IP so hopefully that gets touched on.  If not can you ask this question for me please.

Let's say that I'm Microsoft and I have great people who know lots of cool stuff about the industry.  Many of my people have public facing blogs and, because they are smart and because they are connected to such a well known company their blogs attract a large readership.  Over time this readership and reputation of some employee blogs grows to the point where those employees can make good sums of money from advertising.  And for the best of those people other opportunities also present themselves - such as companies giving cash and other incentives to the employee to promote their products.  What is the right corporate policy to have in place there?

 

posted on 8/28/2006 5:47:11 AM ( 0 Comments )


Live.com and Digital Identity

Ever since Tech.Ed my head has been spinning with thoughts about Live.com.  I was having those throughts at dinner on Thursday night, while drinking shots of Vodka at the party, when I should have been sleeping before my presentation on Saturday and even during the presentation itself.  It would be fair to say that, presently, I'm totally consumed with throughts about Live.com.

I won't ramble too much about why I think that Live.com will have a profound effect on us all in the way that we manage our social networks and also on how we buy stuff - through presence awareness.

I'm not sure how far away this stuff is just yet because I haven't delved around enough in hte backend but with the amount of data that will be floating around and the value that will be attributed to that - by many interested parties in a wide variety of ways - it will be interesting to see how people go about managing their identity on Live.com.

With Live, you can expose different pieces of personal information to specific areas of your social network.  For example, I might make my own personal information public - such as the fact that I'm 38, live in Australia, a Resource Manager for a kick-ass IT company, and my interests.  But I might limit other identifying information - such as where in Australia I live, where I went to school, my Surname, and my wife's name - to only my Instant Messenger Contacts.

There are 4 different scopes that you can use to expose different parts of your identity, they are: Everyone, Messenger Contacts, Friends and Messenger Contacts, and Friends, Friends of Friends and Messenger Contacts.

In choosing everything from the name of your space (mine is showusyourcode) through to what photo's you share you are making decisions about who can find you, who can advertise to you, and so forth.  The challenge is to really work out how to use those scopes to maxmize your reach without comprimising your safety.

The part that keeps me awake at night is the belief that there are incredible opportunities that will appear as a result of this platform and working out how to leverage that potential.

posted on 8/27/2006 9:58:04 PM ( 0 Comments )


Vote for Jem on TripleJ Unearthed.

The other day I blogged about the new website that I released for Jem.  Since then we've had a wave of hits and have started looking around for ways to promote the site and get more people listening to his music.  I've contacted a couple of Podcasts that I listed to, so hopefully he'll get some good coverage from those.

Luckily this is also the time that the TripleJ Unearthed contest is on.  This is probably the biggest contest in Australia for unearthing great new Australian talent and so we've added 4 of Jem's tracks to it.  If you are reading this then we'd really appreciate going along and listening to some of Jem's music, creating an account, and then voting for his tunes.  If he gets enough votes then he'll get played on TripleJ - which could be the kickstart that he needs.  Here's the page for listening to and voting for Jem's music:

    http://www.triplejunearthed.com/Artists/View.aspx?artistid=2077

The voting buttons are the hot pink things on the right side of the page.

posted on 8/21/2006 6:01:55 PM ( 0 Comments )


Getting ready for Tech.Ed

In getting ready for Tech.Ed I started having a bit of a play with the main technologies in the sessions that I'm going to attend - which are: Architecture, LINQ, Atlas, and performance/testing.

To kick things off I re-installed the latest Atlas, Linq, and Blinq bits and started building a little website to try things out.  Most of today was spent re-learning Linq and taking my first look at Blinq.  The first thing that I did was to fire up Blinq and point it at my test database like so:

> Blinq /t:c:\Projects\PD1 /database:projectdistributor /server:. /sprocs

Blinq is a command-line application which calls through to SqlMetal to produce a database context and then creates a website with pre-generated pages for every crud scenario using a series of DetailsViews and GridViews.  Some highlights from the output of a Blinq web app are that they:

    - generate a file called StaticMethods.cs which has static methods over all of the SqlMetal stuff
    - use CssAdaptors for nice menus

As for the rest of the website that gets produced, I'd say that its intent is to show "DLINQ in Action" from a web application perspective.

During the day I was reminded of how totally cool Linq is.  Here is an example of calling a business proc in my ProjectDistributor app:

Projectdistributor db = Projectdistributor.CreateDataContext() ;
int newID = db.AddUserToApplicationRole(1, 1) ;

Both the Projectdistributor class here and the AddUserToApplicationRole method were generated by SqlMetal. 

I think that when we get to using Linq in real world applications that we may use procs for some business level operations - such as above - but that most of the time we'll just code directly off of the SqlMetal produced proxies.  For example, using nothing but the generated proxies I could page through the records in my Users table like so:

    gvw.DataSource = db.Users.Seek(100).Take(25);

This would grab the 100th - 124th records from the Users table and bind them to a GridView.  If the Users table was quite "wide" I could also improve the efficiency by binding to a projection from that table instead:

 
    gvw.DataSource = from user in db.Users
                       orderby user.UserName
                       select new {
                           UserID = user.ID,
                           FirstName = user.FirstName,
                           City = user.City,
                           IsPublic = user.IsPublic
                       };

This would produce SQL under the hood which only requested the 4 columns from the User table.  ScottGu has a great post here which shows how simple it can be to display data on a web page using Linq.

posted on 8/20/2006 9:05:33 PM ( 1 Comments )


Profiling your code using Performance Sessions and PerfConsole

When I wrote SingleUserBlog (this blogging software) I had a single thing in mind and that was to create a blog that could be totally XCOPY deployable.  In other words, you could just grab the application, copy it into a virtual directory and you'd be away - no database to install.  To do this I decided to use good 'ol XML to store all of the data in the filesystem.  In the space of a few weeks I bashed out the code for my blog and put it online... YEEHAR COWBOY :-)

Everything went fine for a long time after I deployed my blog and I was enjoying the freedom of knowing the source code intimately and therefore being able to make little tweaks at the drop of a hat.  That was until one day when my blog started getting slow, real SLOW.  With every post that I put up there it just got slower and slower until it pretty much just stopped.  My code was failing big time.

You need to measure
When it came time to having to fix my blog I had no real idea where to start - although I had a fair idea that my elite file handling routines were in some way responsible for this mess.  Instead of fumbling around I decided to immediately do some performance tuning and to measure what was going on under the hood.  To do that I used the new Performance Sessions in Visual Studio Team System Developer.  Performance Sessions allowed me to record my running code and view which methods were taking the longest and how often each of them was getting called.  Using this information I was able to pinpoint the culprit within a very short space of time and fix it immediately without the risk of making random changes all over the place.

In this article I'll show the basics of getting a performance session up and running and also show how to use PerfConsole to view the raw data from a recorded Performance Session in a more visual manner.

Finding and Fixing a Bug

For this example, we have an application which makes calls to a business layer to get data which can sometimes be an expensive operation.  Here we see some test code which simulates a bunch of calls to the service agent to test how our Service Agent method performs:

static void Run() {
    Dictionary<string, int> items = new Dictionary<string, int>();
    Random rand = new Random();

    for (int i = 0; i < runs; i++) {
        int id = rand.Next(10);
        string retVal = ServiceAgent.MakeExternalCall(id);
    }
}


Under the covers, the Service Agent calls an internal helper to process the request like so:

public static string MakeExternalCall(int id) {
    return DoesWork(id) ;
}

And it's the DoesWork method which is expensive with each call taking around 500ms to complete.  400ms isn't too bad for a single request but in modern portal applications where data may be fetched many times in a single request each of these 500ms blocks start to add up when they are performed in a linear fashion.  When we run our test we can see that for 40 runs our test takes 20 seconds to complete - 40 runs times 500ms.  In this simple example our bottleneck is pretty clear but when we have hundreds of pages and classes and different assemblies all getting called together, finding the source of a performance issue is not so obvious.  To pinpoint our bottleneck we will now create a performance session to run our test code and record the actions so that we can see some metrics behind what's going on.  To get started select Tools|Performance Tools from the Visual Studio main menu like so:

Performance Tools

When you've selected the Performance Tools option from the menu you will be presented with a dialog window for starting a new session as shown in the following image:

Performance Tools Wizard Options

Profiling code produces VERY large files - maybe even gigabytes for what might be a short profiling session.  Luckily for us we don't have a lot of code to profile so our session will be quite small this time and so we should select "Instrumentation" from the previous dialog window as opposed to "Sampling".  Instrumentation will create much larger files and so when you are profiling a large amount of code you should start with Sampling turned on until you can zoom in on the problem area as this will create smaller vsp files and so you will be able to get through more performance sessions more quickly.

When you've created your Performance Session you will have a new session in the Performance Explorer window with a selected target for the session - this will typically be a project output that is observed during the session.  In the following image we can see that the HasCacheableMethods project is loaded as a target for PerformanceSession1:


Performance Session

At this point you can press launch on the Performance Explorer window to start the session and fire up the target. 

When the target has finished execution the session will end and you will be presented with a report containing some metrics from the session like so:

Performance Session Report

These metrics are pretty high level and can be quite ambiguous to begin with but by double-clicking on a row in that report you can drill-down into the next level of detail where things start to make some sense:

Performance Session Report

Here we start to get a really good view over the time that each method has spent running.  In particular the "Elapsed Exclusive" metric details how long was spent only in that particular method whereas the "Elapsed Inclusive" metric is a rollup of that method and the time spent on methods called by that method and so on.  In this report we can now see clearly that the Thread.Sleep call is where nearly all of the time was spent during our session, double click on that to see where it is called from so that we get some context about the work being done:

Performance Session Report

 

PerfConsole

There's another tool that has been released by Microsoft that was written by an internal developer which takes the output of a profiling session and allows you to write queries over it and to view a more graphical representation of the call tree, this tool is called PerfConsole.  Before you can use PerfConsole you must save the results of your performance session out to a CSV file; this is done by right clicking on performance session report and selecting Export from the context menu:

Performance Session Export CSV

Now you can choose what data to export and the location to create the exported CSV file

Performance Session Export CSV Options

Now start up the PerfConsole tool and load the CSV file that was just created by using the load command and passing in the filepath (you can get a complete list of command line syntax for PerfConsole by typing ?? at the command line.

Running PerfConsole

After loading my CSV file I can type in queries to view my performance metrics in a variety of ways, here I've used the following command to create a visual tree of the calltree


> calltree @HasCacheableMethods060811(1) | trim in > 5 | compacttree


Which displays the following result:

PerfConsole results window


I'd highly encourage reading the PerfConsole command line syntax help or reading this blog article to learn more about the query syntax for PerfConsole:

    http://blogs.msdn.com/joshwil/archive/2006/08/04/688599.aspx


After viewing these reports it's now very clear that ServiceAgent.MakeExternalCall is where the Thread.Sleep code is executed from and that, aside from the Thread.Sleep, the ServiceAgent.MakeExternalCall method actually runs fairly quickly - so Thread.Sleep is our enemy here.  Now obviously we cannot optimize the Thread.Sleep code at all but we can start to ask some questions about how to get our code to spend less time in there.  When we look at what is happening in our code (and remember that the Thread.Sleep in this example is a silly placeholder for a database call or some such other expensive operation) we can see that it's getting called on every call to ServiceAgent.MakeExternalCall whereas we could actually cache results for a distinct ID after the first call to it, so we change our MakeExternalCall code to add a layer of caching in like so:


static Dictionary<int, string> cache = new Dictionary<int, string>();
public static string MakeCachedExternalCall(int id) {
    if (cache.ContainsKey(id))
        return cache[id];

    string work = DoesWork(id);
    cache.Add(id, work) ;
    return work;
}

Now that we've fixed our code we can re-run our tests and see that our test code run time has been reduced from 20 seconds to just over 4 seconds.  Not a bad return for a little 30 minute performance fixing session! :-)

 

posted on 8/11/2006 10:55:41 PM ( 1 Comments )


Using Rhino Mocks to test objects

Yesterday Phil Haack posted up this nice post about how to code the MVP pattern in a web application.  The implementation would look fairly familiar to anyone who has used MVC before but apparently big 'A' guy Martin Fowler asserts that there are now many different flavors of a model-view-controller|presenter pattern and in this post, Phil is showing us what the Supervising Controller pattern looks like.

One of the best things that I learned most from Phil's post was how he used the Rhino.Mocks library to create mock objects for his unit tests of his code.  This looks like a very simple way to test code that is normally difficult to test - such as ASP.NET code or code whose state is heavily reliant upon certain runtime conditions to be met.  In such cases you'll often find yourself factoring code out into interfaces and then writing testable stubs for them.  Mock objects save you from writing lots of additional code just for the sake of getting testable stubs of objects.  Here's some code from Phil's sample project in his post where he tests the events and the state of a view in his test code:

[TestMethod]
public void HandlesLoadEventAndSetsViewPropertiesCorrectly()
{
    //Setup the service return values.
 BlogPost blogPost = new BlogPost(1);
    blogPost.Tags.Add(new Tag("ASP.NET"));
 blogPost.Tags.Add(new Tag("C#"));
   
    blogPost.Description = "My computer's cup holder is broken.";
   
    //Setup the load event
    viewMock.Load += null; //ugly syntax, I know, but the only way to get this to work
    IEventRaiser loadRaiser = LastCall.IgnoreArguments().GetEventRaiser();

    // Make sure that the proper service methods were called
    // by the presenter.
    Expect.Call(this.dataServiceMock.GetById(1)).Return(blogPost);
    mocks.ReplayAll();

    //Now run the test.
    new PostEditController(viewMock, this.dataServiceMock);
    loadRaiser.Raise(viewMock, EventArgs.Empty);
   
    //Check that the view was properly populated.
    Assert.AreEqual(2, viewMock.Tags.Count);
    Assert.AreEqual("My computer's cup holder is broken.", viewMock.BlogPostBody);

    mocks.VerifyAll();
}

If the code looks a little odd then read from one of Phil's other fine article where he specifically shows how to use Rhino.Mocks to test events - that will help explain what some of that code is doing.

posted on 8/11/2006 3:31:58 AM ( 1 Comments )


Instantiating a car park at runtime!

I walked past this sign today on my way to the shops and couldn't help but wonder whether this is some syntax from the next version of VB:

Dim a Public Car Park?

In this block of code - which the author has scoped as being private - a private instance of a car park is instantiated and ready for use. 

Wow!

posted on 8/11/2006 3:02:03 AM ( 1 Comments )


ProjectDistributor mentioned on Hanselminutes

Hanselminutes #28 is out and in this edition Scott Hanselman and Carl Franklin discuss Open Source software.  It's a very interesting discussion and explains some of the gray areas.  One of the highlights for me was that Scott mentioned ProjectDistributor as being a great place to host some forms of open source software.  Heck!  ProjectDistributor is even an open source project itself :-)

Open Source projects are interesting beasties and it's a topic that I've always been interested in.  As I mentioned, recently I've had a great deal of satisfaction in making BlogML an open source project and seeing Keyvan add features that I would never have had time to commit.

Listen to Scott's podcast and then leave me a comment about your experiences with open source.  What's your opinion of it?  Is it free as in beer or, as Phil Haack coined... free as in a flower :-)  For me it's both, depending on what I'm using it for.  

Some of my favourite open source software are: Draco, NUnit, NAnt, .Text, IBuySpy.

posted on 8/10/2006 10:09:20 AM ( 1 Comments )


The best Tech.Ed session picker app is...

Over the past week we've seen amazing scenes in the Australian blogsphere between Paul "WPF" Stovell and Bill "VB" McCarthy over who has the coolest Tech.Ed session picker.  We've heard allegations, muckraking, read fraudulent claims, and even witnessed name calling.

For what it's worth, I don't think that the winner comes from either of those applications but is instead the Session picker on the Tech.Ed site.  The reason is simple - it's a web application!

Because of this I don't have to install anything, and it can run on any platform such as Vista or XP without requiring special versions of pre-requisites to be present first.  The Tech.Ed session picker is readily available from all of my machines and I know that when I walk into Tech.Ed on 23rd August that I'll be able to go to any Internet Kiosk there and pull up my sessions from it.  The Tech.Ed session picker is fast due to its use of of Ajax and it allows me to query data in myriad ways such as: by Keyword, Timeslot, Speaker, Session Level, Session Type, and Track.

So sorry Bill and Paul, both of your apps are great, but I'm a web guy! :-)

posted on 8/9/2006 9:28:53 AM ( 1 Comments )


My Tech.Ed. What's yours?

Schedule For Darren Neimke


Tuesday, August 22

3:00 PM - 6:00 PM

 

 

Registration   Sydney Convention Cntr  

 

 

 

6:00 PM - 9:00 PM

 

 

Welcome Party     

 

 

 

Wednesday, August 23

8:30 AM - 9:45 AM

 

 

Opening Keynote     

 

 

 

10:00 AM - 11:15 AM

 

 

 

11:45 AM - 1:00 PM

 

DEV303 Concurrent Development with Branching in Team Foundation Server   Bayside 102 (mid blue)  

 

 

 

1:00 PM - 2:00 PM

 

 

Lunch     

 

 

 

2:00 PM - 3:15 PM

 

ARC204 Architecting Scale: How the M2006 team built a 10,000 Request per Second site   Bayside 104 (mid blue)  

 

 

 

3:45 PM - 5:00 PM

 

 

 

5:15 PM - 6:30 PM

 

 

 

6:30 PM - 9:00 PM

 

 

Ask the Experts Evening   Sydney Convention Cntr  

 

 

 

Thursday, August 24

8:30 AM - 9:45 AM

 

 

 

10:00 AM - 11:15 AM

 

CON308 (.NET 3.0) Windows Communication Foundation: Building Secure Services   Bayside 102 (mid blue)  

 

 

 

11:45 AM - 1:00 PM

 

CON309 (CRM) Modelling and Automating Business Processes with Microsoft CRM   Bayside 202 (light blue)  

 

 

 

1:00 PM - 2:00 PM

 

 

Lunch     

 

 

 

2:00 PM - 3:15 PM

 

 

 

3:45 PM - 5:00 PM

 

OFC213 Excel Enhancements (Excel Client and Excel Calculation Server Drill Down)   Bayside 105 (mid blue)  

 

 

 

5:15 PM - 6:30 PM

 

WEB211 Developing Data-Driven Web Applications with .NET Language Integrated Query   Parkside Ballroom A (light green)  

 

 

 

7:00 PM - 11:00 PM

 

 

TechEd Party   HOME Nightclub, CockleBay  

 

 

 

Friday, August 25

8:30 AM - 9:45 AM

 

 

 

10:00 AM - 11:15 AM

 

DEV315 Visual C#: Future Directions and Tips and Tricks   Parkside Ballroom A (light green)  

 

 

 

11:45 AM - 1:00 PM

 

WEB314 Developing Rich Web Applications with ASP.NET codename “Atlas”   Bayside Gallery B (mid blue)  

 

 

 

1:00 PM - 2:00 PM

 

 

Lunch     

 

 

 

2:00 PM - 3:15 PM

 

OFC319 Integrating Microsoft CRM, Windows SharePoint Services and Microsoft Office 2003   Bayside 103 (mid blue)  

 

 

 

3:30 PM - 4:15 PM

 

 

Closing Locknote     

 

 

 

posted on 8/8/2006 8:06:48 PM ( 1 Comments )


Mount Ainslie, Canberra

On the weekend we decided to go for a walk up to the top of Mount Ainslie (830 metres).  This was our first visit to Mount Ainslie and the views from the top are absolutely spectacular, providing the best view of Canberra over anywhere else in town.

At the base of Mount Ainslie is the War Memorial which is home to Australia's war memorabillia from both World War's and also Vietnam.  Here is a photo taken from just behind the War Memorial prior to our walk - the base of Mount Ainslie is behind the camera in this photo:

BehindWarMemorial

This next photo is taken from halfway up the mountain and shows a view looking straight down Anzac Parade.  At the closest end of Anzac Parade is the War Memorial and at the far end - just across Lake Burley Griffen - is Australia's Parliament House.

AnzacParade

When you arrive at the top of Mount Ainslie there is a lookout which provides an almost 360 degree view of Canberra and its surrounding districts.  In this next photo you can clearly (well as clearly as my 1 megapixel phone camera will allow) see the buildings of the city of Canberra on the right and Anzac Parade on the left.  In the foreground is Anne and Charles.

CanberraCityFromMtAinslie

In the previous photo you can see Lake Burley Griffen in between the city and Parliament House.  When it was time to go home we headed back down the path...

AnneHarryWalking

The walk home went much more quickly than the walk up the mountain and the roundtrip took us nearly 2 hours to complete.

posted on 8/8/2006 9:00:27 AM ( 0 Comments )


I'm joining the dark side

After reading this article I've decided to join the dark side for a week or two to see what I think.  One of the major things that pushed me over the line was battery life - but there's also a chance that readability will be improved too.

posted on 8/6/2006 7:53:13 PM ( 0 Comments )


CRM Tip - reduce the number of browser windows

When working with CRM it's easy to have 4, 5 or even 6 pop-up windows open because of the way that CRM creates a new pop-up window for so many things.  For example, when you click on a Customer account, it is displayed in a pop-up window.  Likewise, click on an Order or an Opportunity for that Customer and it too will open in a new pop-up window.

The easiest way around this is to configure your browser to make sure that new pop-ups open in a separate tab - rather than a new window:

CRM2

Now when you are drilling down into Customer accounts and viewing their Orders and Opportunities, everything will be nicely contained within a single window, thus making it much easier to navigate around:

CRM1

posted on 8/6/2006 3:27:14 PM ( 0 Comments )


Things to look for in a Security Audit

At Readify, we get involved in a lot of audit/review style engagements.  Performance reviews, Architecture reviews, Database reviews and Security reviews.  Internally we now have some useful documents floating around that describe the things that should be done an these kinds of engagements.  Today, while browsing Robert Hurlbut's blog I discovered that he has also published a checklist of things to do when engaged on a security audit:

    Security Code Audit

In addition to that he also linked to an article by Michael Howard which describes some common ways to perform security reviews on code:

    A Process for Performing Security Code Reviews

posted on 8/5/2006 12:01:11 PM ( 0 Comments )


Jem's music site now online

For the last few months I've been dinking around with a little website for my friend Jem who is a musician.  This week, having finally finished it I've managed to get it online; you can see the site here:

     http://JemsJerra.com

There are some free tracks that you can download and listen to or you can walk through the PayPal payment system and purchase whole albums.  Jem's music is folksy-rock and is excellent music to listen to while coding! 

Oh yeah, the site was written using .NET 2.0 and integrates with the PayPal system via IPN notifications.

posted on 8/3/2006 11:55:05 AM ( 0 Comments )