Mad Props!

Omniscience is just a Google-search away.

Login

You're reading Mabsterama, the weblog of Matt Hamilton. Enjoy your stay.

Service Oriented Comics

After listening to another ARCast on the drive home on Friday, I finally decided to bite the bullet and try coding up the "server" side of Comicster (the online database that Comicster connects to to share information from your local collection) from scratch using "service oriented" techniques.

I resolved to do as much as possible using declarative methods - dragging and dropping rather than writing code. To that end, I was able to define my database (using Sql Server 2005 Express Edition) with a data diagram and define my typed DataSet with the DataSet designer in Visual C# Express.

Once those two steps were done, I set about defining the classes that would represent the objects sent back and forth from the "service layer" to the calling client. This I did in code (I'm not sure that Visual C# Express even allows you to define classes visually, but I was more comfortable coding them anyway). I ended up with these classes:

  • Publisher
  • Title
  • Issue
  • Creator
  • Character
  • Appearance (links Characters to Issues)
  • Job (links Creators to Issues)

These are pretty much a one-to-one mapping to the tables in the database, but that's by-the-by. Each of these classes represents a "data contract" between the client and the server.

The classes also have nested relationships. For example, "Title" has a property called "Issues" which is an array of Issue objects. Likewise, "Issue" has a "Cast" property which is an array of Appearances, and a "Crew" property which is an array of Jobs.

Next I started work on the "services". Eventually these would be ASP.NET web services or WCF services, but for now I am just putting them into a normal .NET assembly.

As a first step I tried an easy one - "PublisherService". This class has a single method, "GetPublishers", which returns an array of Publisher objects - one for each publisher in my database. This, as you'd imagine, was pretty easy. Fill the DataTable, iterate through the rows, create Publisher objects and add 'em to a list, then return list.ToArray().

Next I tried one a little more complex: TitleService. This class has a method called "FindTitles" which returns an array of titles whose name partially matches the given search text. Of course, the only really complicated part was defining the queries in the TableAdapter to get the right rows.

Eventually I realized that returning a huge array of titles, each with every issue in that title, was a lot of work to perform and a lot of data to return, so I tried defining an enum (called TitleDetailRequired) as a way for the client to tell the service how much information to return. If you don't specify TitleDetailRequired.Issues as part of your call to FindTitles, then the issues aren't returned. This sped up the calls tremendously.

Passing both a search term and a detail-required enum to the FindTitles method, though, seemed wrong, so I decided to implement a class called FindTitlesMessage which had these two pieces of information as properties. Now my FindTitles method takes one of these "message" objects as its only parameter. This means I can play with the definition of that class without having to change the method signatures of any methods that use it.

So after some work I ended up with services for each major object in my system. Designing the client to test the calls was the easiest part of all:

  1. Add a form to your project
  2. Click "Data|Show Data Sources" to bring up the Data Sources window
  3. Bring up the "new data source" wizard and choose "object" as the type
  4. Drill into Comicster.Data (the assembly holding my data contract objects) and choose "Title"
  5. Now you have a "Title" data source in your Data Sources window. Drag that onto the form and watch as it creates for you a DataGridView and BindingSource component!

The last steps, then is adding a TextBox and Button so you can type in the text you want to search for, and some easy code like this in the Button's Click event handler:

TitleService svc = new TitleService();
FindTitlesMessage msg = new FindTitlesMessage();
msg.SearchText = textBox1.Text;
msg.DetailRequired = TitleDetailRequired.None;
titleBindingSource.DataSource = svc.FindTitles(msg);

Pretty straight forward! Now when you click the button, the grid is populated with a list of titles matching the text you've entered.

The only thing bugging me at this point was that the "Publisher" column in the grid was just showing "Comicster.Data.Publisher", because the Title class' "Publisher" property is pointing to a Publisher class rather than a string or whatever. The fix for this was to handle the grid's "CellFormatting" event and tell it how to format that particular type. Here's that code:

if (e.Value is Comicster.Data.Publisher)
{
e.Value = (e.Value as Comicster.Data.Publisher).Name;
}

I'll post more about this little project as work progresses. Needless to say I'm very excited about it. It really feels like I'm finally doing things the "right way". In time I will download the .NET 3.0 bits and try my hand at converting it to WCF - assuming the integration with C# Express works ok.

Error When Dropping a TableAdapter onto the DataSet Designer

Can someone out there in the blogosphere explain this error? I get it intermittently when trying to drop a table from a Data Connection onto my typed-DataSet designer:

It also occurs if I try to create a TableAdapter "manually", by right-clicking and selecting "Add|TableAdapter..." - Visual Studio lets me step all the way through the wizard and then throws this error.

I've seen this error at work with the full Visual Studio, and now I'm seeing it at home in Visual C# Express, so it's not limited to any single version.

If I could even determine that the error occurred only under certain circumstances, I'd at least be some way towards working out its cause. As it is, I can't pick it at all. When it happens, it happens every time, and I can't add a TableAdapter at all. At other times I'll have no troubles.

For the search engines, here's the text of the error:

An unexpected error has occurred. Please record the following message when seeking support from Microsoft: Source:Microsoft.VSDesigner ErrorCode:-1 Additional Info: 

What do you think, guys? Seen it? Fixed it? Can you help?

AWDNUG September

Another second-Wednesday has passed, and with it another meeting of the Albury/Wodonga .NET User Group!

Last night featured two presentations: One from Andrew on Reporting Services, and one from Michael on the Application Blocks from Microsoft's Patterns and Practices group.

It made for a good night, because even though I know SQLRS pretty well, watching Andrew present was very entertaining. He was a nervous wreck! It was hilarious. Anyway ... about half way through his presentation he loosened up and I think everyone took something away from it, which was great.

Michael's talk on Application Blocks was of particular interest to me because I've yet to play with the blocks and wanted to know more about them. I was a little disappointed that he focused on the Data Access Block, because I've seen code samples about that one already. Nevertheless, it was good to learn that the blocks play nicely with Visual C# Express - that means I can play with them at home.

We also had a new attendee last night - another Michael, this one from Border Express. We'd had a brief meeting with some of the guys from Border Express here at work last week, and they were keen to learn the details of the user group - great to know that they followed through and came along!

I've posted a list of presentation topic proposals to the AWDNUG forums here. If you're coming along to the meetings, maybe post a reply there and suggest a topic or two.

No Cold Shoulder from Dell

What an interesting day.

Sal has been complaining for the past few days of a sore shoulder. It has gotten progressively worse each day, so yesterday she saw a doctor about it. He theorised that she has a condition known as "frozen shoulder". When I heard this, I thought he'd made it up, kind of like a brain cloud or something, but it turns out it's real.

Sal decided shortly thereafter to get a second opinion, and spent last night sleepless and in constant (and, apparently, intense) pain. I took the day off today to take her to her second doctor's appointment, which her work had made for her because they're worried it might be a work-related injury.

Someone from her work showed up at the doctor's office too, so after waiting for nearly an hour (!) Sal let me go home and said she'd get a ride home with her workmate.

Bizarrely, she ended up back at work, and they made her stay there for the entire workday, so that really pissed us both off. She's incapable of even moving her arm, so she was pretty much useless.

Anyway, since I had the rest of the day to myself I decided to go over to my folks' place and set up their new Dell Dimension 3100. What a nice little machine! Only AU$1100 and it came with a nice-looking 19" flat-panel monitor!

After connecting it all up, I spent probably 20 minutes uninstalling all the crap that Dell ships with their standard install. For starters, I'm not interested in that 90 day trial of some anti-virus program (my folks aren't online, and they're unlikely to install anything unless I give it to 'em). They have no need for Google Desktop. They don't need the "Digital Line Detect" and other useless modem-related crap. So much crap!!!

