Rockstar has released the tracks from the radio stations in Grand Theft Auto 4 as MP3 downloads from Amazon. 256kbps, which is decent quality, though I’d honestly prefer lossless. May have to pick some of these up anyway.

Here are the tracks from my favorite radio station, Radio Vladivostok. My favorite tracks are “Zelenglazoe Taksi,” “Schweine,” “Wild Dances,” and “O tebe.” You can get all of the tracks from all of the stations at The Music of Grand Theft Auto.

gaming, xbox comments edit

Over the past few weeks I’ve noticed that, more and more often, my Xbox 360 will hang and give me an error message saying “the disc is unreadable” and inform me that I should clean the disc. Normally I’d say I have some pretty dirty discs, but the times it’s doing it, the discs are brand new - not even a single scratch. Eject the disc and pop it back in and it’s fixed. No cleaning required.

It’s averaging about every hour-and-a-half of game play now. I might play for four hours without interruption one day, but the next day it’ll happen two or three times in an hour. Since it’s really starting to get annoying (and seems to be happening at some pretty inopportune times, like just after you beat a really hard mission but before you can save), I called Xbox Support.

I’ll be sending my console in for repairs, this time for a failing DVD drive. This is the second bad DVD drive I’ve had. Let’s see…

…and now we’ve come full circle with a bad DVD drive.

The box to ship my console back to them should arrive tomorrow, per the UPS site. I’ll probably play through the weekend and then send it back. It’s not unplayable, just super annoying, and I’m so close to finishing the story missions in GTA4.

Today’s my first day back after a full week in Liberty City. I took all of last week off specifically to play Grand Theft Auto 4. It was totally worth it.

I ended up with about 50 hours of play time in and only got around 70% done. It’s huge, and while I admittedly took my time about it because I wanted to enjoy the experience and not feel rushed, I didn’t really get lazy about it, either. It’s a huge game.

I won’t repeat all the hype you can read in game reviews. Suffice to say, they really outdid themselves. The detail in the world they’ve created is amazing, the soundtrack once again kicks ass, and you really do start feeling for the characters - building relationships and learning about them. When things happen to them, you actually care. It truly deserves all of the “10” ratings it’s getting. The only thing I’d really change is that I hate the “race” and “chase” missions. The driving experience in general is pretty good, but some missions you have to race against characters or chase them down and shoot them. The AI you compete against in some of these races and chases is pretty brutal, and if you lose you get to run the race over again. I get controller-throwing-mad at some of these and have yet to find someone who’s like, “Yeah! I’d rather run one of those races than have a cool shootout.” They sort of fixed it in that some of the chases end up where after you chase for long enough the person being chased crashes so you can shoot it out, but still… More bank heists, less racing/chasing.

I haven’t played the online portion of it yet. I hear it’s pretty good, but I’m really a single-player kind of guy.

If you didn’t get this game, go get it now. It’s well worth your $60. If you can, take the week off and play it. It’s surreal, just like watching a marathon of a full season of 24.

aspnet, dotnet comments edit

The Web Client Software Factory is a great software factory from Microsoft Patterns & Practices that enables you to pretty easily make well-constructed enterprise ASP.NET applications that can be extended by downstream developers. The factory contains a lot of stuff - recipes, templates, and a lot of help to automate some common tasks - but the key item you’ll find in there is the Composite Web Application Block.

The CWAB allows you to make modular web applications that come together at runtime to make a nice, seamless experience. It makes it easy to partition work to various teams but maintain a consistent experience across the application. It also enforces some nice Model-View-Presenter separation of concerns when using web forms. Well worth the effort to use.

The thing is, you may not always want the entire Web Client Software Factory package when using Composite Web Application Block. There are two primary reasons you wouldn’t want the Web Client Software Factory in its entirety, both of which have to do with the associated guidance packages:

  • You don’t want the stock guidance packages. That is, the recipes and templates and other automation items don’t do what you want them to or are otherwise just something you don’t want. Maybe it’d cost more to modify the guidance package to do what you want than it would be to just manually do the work. Maybe you don’t want the dependencies that the guidance packages assume you want. Whatever the case may be, you don’t want the guidance packages.
  • You don’t want to deal with the developer environment cost. Having guidance packages that everyone has to use also means you have one more thing to install on every developer machine. When upgrades come around, it’s not just dropping an assembly in a folder to take the upgrade. There’s a cost associated with this, and you may not want to incur it.

Either way, you may not want the whole thing. What do you get by not taking it all?

  • Slightly ore complex setup.It’s a little more effort to manually get a CWAB project going if you don’t use the guidance packages. Not much worse, but this is a legitimate downside.
  • Manual control over everything. File placement, assembly breakdown, naming, etc. You could customize the guidance packages to do things your way, but it’s not a 20-minute undertaking to do so. If you’re not going to be adding pages or projects every single day, it’s probably cheaper to just do it manually.
  • Fewer implied dependencies. The guidance packages assume you want the Patterns and Practices logging, security, and exception handling application blocks, so there’s a lot of extra stuff that goes into the templates and such to support that. It can be a pain to rip all of this out if you don’t want it. The only extra dependencies you have when you’re using CWAB solo are CWAB proper and ObjectBuilder.
  • Easier upgrades.When a new version of CWAB comes out, it’s an assembly update, not something that has to be installed on every dev box.
  • Easier ability to implement standard forms authentication.Out of the box, CWAB uses the security application block for locking down page access. If you just want standard location-based authorization it’s easier to do it without the security application block in your way.