Anyway, dad is kind of a technophobe so I spent the afternoon with him explaining iTunes to him. I'm not a fan of iTunes by any stretch, but he has an old iPod shuffle (guess who bought that for him?) so it was reasonable to centralize his music-management there. iTunes 7 is pretty neat - it has some album-art visualizations which look so good they could have been designed by Microsoft. Bravo for keeping a close eye on the competition and introducing some of their nicer ideas into your otherwise crappy software, Apple!

I left dad late in the day, manually typing in track and artist names. What a bitch it is to import CDs when you don't have an Internet connection! I'll have to investigate whether it's possible to keep an offline version of the CDDB.

Two Degrees from Royalty

Y'know how they say that everyone in the world is connected to everyone else by six degrees of separation or fewer? I found out the other day that I'm connected to genuine royalty by only two degrees.

I don't know how many people outside of the US saw the news story of an Australian tourist shot in Jordan, but it was big news here (understandably). Anyway, it turns out that the girl who was shot is my wife's cousin, and I've apparently met her at one of the in-laws' family get-togethers (I'm hopeless with names and faces, so there are a whole lot of Sal's family that I've met and don't remember).

Anyway, Ashleigh (the girl who was shot) was visited in hospital by the King of Jordan! As a gesture of good will, he's paying for her parents and sister to pick her up and take a holiday in England!

So there you go - I'm only two degrees of separation from the King of Jordan! How cool is that?

New Comicster Version

Just in case there are some Comicster users out there who are subscribed to my blog but don't actively check the forums (I'll be posting there soon): There's a new version of Comicster available.

The catch, though, is that you won't see it if you click on "Check for Updates" in the "About" dialog.

The reasons for this are manifold, but they basically boil down to the aforementioned stuff-up I made with the code-signing certificate.

Anyway - here's what you need to do to upgrade to Comicster 1.0.3.0:

  1. Go to "Control Panel|Add or Remove Programs" and uninstall Comicster.
  2. Visit this link and install Comicster just like you're installing it for the first time.

That's it! You're now running the new version. The only bummer is that your "settings" (thumbnail size, whether to automatically open your collection etc) won't come across with this new version. I apologize for that.

What's new in this version? Well, there are one or two behind-the-scenes changes that should streamline future updates, but the big news is our new arrangement with ComicList.com! Charles over at ComicList.com has provided individual feeds for new comics from Marvel and DC each week, as well as new comics from smaller publishers grouped into a third feed. If you look in the "Online" section of the tree, you'll see the feeds.

As always, post in the forums if you are having any problems - particularly if you have problems updating to this version. I'm here to help!

ClickOnce Expired Certificate

Damn it!

I've got an upgrade I wanted to make to Comicster this weekend, and only now I've realised that the self-generated certificate I was using to sign the application has expired!

What does this mean for Comicster users? Well, I'm fairly certain it means that upgrades from the current version won't work. ClickOnce will assume that this new version, since it's signed with a different certificate, is a different program.

If I don't hear back from the MSDN forums with a decent solution, I'll have no option but to generate a new key and try to let everyone know to uninstall their current version and install the new one, rather than relying on the upgrade process.

What a bummer!!!

If you've had any experience with renewing expired self-generated certificates (or generating a new one with the same key), then please leave me a comment!

More Credence to the Enough Rope Dead-Pool Theory

Legendary Australian motor-sport champion Peter Brock killed today in a car accident!

Appeared on Enough Rope 18/7/2005!

This is getting spookier and spookier! Who's next? Alice Cooper? Clive James? Kevin Spacey???

XNA Invaders

Check out Pete's first little effort with the new XNA Framework: XNA Invaders.

Give 'em Enough Rope...

Oh my god! I just came to a shocking realisation!!!

If you appear as a guest on Andrew Denton's Enough Rope, it's the kiss of death!!! Stay away, people!!!