Here are some general steps to show you how to get CWAB working in your project without all of the guidance packages. It will help if you’re familiar with using CWAB within WCSF before you try this out. (I have a sample later in this article that you can look at for a more concrete representation. I followed this general process in creating that sample.)

  1. Create a web application project.
  2. Add references to the Microsoft.Practices.CompositeWeb.dll and Microsoft.Practices.ObjectBuilder.dll.
  3. Add modules (class libraries). In most CWAB projects, there’s a sort of default “Shell” module that corresponds to the main content of your site and registers most core services. Add at least this module. For each module you add:
    1. Add a reference to Microsoft.Practices.CompositeWeb.dll and Microsoft.Practices.ObjectBuilder.dll.
    2. Add a reference from the web application to the module.
    3. Add a module initializer class to the module. (A class deriving from ModuleInitializer.)
  4. Add a Global.asax that derives from Microsoft.Practices.CompositeWeb.WebApplication.
  5. For the Default.aspx page (which comes for free with your web application project)…
    1. Break the page up into Model-View-Presenter format with the presenter and view interface in your “Shell” module.
    2. Update the page namespace to match the namespace the presenter and view interface are in.
    3. Update the page to implement the view interface.
    4. Update the page to derive from Microsoft.Practices.CompositeWeb.Web.UI.Page.
    5. Add a Presenter property to the page with a [CreateNew] ObjectBuilder attribute on it.
    6. Add the page to the “Shell” module initializer’s site map registration.
  6. Rinse and repeat for additional pages - put the presenter and view interface in the proper “business module” and implement the interface on the page.

There are a lot of things you can do to make this way, way easier.

  • Create abstract generic “View” and “MasterPage” base classes. There’s a lot of common “template” sort of stuff (like the “Presenter” property on every single web page) that can be removed by creating some abstract generic classes and deriving from those instead.
  • Create abstract module initializer classes for business modules and foundational modules. Every business/foundational module initializer is almost identical. You can make it easier to create initializers if you have some base classes that have abstract methods you’re forced to implement.

To get standard location-based authorization working with the site map, you’ll also need to create a custom SiteMapProvider to use in place of the one that comes with Composite Web Application Block. The reason you’ll need that is because the out-of-the-box version trims by security application block settings. To bypass that and use standard location-based auth, you’ll need a custom provider.

It sounds like a lot, but keep in mind it’s one-time work and once you’ve got it set up, it’s not all that bad. To get you started, I’ve got a sample project you can download and see it in action. You’ll need to get the Web Client Software Factory because you’ll need the assemblies that come with it (I didn’t include them in my sample project). Drop them into a specific folder in the sample project and you should be good to go.

Of interest in my sample:

  • The “Framework” module has some example abstract base classes for views and initializers.
  • The “Navigation” module has a service that helps you locate existing nodes in the site map and contribute to them - something the CWAB doesn’t come with out of the box.
  • I called my “Shell” module “Core” to make sure there was no reliance on the assembly name “Shell.”
  • The “Core” module has a location-based authorization SiteMapProvider example.
  • The sample master pages and style sheets are the ones that come with the WCSF default site template.

The sample is exactly that - a sample. It’s not really tested (it works in the context of the sample, though) and I don’t offer you any guarantees that this will work for you and be totally bullet-proof. Your mileage may vary, no warranty expressed or implied, etc.

[Download Sample Project (48K)]

net comments edit

In this Two Minute WF, I’m going to tell you about WorkflowInstance.

This is a really simple one: A WorkflowInstance is - wait for it - a single instance of a workflow. Yes, it really is that simple. You pick your workflow type, fill in the activities it’ll use, and you have a workflow definition. Once you have the definition, you instantiate it and start it running. It’s sort of like defining your class/type and then newing one up. For objects it’s like this:

MyCustomType myVar = new MyCustomType();

For workflows, it’s like this:

using(WorkflowRuntime workflowRuntime = new WorkflowRuntime())
{
  AutoResetEvent wh = new AutoResetEvent(false);
  workflowRuntime.WorkflowCompleted +=
    delegate(object sender, WorkflowCompletedEventArgs e) {wh.Set();};
  workflowRuntime.WorkflowTerminated +=
    delegate(object sender, WorkflowTerminatedEventArgs e) {wh.Set();};
  WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(MyCustomWorkflowType));
  instance.Start();
  wh.WaitOne();
}

In the example, I not only create an instance of my custom workflow type, but I also start it running. It’s a little more complex than just creating a new object, but it’s not that much worse.

The WorkflowRuntime is responsible for instantiating workflows and starting them running. Since workflow instances run on a different thread than the main program, I’m using an AutoResetEvent to do thread synchronization - we don’t want to end the program or dispose of the WorkflowRuntime until the WorkflowInstance has had a chance to complete its run.

Something to watch for when you’re working in a larger environment with lots of instances - you only get one WorkflowRuntime for a given AppDomain. What that means is the WorkflowCompleted and WorkflowTerminated events are for all WorkflowInstances - you don’t get one for each instance. Be careful when subscribing to these events when you just want info on a single instance. If you forget to unsubscribe from the event and the event subscriber goes out of scope, you may have a memory leak on your hands. (The Garbage Collector won’t clean up the now-unreferenced event subscriber because there’s still one reference to it - the subscription to the global WorkflowRuntime event.)