2008-05-04

Global Warming - Lastest Excuse for the War on the Family

Pretty interesting article on how the pseudoscience of global warming is being used in a renewed attack against families and religion. I'll have to keep my comments to a minimum, because not only does the author already make plenty of points clear, I don't think I could comment further without wanting to tear into the lefty environmentalist whackos who actually believe that tripe.

I love the author's last paragraph, though. Reminds me of the Mystery Science Theater 3000 short "Mr. B Natural", when Tom Servo quips, "Meanwhile, the Midvale police visit his locker to find out why they call him, 'Buzz'."

I always found it interesting (and sad) how words get twisted. Instead of perversion, it's "progressive". Obscene is "adult". And conservative faith and belief is "backwards", "Puritanical", and even "dangerous".

I've said it before. Some days, I wish the Second Coming would hurry and get here to put an end to this madness.

2008-04-16

Web Part Madness

In my earlier post, I commented on how, from what I heard from another developer's rantings, web parts involve developing your own web page. As I'm about to dive into my own web part, I realize I didn't fully grasp what he meant.

It appears that some large things that one would normally take for granted in an ASP.Net web page — in particular, the creation of child controls and the rendering of the page and said controls as HTML — must now be coded manually. Yes, imagine my surprise when I opened up some web part code and saw the CreateChildControls and Render methods and all their code.

What. The. Crap.

It's like SharePoint development takes all the ease and safety of .Net coding and rips it away like a scab that hasn't fully healed, leaving a bloody festering wound in its place. But at least they give you a needle, and if you're lucky, you can go out on the web and find enough thread to sew the wound closed.

Yes, the geezer in me is already telling me to sit down and shut up. I've drawn out web pages by hand before, where the closest thing we had to a "server control" was an include file that wrote an expected structure of HTML code to the response stream. But for heaven's sake, that was over five years ago. We're supposed to be well beyond that. We're even coding with the very tools that take us beyond that, and we're being told that we have to do our jobs with the important tools tied behind our backs.

Maybe this is what Microsoft meant by "do more with less"?

2008-04-10

SharePoint, addendum

Just a quick little addendum on SharePoint. As part of my document library woes from before, I discovered my problem. It seems that there are differences between sites and webs, and in some cases, SharePoint blurs the lines between them, and in others, the lines are very clear. For instance, a Document Library site (or web — see, I'm already confused) that exists under the main site at http://localhost/Docs is not the same site as http://localhost/. Although some features are accessible through the web services located at http://localhost/_vti_bin/*.asmx (such as finding a document by URL), some features are not unless you use the services belonging to the specific site (e.g. http://localhost/Docs/_vti_bin/*.asmx, such as creating a folder).

It doesn't help that, when you add a web reference in Visual Studio to a subsite's services by directly entering http://localhost/Docs/_vti_bin/Dws.asmx, it adds the value to the app.config/web.config file at the root http://localhost/_vti_bin/Dws.asmx level, and if you're not expecting this, you're using the wrong services.

Not that all my problems are solved. Apparently, the web services aren't letting me get information on an empty folder, which sucks, so I dropped that possibility and moved on. (Compared to the object model, the web services are pathetic.)

Recently, I created a custom view for a document list. To create this view, I had to download and install the newest version of FrontPage of all things, called the SharePoint Designer (because Visual Studio refuses connect to a SharePoint web site with an explicit message saying so — more evidence at the lack of support in SharePoint for developer tools). I did this because I needed to remove all the "chrome" from the list view (it's being embedded in an IFrame from a CRM site), and the only way to do that is to customize the .aspx code itself, and the only tool to do that is FrontPage (by whatever name they call it), apparently.

With it all created and working great on my local development machine, all that's left is to migrate it to the servers. I have yet to figure this part out. Although we do have manifests and such set up for web part and event listener deployments, we do not have anything for a custom view template page, and so far Googling has failed to reveal anything that might help.

Again, I iterate how frustrating and ridiculous this all is as a developer. I should not have to waste hours of time trying to find out how to move my work from one server to another. It's possible to point my local copy of SharePoint Designer to the server (with some hosts file editing, since the URLs are only created local to the machines), but this kind of manual copying, essentially duplication of work, is also pretty dang frustrating.

I did come across tools that promise to migrate whole lists, but that's not what I want to do at all. That would overwrite content, which would be bad. I just want to migrate changes, update a view (actually the template for a view), and preferably without installing or pointing a development tool to each server in turn for each change. (And I wasn't able to determine if the solutions I came across would migrate views anyway...)

I'll try to keep these posts updated with any solutions that I find to this and other problems as they come up... >:(

2008-04-04

I'm a developer, and I hate SharePoint

When you develop a regular ol' web site in Visual Studio, you just say "create a new web site". You create your pages and web controls, classes, whatever you find necessary. To debug it, you set your breakpoints anywhere you want and hit F5. Studio these days even launches its own built-in web server, so you don't have to set up IIS. You can even change your code on the fly in some cases. When it comes time to deploy, you grab the code, copy it to the server, point IIS to it, and you're done. (Ok, it's rarely that simple, but it can be. Throw in a few web.config changes or other optional steps like pre-compiling if you wish...)

How easy is it to develop a SharePoint site? First, you have to install SharePoint. While I've never actually done this step, I can't really say that it's hard or easy; however, since IIS comes pre-installed, it's a pretty simple bet that installing anything is more difficult than not having to install anything. Considering how big SharePoint seems once you get it installed, I imagine installing and configuring it can be extremely complicated. Or perhaps it's fairly easy if you just accept all the defaults.

I'm working on a SharePoint project that, so far, we've tried building an event listener, a web part, and code that uses the web services. The event listener works fine, except that to debug, you have to:

  1. manually create the list in the SharePoint site on every developer's instance of SharePoint
  2. register the listener class library in the GAC
  3. use a command-line utility to register the listener with the event
  4. run IISRESET to restart SharePoint
  5. attach the Visual Studio debugger to the SharePoint process

Fortunately, a batch file takes care of the middle steps, and the first step only has to be done once. Still, it's a lot of extra overhead, and it has to be done for every listener that gets created.

The web part has been the responsibility of another developer. Based on his comments, I gather that designing a web part involves practically designing a whole web page. What I remember from them in a previous job, setting them up and deploying them was a royal pain. Modifying them was considered something you just Didn't Do. Their solution was that they had a web part that had, as a parameter, the path to a web control. If you wanted to create a new element on a web page, you created a regular .ascx web control, dropped the "container" web part on the page, and set the path property to the location of the .ascx control. Probably the only easy thing about that job.

The web services are supposed to be easy to use. They have been decidedly not so. My tasks have revolved around trying to interface with the default document library. I can access documents by using the URL http://localhost:ip/Docs/Documents/filename.doc just fine. And yet, if I try to get any information about the document library itself, it tells me the very document library from which it is serving documents doesn't exist. This is most evident when I use the Dws.GetDwsData method on an existing document. It returns a load of information (including a "LastUpdate" parameter which, instead of being a piece of useful information like when the document was last updated, is a key for future calls to see if it was last updated since a given key). One of these pieces of information is a reference to the Document library, which it returns as an error code, "ListNotFound". Because this document library that these documents are stored in doesn't exist, I can't use other methods I need, such as Versions.GetVersions, Dws.CreateFolder, or Lists.GetListItems.

And we haven't even gotten to the point where we try and deploy SharePoint content yet. As I already alluded to before, there's no real way to transfer content pieces from one machine to another in any easy or automated way. A simple list had to be manually created on every developer's machine, and it'll have to be done on Development and Test. In that previous job, they had an established procedure: back up the entire SharePoint database from development, and restore it in the test environment, then QA and then Production in turn. (Which, yes, meant you can't store any development or test information in SharePoint.) While I was there, for the first time, a SharePoint List was used to store data instead of content, and they had to bring in a Microsoft consultant to write a special utility to export the data and re-import it, so it wouldn't get lost in the complete-backup-and-restore deployment procedure they had for years. Because, of course, no procedure currently exists.

Supposedly, SharePoint is what companies want, because it means they can manage content without having to go through development to do it. Case in point, we have a static web site that we're moving into SharePoint for our client, because every change they want to make, they have to call us to make it. The problem is, it's taken our one consultant, the one who's supposed to be experienced in SharePoint, all week to get the existing site into SharePoint, and he still hasn't even gotten the framework in place, let alone the content — something even he agrees would take maybe two days, start to finish, to completely rebuild in a standard ASP.Net site.

Where it seems to make sense to set up a single-environment easy-to-manage web site and collaboration area, it is a nightmare for multi-environment (i.e. Dev, Test, Production) migration and custom development. And yet, it's what the people at this consulting firm keep selling like it's the Holy Grail. I have my own theories as to why this is, but the fact remains, we're stuck with a tool that just refuses to do the job, and tasks that should take half a week are becoming impossible to do in two.

2008-03-24

Whatever happened to Microsoft Phone?

Many years ago, I had access to a piece of software called Microsoft Phone. It was distributed with some versions of the Creative Labs Phone Blaster, a rather massive expansion card that combined a modem with a sound card. What made this combination really cool was that the card and the software turned your computer into a telephony device. It wasn't the first or only device on the block that could turn your computer into an answering machine — I had something in my computer in college that did the job as well (although I'm sure my roommate often times wished we just had a simple tape-based machine, especially when I would reboot my computer and it would knock him off the phone). It also wasn't the only software that could use your computer's microphone and speakers as a speakerphone — some Phone Blasters were bundled with completely different software that did that as well.

What made Microsoft's product so interesting is that it was integrated with its fledgeling text-to-speech and voice-recognition programs, and it used the common MAPI message storage system. Back in the day, when Windows 95 was still new, mail storage could be set up as more of a common database. At least, the mail storage location was a simple control panel icon, and the built-in Windows Mail client could connect to the MSN service without an issue, without having to use any custom email software. (It seemed simpler then; maybe it could still be done that way today, since I'm back to using Windows Mail in Vista instead of Outlook or Thunderbird or Outlook Express or even Live Mail.)

In any case, installing the Microsoft Phone software included installing Microsoft Voice, which allowed for some voice recognition. Trying to control the computer with it was more of a gimmick than being really useful at all. (Looking back on it now, it's hard to expect more out of 1995 technology, although I'll get into that in a minute.) The command set was fairly limited, although what commands it did know, it did recognize fairly well, so although there wasn't a lot you could do with it, you could at least do those things consistently.

Now, here's where things got interesting, as far as Microsoft Phone was concerned. One of Phone's features was that you could dial in to your phone and enter a code to access the program and start issuing commands. Fairly standard fare for answering machines. And, just like any ordinary answering machine, you could issue those commands by using a touchtone keypad. Where it started to set things apart was, Phone would prompt you for commands, and not by using pre-recorded prompts. It would read you instructions using text-to-speech reading from a help file. While this might not sound like such a big deal, especially in an age where sound compression and disk space are cheap, back then, this was huge. Phone was able to provide a rich, vocal interface without having to save megabytes of prerecorded files.

The next interesting thing it could do, because of text-to-speech, was it could read extended information about your message. It could not only announce the time and date of a message, and read the phone number, but it could also read the name of the caller. If that caller was in your address book (remember, this was all coming from your MAPI store), it could read that personalized name. Granted, the pronunciation wasn't always perfect, but it was still a very cool feature to hear your computer read the name of your caller to you over the phone along with the message.

Now, this was back in the days of dialup, and you could set your computer to call into your ISP and check and download email during the day. This brings me to the next very cool feature. Remember, all messages were stored in the single MAPI store. So when you play new messages, included in that was your computer reading your new email messages to you. The first time I showed this feature off to a friend, her jaw hit the floor as soon as she realized what was happening.

And finally, because this was running with the Microsoft Voice speech recognition engine, not only could you give the commands using your touchtone phone buttons, you could speak your commands and have the machine respond.

So where is this technology today? As I was writing this, I was thinking about how cool this was back in 1995, but I was questioning how it would work a decade later. In 1995, voice was still a preferred method of communication. Being able to call my computer and have it read my email to me would be a great feature. Today? Not so much. In 1995, 99% of email in my inbox was interesting and valid, came from human beings who sat down and thought about what they wanted to say, and wrote it as if they were writing a letter, with well-thought-out sentences and grammar. Today, most email is hastily dashed off, with lots of abbreviations, written with very little context. And that's only the ones I want to read, which is a minority. The majority of email I get now is mass mailings from corporations, or spam about prescription drugs I don't need or software that's not licensed or legal, or newsletters or chain letters or group mailings or any number of other impersonal communications — basically, nothing I'd need to phone home about.

However, the concept of having voice messages delivered to email is desirable. So I guess, a decade later, I'd be looking at the reverse of what was cool in 1995 — being able to connect a text-type device (i.e. an email browser) to my home message storage and get voice messages. It might be cool to have dictation transcribe that to text for very low bandwidth applications, but with the way email clients work these days, it'd almost be unnecessary. (Almost. I still use Pine over an SSH connection to read email from work, so text-only email and browsing isn't dead yet. At least not for me.)

I'm still intrigued by the concept of a software-controlled answering machine, one that could take messages, convert them to email (making the "from address" look like a phone number would be a nice touch), especially one that could be programmed to automatically answer and annoy calls from certain phone numbers (such as those identified charities that continue to call soliciting donations despite the request for no solicitations). In the end, we've got to go with something that "just works"; so although I tried to recapture those old glory days by buying the Microsoft Cordless Phone product around the turn of the century (that failed to live up to expectations, especially when it wasn't supported past Windows 98), we ended up buying a plain old telephone answering machine that isn't a piece of software installed on a computer — and my current roommates (i.e. my family) are much happier for it.

As far as voice control, I finally decided to play around with it in Vista the other day. I will say that I am impressed with how far it has come. For general navigation, there's this "say what you see" concept, where you can just say the name of what you see — the name of a link on a web page, for instance — and the computer will attempt to discern what you mean. You say the name of a command button or link, and it clicks it. However, it's still rather clumsy. I feel like I'm talking to my 1-year-old, having to repeat things over and over again, sometimes louder, sometimes trying to say things a different way. Dictation was especially frustrating, as you're supposed to be able to say "correct" and the words it just got wrong in order to fix it — and yet over and over again, as I was trying to dictate and correct, it started typing "correct this" and "correct that", like an old sitcom routine where the dullard keeps reciting stage directions.

And in that sense, it doesn't feel much different than 1995. Sure, you can actually dictate text now. But giving commands? That's been around for over 10 years, and we're still pointing and clicking with a mouse. At the end of the day, I couldn't see how it could possibly be any more convenient or useful than just using the freaking mouse or keyboard to directly input the location or text desired. Even if it does entertain my wife to listen to me try to use it....

2008-03-17

It's so hard to send email programmatically

One look at the subject line, and I'm sure the first word that comes to the minds of the four people who might see this blog is, "Huh?" Sending email isn't hard. Programs do it all the time. Why can't a genius like you figure it out, Yakko?

Well, here's the problem. See, I'm writing a custom Windows application for a client. This application is essentially a database for storing the deposits and withdrawals of a handful of investment companies and their investors. In essence, it's copying what he tracked in spreadsheets. Since I'm moving this from spreadsheet to database, I can implement all new features for him like tracking performance over time, graph them, compare them to market indices, and the big new feature, generate PDF reports and email them instead of printing paper copies one by one.

He runs all of this on a PC in his home office. As such, I made sure I wrote the program to be as small and simple as possible. Sure I considered using SQL Server Express with Reporting Services to generate the reports, but how easy would that be for him to install, or back up the program, or send to his part-time clerk for easy data entry? Small and lightweight were part of my requirements here. And thanks to the .Net framework, I managed to write a pretty decent app, with a SQL Server CE database engine, that would fit on a floppy disk. Not that I could find a floppy disk to put it on anymore, but you get the idea.

The one part of the program that really disappointed me, though, was the email tool. Here I managed to generate these nice-looking PDF reports in real-time (using the PDFSharp library -- they say "the same drawing routines can be used to create PDF documents, draw on the screen, or send output to any printer", and in my experience it really was almost that easy to convert my paper printing code to make a PDF). But how to email them?

While it is true that the .Net framework includes some very simple routines for sending SMTP mail, which I have used before in various client-server, intranet, and web applications, the trick is they work really well if you're using them on a server. Ever send email from a personal computer on a dial-up connection? (Yes, he's still on dial-up; don't ask.) Even if you're on broadband on a static IP, chances are your address is identifiable as an end-user, and there's a very good chance your email will be rejected with prejudice.

Now, he can send out email using his email program of choice. Why? Naturally, because it's configured to use his ISP's email server. Because I want to keep this program as simple as possible, adding email configuration was not in the design; and, I could find no way to query Windows to discover (a) what email program he's using, and (b) what settings that program uses to send email. (I couldn't even be certain I could use the same settings -- he's on MSN; what if it requires SPA?)

When you think about it, it all makes sense. How easy it would be for spammers to write programs to do just that and send email out via a user's ISP's email server, instead of trying to send out from the easily-blockable local address.  If I recall correctly, viruses used to do just that, before email programs had to get better at locking external program access out.

So what do I do? I create a "mailto" link with the appropriate subject and body parameter for every PDF that must get generated (but no attach parameter; although that used to work once upon a time, apparently that got to be too big of a security risk as well, and while some email programs simply ignore it, Outlook will refuse to start and throw an error instead), then delay about 5 seconds (because in some of my test scenarios, if a second "mailto" link was getting processed at just the wrong point of processing of the first one, the second would trigger an error instead of opening a second window). Once all the mail windows were open, an Explorer window would be opened to the folder containing all the PDFs generated, so they could be manually dragged and dropped on the appropriate mail windows.

I ask you: how much does that suck?

Probably the only redeeming point in this is that, at this early stage in the game, manual intervention is desired, so he can see the reports and the messages before they go anywhere. It's going to get old very fast, though...

2008-03-12

It's not a toy, it's for business

My wife and I got Tablet PCs for our business. We've been wanting them for a while. We decided to pick up a couple HP Pavilion tx1420us models. These are considered "home entertainment" models, not business models, but they had decent specs for the price.

The screen isn't as big or as fine as I would like. This replaces a Thinkpad T40p, which had a nice large screen and a 1400x1080 resolution. This tablet has a relatively small screen with a lot less real estate at 1200x800. Also, I've found that the pen takes a lot more pressure to use than I would like. It's quite tiring to write with for long periods of time, and it has a tendency to "stutter" when drawing over any distance.

But I definitely like the tablet. I've wanted one for a long time, and I'm glad I have one. They are fun to use, not to mention pretty easy when "point and click" is literally pointing with a pen and physically tapping it. There's something rather satisfying about being able to move things around screen by grabbing it with a pen and pulling it around. It makes it feel a little more "hands-on" than like I'm using a remote control (i.e. the mouse or touchpad).

It comes with Vista, which at the moment I have this sort of love/hate relationship with. I know the UI enhancements are all eye candy, but honestly it makes the computer "feel" next-gen, like we've finally progressed. However, it is very different than older versions of Windows. When I first sat down in front of XP, it didn't take long to find my way around, because it was so similar to Windows 2000, which was similar enough to 98... In Vista, I'm still trying to figure out how to do tasks that were second-nature to me before. So far, though, it hasn't been "too bad". I haven't run into any driver or compatibility problems, and I found the dialog box that pops up every time you launch a program easy to turn off (convenience trumps security, for now). I'm sure a big part of this is I'm running on all-new hardware that came with Vista — I still have no intention of ever trying to upgrade my older machines to this OS, even if they're still running long after XP is dead and buried.

2008-02-29

How fast is a parsec?

Possibly the most plausible explanation I've heard for the blatant error in unit in the cantina scene in A New Hope is, according to a copy of the script, Skywalker and Kenobi were supposed to react as if they knew they were being fed a load of hogwash — an emotion that was, unfortunately, never really conveyed.

The Wookieepedia article on the Kessel Run mentions this, plus another explanation offered by George Lucas in DVD commentary (that he meant his navigation computer could find shorter — and therefore faster — routes), but only as "behind the scenes". The more prominent explanation is given thus:

Solo was not referring directly to his ship's speed when he made this claim. Instead, he was referring to the shorter route he was able to travel by skirting the nearby Maw black hole cluster, thus making the run in under the standard distance. However, parsec relates to time in that a shorter distance equals a shorter time at the same speed. By moving closer to the black holes, Solo managed to cut the distance down to about 11.5 parsecs.

Essentially, his ship was so fast, he was able to take a more dangerous shortcut.

Why do I think this is a load of bunk, in the context of the cantina scene? The whole conversation at that point was about speed. Why mention distance when your client is asking about speed? Expecting a farmboy and a nomad to know the details about a particular space race as a condition for winning a fare seems like pretty bad business sense. Solo may have made some bad decisions, but I don't see him as being entirely stupid.

If you do take the Wookieepedia explanation as fact, though, it does explain that awkward silence with the following deleted scene:

Han: "It's the ship that made the Kessel Run in less than 12 parsecs."
Luke: "So, that would mean he'd have to take the Maw shortcut? How fast do you have to go to get around there?"
Ben: "Um, let's see, take a left at Geonosis Prime, you'd have to circle Kamino..."
Luke: "No, Kamino's too far; that's at least half a parsec out of the way; he'd have to go past Denobula."
Ben: "Denobula? Oh, yeah, at the Circle-K. Used to love their donuts. I haven't had their donuts since, oh, before you were born..."
Luke: "So, to get down to 12 parsecs, you'd have to cut pretty close to Naboo in order to make that turn."
Ben: "That would put you within... ten million kilometers of Maw?"
Luke: *scribbling* "No, no, carry the 4."
Ben: "Oh, right, right, half a million kilometers. Now, with the mass of Maw, the velocity needed for a Corellian freighter to escape would be... um..."
Han, annoyed, impatient: *ahem* "She's fast enough for you, old man."

Assuming Han was full of it, though, and Ben and Luke eventually caught on, I imagine the scene in docking bay 94 might've played out a little differently...

Luke: "What a piece of junk!"
Han: "She'll make .5 past light speed."
Luke: "What, .5 parsecs?"
Han: "She may not look like much, but she's got it where it counts."
Luke: "Really? Does it count all the way to blue?"
Han: "I've made a lot of special modifications myself."
Ben: "Yeah, like the ability to tell time with a ruler."
Han: "But, we're a little rushed..."
Luke: "Yeah, we've got to go in just a few inches."
Han: *thinking* I should've let Greedo shoot first...

2008-02-21

There's always a bigger fish

I've been on the job market for a little while now. I got laid off from my previous job, thanks to recent changes in the economy. Fortunately, the job market is fairly active at the moment. Inside of a week of finding out I was being laid off, I had two phone screens and an in-person interview.

One company with which I interviewed recently, I felt was going to be a sure thing. The phone interviews went very well, and when I met them in-person, everything seemed to go well. I had a great conversation with the manager, and the interview with the development team was great. I felt like it was a great team, like it was a great group of guys to work with, and that we would get along wonderfully. They seemed reasonably impressed with what I knew and what I could bring to the company as well.

I did have another company that was wanting to bring me on. They had worked with me before, they knew my capabilities, and I think they were nervous that I might take another offer (I had done it before — no hard feelings to them, but at the time, they didn't have anything for me, and I had another offer that was really good). I wasn't going to tell them no until I knew I was going to take another offer, so of course I was eager to see if I was going to get one from the interview. (I was pretty sure I would, but I did want to be sure the offer was in the ballpark of my desired salary/benefits.)

This is where it helps to be working through a recruiter. I can call him and pester him all I want, without fear of turning off the potential employer for calling them directly too much. ;)

I finally got their decision. They said I was a great fit and fully qualified, but they were going to go with someone who had just a little more expertise or experience or something. Now, fortunately, I did have interest from the other company, so I am able to switch over, accept, and start working on this other project. Even if I'm not sure it's ideal, the fact is, it's work, and as such, it's income. (There are also other benefits, such as a decent health care plan, not far from my kids' school, more of a "known quantity" as I've worked with them before...)

The annoying thing is, this isn't the first time I've heard that explanation. "Yeah, you'd be perfect, but someone else is better." It just leaves me wondering. Is it the truth? What is it that I could've improved on so that I could be the one that's just "a little better"? Or was there a flaw with me that they're not telling me? Or was this other guy's advantage more of an inside — a friend or relative that as good as had the job from the beginning? (Although usually it's the bigger companies that bother with interviewing just to say they did; this was a smaller company.)

Then again, I had been praying that I would be guided to the right job for me and my family. Although I think I would've enjoyed the work, it was a bit of a commute, which would've taken me away from my family. Perhaps that, or other reasons that I couldn't see, would've made this job not as good as something else.

In any case, it's hard to be too upset. Instead of having to make a difficult decision between two opportunities, the options narrowed themselves down for me. It's almost more of a relief, actually. And, I now know where my next few paychecks, health insurance, and so forth are coming from beyond the next two weeks. I know my wife can relax a bit, too, knowing everything's pretty much taken care of.

2008-01-16

ASP.Net, Dynamic Controls, and ViewState (oh my)

Let's say you have an ASP.Net page. On this page is a PlaceHolder. In that page, controls may get dynamically loaded into the PlaceHolder. This may occur as a result of a postback event (e.g. Button or LinkButton click) or simply as a result of some logic that occurs when the page loads. However, even with EnableViewState set on the PlaceHolder, controls that you load are not automatically persisted in ViewState. What to do?

This is a problem I've run into at least a half dozen times in my .Net coding career. It's also a problem I've solved that many times. However, every time I come across it, I forget one small detail, or I do something a little differently that makes it all fall apart. So, at least for my own benefit and perhaps for the benefit of others that may stumble upon this post, I'm putting the solution here. I haven't yet seen anything that pulls all these techniques together; this might not be the first, but at least it's one I know. Links to other pages contained here may not be from where I first got my information, but I'm including them for further reference and information.

First: When you create your controls, make sure you add them to the page FIRST, and THEN set any properties on them. This is because, in order for the ViewState manager to consider the control for management, it has to detect a change, and it can only detect changes after the control has been added to the Controls collection. (Thanks to Jeffrey Palermo's blog for pointing this out, and explaining the reason for it.) But what if you don't have any properties to set? That is remedied by the next consideration.

Second: Set an explicit ID. When ViewState is saved and restored, the control IDs must match. (I've seen a reference that says you have to use a custom class and explicitly tag it "ViewStateModeById", but my experience has shown me that ID matters whether you do this or not. Sequence may or may not be as important.) If you don't specify an ID, ASP.Net will automatically generate one, and there is no guarantee that the one generated when you create it on the fly will be the same when you recreate it on PostBack. The result is, you may get the control back, but its state will not persist on the first PostBack (although it might on the second and subsequent PostBacks, since it will be consistently reloading during the PostBack from the same spot -- this behavior may be confusing).

The tricky part comes in play when you have to reload the controls on PostBack. You have to do it before ViewState gets loaded, otherwise the controls won't be there to get their ViewState restored to them. The event before LoadViewState is Init. But you have to somehow have the page remember what controls were loaded. Keeping that value in ViewState is the most convenient, but you can't retrieve that value from Init because ViewState hasn't loaded yet. What to do?

I've seen one solution to this as to use the Session. I'm not a big fan of this myself for a few reasons. First, it requires Session. I consider it a goal to write web applications that don't require Session at all, because they generally perform faster and are more scalable. Granted, I rarely succeed, and Session does have its place, so writing it off isn't a valid enough reason. Second, it is very easy to get the page state out of sync with the session state. Hit the "Back" button a couple times, and then submit. The page submits a ViewState with two controls, but the server checks the Session variable and loads four controls, and then tries to apply the ViewState to it. Third, that variable has the lifetime of the Session. At worst, if it's not cleared out or checked appropriately, its presence may cause confusion on another page. At best, it's just taking up a couple bytes of memory long after its purpose has been served.

So what's the solution then? Third: My trick is to override the SaveViewState and LoadViewState methods on the page. SaveViewState returns a serializable object that gets dumped to the page. It's fairly trivial to override this method to return an object[2] (which is still an object and still serializable), putting your own data in one element and the results of base.SaveViewState() in the other. What you need to store in that element is something you can use to recreate the controls in the order they exist on the page. Maybe it's just a number -- if you create the controls as a series and give them IDs of ID{x}, where {x} is the sequential number, then all you need is the number of controls to recreate. Or maybe it's a string array that contains the list of control IDs. Or perhaps, if the controls are of different types, it's an array of the control types that have to be loaded, or the paths to the .ascx files. Whatever it takes.

The LoadViewState method is overridden to check to see if the ViewState object is an object array, and if the first element is of the type we expect (the one we create in SaveViewState). If so, it recreates the controls based on that first value, and then calls base.LoadViewState on the second. (If it turns out not to be an object array or something is not of the expected type, I am in the habit of just calling base.LoadViewState directly, just as a safety catch in case the overridden SaveViewState got missed. It's never happened yet, though.)

The code, therefore, looks a little like this:

/// <summary>
/// Saves the view state, including the IDs of placeholder controls so they can be reloaded on postback
/// </summary>
/// <returns>new ViewState object</returns>
protected override object SaveViewState() {
    object[] newViewState = new object[2];

    List<string> docTypeSelectionControlIDs = new List<string>();
    foreach (Control control in placeHolder1.Controls) {
        if (control is DocTypeSelectionControl) docTypeSelectionControlIDs.Add(control.ID);
    }
    string[] arrayOfIDs = docTypeSelectionControlIDs.ToArray();

    newViewState[0] = arrayOfIDs;
    newViewState[1] = base.SaveViewState();

    return newViewState;
}

/// <summary>
/// Loads the view state, including custom state information from the SaveViewState override
/// </summary>
/// <param name="savedState"></param>
protected override void LoadViewState(object savedState) {
    //if we can identify the custom view state as defined in the override for SaveViewState
    if (savedState is object[] && ((object[])savedState).Length == 2 && ((object[])savedState)[0] is string[]) {
        //re-load the DocTypeSelectionControls into the placeholder and restore their IDs
        object[] newViewState = (object[])savedState;
        string[] arrayOfDocTypeSelectionControlIDs = (string[])(newViewState[0]);
        foreach (string docTypeSelectionControlID in arrayOfDocTypeSelectionControlIDs) {
            DocTypeSelectionControl dtsc = (DocTypeSelectionControl) LoadControl("DocTypeSelectionControl.ascx");
            placeHolder1.Controls.Add(dtsc);
            dtsc.ID = docTypeSelectionControlID;
        }
        //load the ViewState normally
        base.LoadViewState(newViewState[1]);
    } else {
        base.LoadViewState(savedState);
    }
}

/// <summary>
/// Loads the page, including some dynamic controls
/// </summary>
protected override void OnLoad(EventArgs e) {
    if (!IsPostBack) {
        Document[] documents = (Document[])(Session["Documents"]); //The size of this array varies
        foreach (Document doc in documents) {
            DocTypeSelectionControl dtsc = (DocTypeSelectionControl) LoadControl("DocTypeSelectionControl.ascx");
            placeHolder1.Controls.Add(dtsc); //Add control FIRST
            dtsc.ID = String.Format("DTSC_{0}", doc.DocumentID); //THEN set ID
            dtsc.InitializeControl(doc); //control initializes itself based on this document, and saves info in its ViewState
        }
    }
}

Note that this is just a quick sample. The controls in the placeholder could be modified as a result of some control event, but it really doesn't matter. The part that controls saving and reloading the ViewState of the controls doesn't change.

UPDATE 4 Dec 2009 — I created a sample project, using Visual Studio 2005 and .Net 2.0, that probably does a better job at describing things than I'm trying to do here. The project is very simple, with a single page and a single control. The page starts by loading a single instance of the control into a placeholder, and a button lets you add as many more instances of the control as you want. Every time you add a control, there is a PostBack, and all existing controls get their state and values loaded and re-saved to ViewState. You can see that the controls themselves do nothing to save their values from PostBack to PostBack; it all happens automatically thanks to the standard ViewState manager. When you click the "Submit" button, the main page loops through all the controls, collects the selected values, and builds a table to display the results. There is no use of Session, and at any time you can use the Back (or even Forward) buttons to navigate to a previous state of the page and pick up from that point.

DynamicControls.zip

2008-01-07

Come join the Social!

I don't have a Zune, but I thought it might be kind of fun, since your Zune Card and your Gamercard are automatically one, to set up my Zune Card account and join "the Social", as it were.

For a company that usually has "integration" down to a science, they're really dropping the ball on this, aren't they?

I have Windows Media Player and Windows Live Messenger. With a simple flick of an option on both sides, I can have my status message on Live Messenger automatically update to show what I'm listening to in Windows Media Player. It should be pretty much the same thing for Zune, no?

No. I have to download the Zune player. While it has some nice little features of its own (I like the collage of album art you can have in the background of the "now playing" mode), it lacks a ton of other features that are in WMP11, like visualizations, minimizing to a toolbar, updating the Live Messenger status message, responding to the media keys on my keyboard...

I did some searching on the 'net, and all I could find were echos of the questions going through my mind: Why didn't they just make a plug-in for WMP11 and integrate Zune functionality into their already-very-capable and useful media player?

2008-01-06

Water heater want a blankie?

Our hot water has always been pretty hit-or-miss. Some mornings, I would get up, turn the water on full hot until it warms up, and have to back it off to a comfortable temperature; others, I would leave it on full and have a lukewarm shower. I don't know if lately it had been getting worse, or if we just decided to do something about it, but we finally got an insulation blanket for it.

The difference was immediate. The very next morning, I noticed that the time I had to wait before I got hot water was dramatically shorter. And, the water was a lot hotter. It was very nice. Since it had been known to happen on occasion before, though, I was hesitant to directly attribute it to the new blanket; but we installed it on New Year's Day, and for the past five days since, the results have continued to be positive. I've also noticed that water out of other taps (like the kitchen sink, for instance) also get hotter water faster.

So how much money have we thrown away over the years? Honestly, probably not a lot. It's said one of the problems with a water heater is that it has to constantly re-heat the same water in the tank as it sits and cools when it's not used, and it would seem that our water heater didn't do very much re-heating once the water cooled. It's a gas-fueled appliance, and our gas bill during the summer months has always been pretty low. Although add on the amount of water dumped down the drain waiting for hot water to flow, and even if it's still not a lot, it's still waste. Plus, we've been throwing away comfort. Even if it's not a big thing, it's nice to know that we managed to do something to improve our lives. Not only is it an improvement, it helps to take the edge off knowing there are so many bigger improvements that we just haven't gotten around to, or can't afford, yet.

2007-12-30

Learning to live with Quicken

As someone with whom I once worked was fond of saying, "Once you've used it a while, you get used to it." I still think from a UI perspective that Money is the better program, but I am starting to appreciate Quicken a bit more.

For one thing, I went through my bills lists and changed the types for transfers from "Transfer" back to "Payment". Fundamentally, there doesn't seem to be any difference, since the thing that really defines it as a transfer is the fact that the Category is the other account (surrounded in brackets to help distinguish it as an account). The difference, though, is that you get the "Payee" textbox back. I went through and put the account name in the payee field, so now on my bill list, I see the accounts under the "Payee" heading. A part of me is not completely satisfied with this, as it means I have to be descriptive enough in my payee field to identify the transaction in a list, or that in some cases the payee may not match the account and only be confusing (way back when I had a Circuit City card, which I got for the finance deal for one purchase and never used again, the account was "Circuit City Card" but the bills were paid to whatever the holding bank was). But since most of my bills are paid online these days, I don't know that it's that big a deal anymore.

I mentioned before how Quicken's calculator needed to be brought up manually with a click, whereas Money's would pop up automatically on the first press of a math symbol. I'm not sure why this wasn't working for me before, but when I was entering splits paying bills tonight, it worked just fine when I hit the "+" key. Perhaps last time, it was in one of those fields that doesn't automatically insert decimal points either despite having that option turned on.

I also complained about the lack of shortcuts in the date field in Quicken. Well, it would seem that I didn't even try them. "t" does in fact enter today's date, "y" and "r" go to the start and end of the year, and "m" and "h" the start and end of the month. I also noticed that repeated presses of "y" or "m" go back a year/month, and repeatedly pressing "r" and "h" go forward a year/month. I don't recall Money doing that, but I never tried it there; now I'm tempted to fire up Money and see. Oh yes, and "-" and "=" go back and forward one day, too. I really have no excuse for missing that; I'm usually very much a "try it and see what happens" kind of guy. All I can figure was that I was in a complaining mood and started assuming the worst. Bad Yakko.

I had to balance my business checkbook tonight, and that was confusing. I had forgotten to mark my previous transactions as "Reconciled", so when I entered my statement amounts, I couldn't get the balances to match up. That, again, is somewhere Money excels and Quicken fumbles. If everything isn't exactly right before you start something, you're screwed. Money, see, would take the starting and ending values from your statement, decide the transactions on that statement need to describe just the difference, and then when you're done, alert you to the discrepancy between the bank's balance and your register's reconciled balance. Quicken is very confusing in this respect, because no matter how you mark things, nothing will match up. Or maybe that's something else I have to get "used to" -- but hopefully, I won't have to get used to that anyway once I get the first set of statements balanced.

Downloading transactions, however... Let's see. Quicken:

  1. click the button
  2. enter your "password vault" password (still wish I didn't have to do this)
  3. wait for a pause before the dialog box pops up with all my accounts and passwords (hidden -- see, I'd prefer only needing the vault password if I was changing those, instead of having to type it in so Quicken could retrieve the passwords from the vault itself)
  4. click OK and let it fly

I didn't time it, but I don't think it could've taken more than a couple minutes to be ready for me to start entering transactions and such.

Money:

  1. click the button
  2. more or less instantly, see the dialog box with all accounts and passwords (hidden -- note, no master password required)
  3. click OK and let it fly

Again, Money wins out on the UI. I've also ranted and raved about Money entering transactions in the register and Quicken using a separate (and small, un-resizable) list. However, the time required is where Quicken wins, and wins big. Money would spend the next half hour to an hour "updating transactions", and as I mentioned before, often sit there not "updating transactions" until I start to enter a transaction myself, at which time it starts "updating transactions" and refuses to let me save any changes until it finishes, five, ten, fifteen minutes later. For that, I'll enter a stinkin' master password in Quicken.

2007-12-24

How much can I put up with to resist evil?

Today is my traditional bill paying day, and it's my first day using Quicken as my primary financial software program to do it. I got the opportunity to balance my checkbook against a bank statement. How did it go? Well, let's compare.

Money would ask for my beginning and ending balances, plus ask for service charges and interest. I'd usually enter this from my statement, but then I'd have to delete the duplicate entry as those transactions would have already been downloaded. Quicken doesn't even give the option to enter those amounts, which I suppose is a blessing in my case since I couldn't seem to get it through my head that I didn't need to enter these things in twice.

Money then shows my list of unreconciled items. Its default method is to sort by checks first (defined as anything where the "check number" is actually a number, not "ATM" or "Internet" or blank) sorted by number, then all other withdrawals sorted by date, then all deposits sorted by date. Coincidentally, this is exactly how my bank statement is printed. Also, the list is editable, in that you can enter transactions on the fly — very useful if something came through on my statement that I forgot to enter. Admittedly this is less of an issue since the transactions are downloaded long before I get to the statement. Also, since Money puts downloaded transactions in the register before you "Accept" them, you can balance against them and reconcile, even while leaving the transaction "unaccepted" pending review (i.e. trying to remember what that transaction was for, so I can put the right category on it).

Quicken lists the unreconciled items in two groups, deposits and withdrawals. Each list is sorted by date. The deposits are fine, but this makes the withdrawals very difficult, as checks are much more difficult to find (their dates are updated as they clear, which is quite often not in the same order they were written; also, with my wife and I writing checks from two different checkbooks, our check numbers are shuffled together instead of separated sequentially). There appears to be no option to sort differently. Also, because downloaded transactions are not in the register until you "accept" them, you must do that step first. And of course entering new transactions can't be done in-place. (I think I recall a "Finish Later" button, so I suppose it would be possible to exit and come back.)

I've already ranted about the bills and seeing a list of "Transfer" "Transfer" "Transfer" "Transfer", not much to add there — except perhaps to note that my previous rant about really small list boxes (or dropdown boxes) applies even more so to the transaction list when you try to manually match a downloaded transaction to your register. Seriously, can I please see more than four things at a time? I did see that, like Money, Quicken has an option to "automatically insert decimal point in money fields". However, this only applies to the check register or split window. Forms, such as the one used to enter a bill or the one used to start the reconciliation process, do not auto-enter a decimal point. This inconsistency has so far led to frequent errors resulting in very large dollar amounts that would almost be funny if I weren't actually trying to get something done. Also, Quicken includes a calculator button by most every money field, but you have to click it to activate it. Money has it too, with the added bonus that the instant you type in a math symbol (+ - * /), the calculator opens starting with the value you just entered and the action primed and ready for the next value. Quicken's date control has one extra bit of lameness that I'll have to get used to. It only shows the current month. If the month ends on a Monday, that's all of that week it'll show. In Money, you'll see in a lighter color the first few days of the next month to fill out the week. It's minor, but an annoyance since I pay my bills on a weekly schedule, so when I'm spanning a month boundary, I have to tab forward to use the date control. Money also has nice little shortcuts in its date control that I used often: "t" goes to "today", "m" goes to the start of the month, "h" the end of the month, "y" and "r" for year, "-" goes back a day, "=" (under the "+") goes forward a day. Pretty small and simple, but you don't realize how much you use it until it's gone.

Yeah, so far, I'm of the opinion that, compared to Money, Quicken sucks. Except that Money tries to lead you along with its flaxen cords while it binds you with chains. Knowing that, how could I ever go back to Money?

2007-12-19

Getting there is half the fun

The conversion from Money to Quicken continues. Once the reports were finished (I don't know how long the account one ran, but the investing one was quick -- probably because it is a much smaller fraction of my database), I ran the conversion tool, which finished and launched Quicken with the converted data. Now, I know data conversion is an inexact science. I've written data conversion programs myself, and even when the source and target databases are designed in-house, not everything comes over as cleanly as you hope.

The first problem I noticed came up as I tried to set up my accounts' online access. When it converted the accounts, every account came across as a "Bank" account. "Credit Card" accounts, however, are a different type. While this doesn't seem like a big distinction, there was one very clear issue. When selecting financial institutions, Quicken filters the list based on the account type. It confused me at first, because an institution would show up, but the specific bank that manages credit cards wouldn't be there, and trying to continue with the bank listed wouldn't work (because I don't have a "bank" account with them, I have a "credit card" account with someone else).

The fix wasn't horrid, fortunately. I had to set up a "Credit Card" account for each credit card, and then I could select all transactions from the "Bank" accounts in turn and move them to the appropriate "Credit Card" account, and finally delete the old "Bank" account.

What made this process a little more annoying was the "Move" dialog box. The destination was a simple dropdown list that showed maybe four or five accounts at a time. The sort order was as it appears in the ever-present sidebar: Cash accounts first, then credit, then assets (I think -- I might have that order wrong), alphabeticaly sorted within each group (unless you move one, which I did accidentally on occasion). But there were no dividers or anything in the dropdown; it was just a list. And if you're not expecting that exact sort order -- because, for instance, the application is new to you and you don't instinctively know credit cards are at the bottom -- it makes it a royal pain to find anything. A point to Microsoft for better UI design here, where account list dropdowns are larger, have descriptive dividers, and in some cases end up being rich custom windows making it very easy to see where and what accounts you have.

Downloading transactions wasn't too painful, but again I did come across another UI blockade trying to have it save my passwords. When you elect to do so, you have to use the "password vault" wizard, where first you select your institution, then (if you have multiple "identities") select an identity (the username -- note this only appears if you have more than one), then enter the password. Why was this an issue? Because I don't often think of my accounts in terms of institutions; I think of them as accounts. I don't think "Citi Cards", I think "MasterCard". And, when I think of passwords, I think of them tied to a username. I don't connect "Citi Cards" to "p@sSw0rD", I think "My credentials for the MasterCard account are yakko_0123/p@sSw0rD". Quicken definitely loses points for forcing me to link institutions to passwords one at a time in their predefined order; another point for Money in that a full list of online credentials is displayed all at once, with a simple checkbox by each for remembering passwords right there, without needing a separate wizard. Although once remembered, I don't think I ever found where to change that information in Money, so Quicken gets a point for having a "go-to" place for password management, even if its interface sucks.

Downloading transactions is pretty straightforward. They have different ways of entering them into the register -- Money puts them in the register and has you accept them in-place, Quicken puts them in a list below the register. When you match a downloaded one to an existing one, both will remember the translation between the downloaded name (usually something messy like "WAL-MAR#919238 COLO") and the name you used ("Wal-Mart"). Quicken tells you it's doing it, though, but I wish it gave you the option to override that new "naming rule" on its popup. When I use the ATM to deposit birthday money from my mom, I'll enter "Mom" as the payee, but it'll get downloaded as "ATM DEPOSIT". That doesn't mean I want all my "ATM DEPOSIT"s to be from "Mom"...

As I was doing this, I noticed something that I knew was going to cause me pain. When Money downloads a transaction, it assigns the same Split information (if available) as it had from the last time that payee was used. Often, the amount will be different, but Money uses the old Split values anyway -- it then flags that transaction with a warning. In the conversion, those splits came across, but the warnings did not; so now I have a ton of transactions (because my wife, who spends the money and keeps promising to update the splits to what was really spent and never does) in Quicken that have invalid data. I'm going to have to compare Quicken and Money side-by-side, see which transactions Money has flagged, and delete the splits in Quicken by hand.

Loans do not convert. This, I knew ahead of time. Still doesn't mean it wasn't a pain to set that up again. I started with the mortgage, because that bill is due first, but at some point I'm going to want to rebuild those properly as well.

Most of my investment accounts, I just left as-is, because they've closed, so if the information isn't entirely accurate, it's not a big deal. My active ones, though, for some reason didn't convert right. I forget what kind of account they came over as, but it wasn't the right kind of investment or something that prevented online access. So, I set those up by hand. And that included having to enter the purchases of each lot of stocks (which, with dividend reinvestment plans over the course of a few years, was a lot of data entry). Pretty annoying; and the interface felt rather clunky. And after doing so, I of course was a little off by thousandths or ten-thousandths of shares. I'm sure this is not helped by the fact that E*Trade seems to round shares to thousandths in its file downloads -- in Money, whenever I got a statement update from E*Trade, I always had to log on to the site myself to get the exact share amounts before entering the transactions into my register; otherwise Money would complain that the brokerage statement and my Money register were off by 0.000128 shares.

I noticed, too, that categories were a little off. Quicken has its own predefined list, and in many cases, it took categories I used and converted them. It took Bills:Telephone and turned it into Utilities:Telephone, for instance. All things considered, it's not too bad. Half of my bills are under Bills and half are under Utilities now, but Quicken can move and merge categories just fine. One thing I did find amusing is it seemed to match my Insurance category to its Auto:Insurance subcategory. This led to categories such as Auto:Insurance:Automobile, Auto:Insurance:Health, Auto:Insurance:Dental, Auto:Insurance:Life...

The next thing I decided to do was to enter my scheduled bills and transfers, so I could pretend to get back on schedule. This wasn't too bad. The option to set a bill for the "First Sunday of the Month" was nice for scheduling Fast Offerings, which I used to have scheduled for the first of the month and always be "overdue". I did have a slight annoyance when doing the transfers, because the payee/category is listed at the top of the form, but transaction type is further down, and when you switch the type to "Transfer" is when "Transfer To" replaces "Payee". It should be strongly noted, however, that this replacement is probably one of the most idiotic UI blunders. When it hides "Payee", behind the scenes, it enters the word "Transfer" into the payee field. When I was done, I looked at the upcoming bill list. What did I see for the week? "Transfer", "Transfer", "Transfer", "Transfer", "Electric company", "Transfer", "Transfer", "Transfer", "Transfer", "Transfer". The only option I could find for customizing this view was to add "Account", which showed me the account that was paying out, namely my checking account. THIS DOES NOT HELP ME. In order to see what "Transfers" are due next, I have to double-click and open each one in turn.

When I went to actually pay my bills, I noticed something a little odd. Due to medical bills (and an uncooperative insurance company -- which reminds me, I still need to call and ask why they're refusing to pay for the emergency surgery performed by an in-network surgeon), cash flow has been really tight, so, in the back of my mind, I was wondering if I would need to pull money out of savings to pay this week's bills. So, after entering my bill payments, I checked my checking account balance, and it was higher than I remembered. A lot higher. Somewhere to the tune of $3000 higher. "Hey, good news! I just saved a bundle by switching financial software!" Um, no. That can't be right. I switched over to Money, and sure enough, my balance was just as low as I remembered. It seems that my next major task is to have Quicken and Money side-by-side and comparing each and every transaction over the past 10 years and see what's missing (or extra).

When I first switched from Quicken to Money, the two programs were virtually identical. Now, they are so different, I feel like I'm on a completely new operating system. (I can't quite put my finger on it, but Quicken "feels" like a Java app -- maybe it's just that all those Java-based financial apps I checked out were made to look like Quicken?) Although some of it could be chalked up to familiarity, I have found so many reasons why Money's UI is far superior to Quicken that I'm actually tempted to return Quicken for a full refund (I really wish they'd had a demo available for download).

Except I won't be going back to Money. Not when it pegs my CPU for minutes at a time doing apparently nothing, and certainly not when they demand a Passport ID to connect to my banks. That's right, it's worth the pain to go to Quicken for that.

Here's what I'd like to see from Money:

Better/faster database
Money started out on a Jet database, and I suspect it still is. Why not upgrade it to the SQL Express engine, the one they've been promoting for .Net developers? I don't know if that's the source of all the slowness, but it couldn't hurt to move into the current century. Perhaps Reporting Services could take over some of the report work?
Open database
Back in the 1900s, you could fire up Access and connect to your Money database and access your data at will. Now, there's what, one tool out there that lets you connect Excel to Money? I say let me at my data.
Lose the Passport
I do not want my data stored on your servers. Do not make that a requirement for useful and unrelated features.

2007-12-16

Do you have all your install disks?

My computer has been degrading over time. The most recent manifestation was video playback. For some reason, videos were playing as if I was in 256-color mode. I'm not entirely sure what happened; I have upgraded the video card and monitor within the past year or so, and even upgraded the video drivers more recently, but this seemed to happen well after any tinkering I did there. I tried uninstalling and reinstalling video codecs (I use the K-Lite Mega Codec Pack; it's generally served me well), but nothing seemed to fix it. I decided it was probably time to wipe and reinstall.

So, I moved the desktop files and My Documents folders, plus any other data I found (forgot about my Audible books, but I can always re-download those), to the data partition, and reinstalled Windows. So far, I can sum up the progress as "fair". Audible Manager unfortunately is giving me problems downloading books (and I'm reluctant to upgrade to the newest version, for reasons I won't describe here) -- I think I can work around that, if nothing else than by installing the latest on a VPC (something I think I need to do more often).

I ran into a big problem today, though. Sundays are usually my days for paying the bills for the week. As I've mentioned before, I use Microsoft Money for my finances, but that is something I want to change. I did pick up a copy of Quicken already, so I figured this would be an ideal time to make the switch. Unfortunately, Intuit can't read Microsoft's data files directly, so the transfer involves running a couple reports out of Money and using a tool from Intuit to import them into Quicken. Seems simple enough. All I have to do is reinstall Money and run those reports.

And it was only then that I discovered I couldn't find my Money 2006 install disc. I started with a frantic search of the disaster area that is my office, but the closest I could find was Money 2005. I was pretty sure 2006 was the version I was last using, though. So I tried the internet. I searched for Money 2006 Download, and I found a link to download a trial version. Should be good enough, all I need to do is run the reports and be done. But when I started it up, it accessed my Money data file and immediately reported that my trial version of 2005 had expired. Wait, 2005? Was I wrong? Did it read that from the data file, and was it really 2005 that I had been using? They haven't changed the interface at all; the version year is easy enough to overlook.

So I installed Money 2005, but when I tried to open my data file, I got the ever-helpful error message "Money cannot locate filename or cannot open it, possibly because it is a read-only file, you do not have permission to change it, or your disk drive is write-protected. If you have chosen the correct file and it cannot be accessed, you will need to click OK and then Restore your most recent backup file." Searching Microsoft's site brought me through a few "Page cannot be found" links (why do their own search results result in dead links?), but I finally found a page that mentioned the error might be caused by Money not being fully updated before opening a file that had been previously opened by a fully-updated copy of Money 2005. Makes sense to me. Except following the steps to update Money and then opening the file didn't help. The other explanation seemed more likely: the data file was created in a later version of Money (namely, 2006), and 2005 can't open it.

After a few moments of panic, I started to weigh my options. Attempt to buy a copy of Money 2006? Should be cheap, but an unnecessary expense, not to mention a delay I should do without before paying my bills. Find an illegal copy on the web? A possibility, one I entertained only because I had actually purchased the program, I just couldn't find the stupid disc -- but a search that would be fraught with hassles: finding the right version, making sure I got everything, making sure the download didn't include a virus or two.... What about a trial of the current version of Money? I went to Microsoft's site, and sure enough, they have one available. Their FAQ even discusses running it side-by-side with an existing version of Money on an existing data file, which gave me hope that I wouldn't see it complain the same way the 2006 trial did when I pointed it at my data file. Downloaded, installed, ran -- success.

Now, it is in the process of generating the first report. It's been at it for nearly an hour, keeping my 1st-generation Pentium 4 (i.e. pre-hyperthreaded) pegged on my nearly-clean Windows XP installation. I guess I should expect the lack of speed by now. Maybe it's not really fair for me to judge it; it is, after all, generating an XML document based on my entire financial history for as long as I've tracked it, about 15 years or so. Still, it does seem like a long time to process a file that is only 30MB, especially when I've seen reports run in an Access database (which I strongly suspect Money still uses, with the ".ldb" file it creates when it runs) up to a gigabyte in size in much less time than it takes Money to do even the simplest tasks.

Maybe it just "knows" these are its last moments with me, and it wants to make the most of them. Well, good luck with that; I'm going to bed. Hopefully it'll be done with the first report by the time I wake up, and I can start the next one off before I leave for work.

2007-12-07

We're not done yet?

Got another box today from the Microsoft repair center in McAllen, TX. Anyone want to guess what's in it? Yep, another Microsoft Xbox 360 Wireless Racing Wheel. I don't know the serial number of my old wheel off-hand, nor do I think I would recognize it, so I don't know if this wheel is the same; but I suppose it is a repaired wheel in response to the one I sent in just last week.

For those of you keeping score, that makes four boxes I've received:

  1. Empty box, with instructions and packing tape but no return mailing label, not returned
  2. Box with wheel, probably retrofit
  3. Empty box with return label, returned to MS with my original wheel
  4. Box with wheel, likely retrofit, likely response to previous box

So to anyone who bet on the wheel getting repaired and returned, despite my having already received a (probably) repaired wheel, I guess you win. Give yourself a pat on the back.

Now, why couldn't they have done this when my 360 had to be repaired? :D

Anyone know where I can get an extra set of pedals? ;)

2007-11-30

Oh, did you want this back?

"Oh, by the way," my wife said yesterday, "you got another box yesterday. I think this one's empty."

Yes, on Wednesday, I got another empty box for returning the Xbox 360 Wireless Racing Wheel. This time, it contained the instructions, the packing tape, and the return address label.

So, the old wheel is all packed up and ready to return. Anyone want to take bets on whether or not it's repaired and returned to me?

2007-11-29

Be careful what you let kids name teddy bears

I've been "reading" (actually listening to the audio version of) the book The Enemy at Home by Dinesh D'Souza. It's a rather opinionated book that offers up a view of Western culture and how the Muslim world views it, as a way to explain why America is hated by the Middle East. It's kind of interesting, and the more I read, the more respect I gain for some of the Muslim culture's values. (It's also kind of insulting, because he's so focused on blaming Liberals that he leaves out so much; it's really a specialized form of "Blame America First" -- but that's another rant.)

And then I see stories like this, and respect just flies out the window. The gist is, a British teacher in Sudan asked her class of 7-year-olds to name a teddy bear. One of the kids suggested Muhammad, his own name and the most common given name in the world. The kids voted in favor, and so it was. Well, the Sudanese government decided that by allowing the use of the name Muhammad for an inanimate object, the teacher was "guilty of 'insulting the faith of Muslims in Sudan' under Article 125 of the Sudanese criminal code" and sentenced her to 15 days in jail and deportation.

I suppose I should give the Sudanese court a little credit here. The original charge was "inciting religious hatred," which would've gotten her up to 40 lashes, a fine, and six months in prison. I'd like to think that they realized no harm was intended and chose the least possible sentence for the least possible crime.

Still, the fact that this was even an issue (and one that was so severe that lawyers assigned to her defense received death threats) sickens me. Maybe D'Souza would accuse me of ethnocentrism, but this is just ridiculous.

edit: It seems the USA Today link I used keeps changing; it was a report on the sentencing a moment ago (and is what some of my quotes were citing), and now it is a report on the response by the British government (which lacks some of the facts I quoted). I wonder if this Bloomberg.com link will be more stable...

edit 2: I've seen many reports that suggest this whole thing was blown out of proportion, that many Muslims do not support this decision. Good for them. I hope they are the majority, and that the sickos that were calling for the teacher's execution represent a radical minority. (Goodness knows this country has its share of vocal whackos that seem to do their best to try to give the rest of us a bad name.) I still think there is sufficient cause for concern, because at least some of those people who think she needed to be punished had the power to make it happen. What would've happened if the British government didn't hear about her and intervene on her behalf? Would reason have prevailed? What's that saying about knowing a person's true character by what they do when no one is watching?

2007-11-21

Goofy IE6 bug of the day

Yeah, here's one that took a while to track down.

If you are able, check out this HTML in IE6:

<table><tr><td>
<span style="color:Red;display:none;">Please enter valid date</span>
<span style="color:Red;display:none;">Please select a Month.</span>
<select style="float:left">
   <option value="0">Month</option>
   <option value="1">Jan</option>
   <option value="2">Feb</option>
   <option value="3">Mar</option>
   <option value="4">Apr</option>
   <option value="5">May</option>
   <option value="6">Jun</option>
   <option value="7">Jul</option>
   <option value="8">Aug</option>
   <option value="9">Sep</option>
   <option value="10">Oct</option>
   <option value="11">Nov</option>
   <option value="12">Dec</option>
</select>
</td></tr></table>

This is a much-stripped-down segment of a web page I'm working on, generated by ASP.Net. It is generated by two standard ASP.Net validators (one Custom and one Required) set to Display="Dynamic" and a standard ASP.Net DropDownList inside a standard, run-of-the-mill HTML table cell, with an element from an included stylesheet thrown on. What you will see is a select box, with the last bunch of bytes from the list of options displayed below it. This text cannot be clicked or selected, the IE Developer Toolbar disavows any knowledge of its existence, and it's obviously not in the source as plain text. The text does appear in the select box where it's supposed to be; there's just a duplicate, unexplained copy on the screen. The amount of text displayed varies from select box to select box -- there is another that is in an AJAX UpdatePanel that loads a very long list of names that only displays the very last character from the very last option.

This appears just fine in IE7, Firefox, and Opera (and probably most others).

What I found, as I was systematically stripping styles and other elements off of the page, is this only seems to occur when there are two validators both with Display="Dynamic" (rendered as "display:none" in the span styles), and only in a table cell. Remove either validator or change its Display property to Static or None makes it go away.

Of course, removing validators or changing their display wasn't going to be the answer -- there are too many pages and too many different ways validators are drawn and used to alter. But as I was going through the stylesheet, I found this block of code:

INPUT, SELECT, TEXTAREA {
   font: 11px Verdana, Arial, sans-serif;
   float: left;
}

I commented out the "float:left", and sure enough, the problem went away. You can try it yourself by either removing the "float:left" on the SELECT tag, or changing it to "float:none".

Why are we floating all input elements left? I'm about to find out, but considering just about everything is in a div or table cell, I'm guessing (and hoping) this style element can be removed safely...

2007-11-18

Cheaper to replace than to repair?

Either Friday or Saturday, I got a new box from the Xbox Repair Center. We noticed it as we were on our way out for the day, sitting on the doorstep, so my wife just grabbed it and put it inside. I figured it was a new empty box for the Wireless Wheel, with instructions and hopefully a return address label this time.

Today, I remembered the box and decided to get my wheel ready to ship out for repair. I grabbed the box and brought it to the kitchen table. It seemed a little heavy for an empty box; perhaps there was more packing material this time? I opened the box, and inside was... a new wheel. No pedals or power supply or anything, just the wheel.

"So," my wife says, "it was easier for them to send you a new wheel instead of sending a return address label?"

"I'm confused," I say. "And, I think, so are they."

Oddly enough, this isn't the first time this has happened. I bought a Mad Catz racing wheel for my Xbox 1 years ago. It was a nice piece of equipment, but it had this rather annoying issue in that it would seemingly randomly lose connection to the Xbox. I'd get a message saying "Controller disconnected, press A to resume" from the game. I could press A immediately and be back in action; although the game would often forget my controller scheme and revert to the default, which meant I had to figure out which standard controller buttons mapped to which shifters and levers on the wheel, which was of course different from the wheel configuration -- very annoying to say the least. I contacted Mad Catz support e-mail and explained the problem. Apparently, some of the wheels had an issue where the vibration motors would interfere with the controller signals. They were aware of the issue and offered to send me a replacement immediately, and in the meantime told me I could work around it by turning off rumble in the game. The replacement I received worked a lot better, but it would still disconnect on occasion; when I emailed Mad Catz and explained that the problem was much improved but still there (I would see the problem maybe once in every three races), they were not satisfied and sent me yet another replacement. That one worked flawlessly. I asked them each time what I should do with the old wheel(s), and their response was just to toss them, not to even worry about returning them. Being the pack rat that I am, they're still around, even if they don't get used (except once when I and my wife's brother's kids turned off rumble and used them for some split-screen racing one holiday).

I'm starting to think I could make a living doing this. If I could fix these things myself (which is the one critical piece missing), I could make some serious money buying racing wheels, calling the manufacturer when they're defective, and getting replacements sent to me.

2007-11-14

They may not have lions or tigers...

It's winter time in Colorado, which means time to buy stock in hand lotion. Even someone with naturally oily skin such as myself ends up with dry, scaly hands when heaters turn on for the season.

My wife got me some lotion to take to work, and I was just looking at the label. It is Neutrogena's "Norwegian Formula Fast Absorbing Hand Cream". "Developed with dermatologists", the back of the bottle proclaims. But, why "Norwegian formula"? What is so special about Norway that would make a hand lotion developed there better than, say, a "Swiss formula" hand lotion? Do all Norwegians have "perfectly soft, supple, smooth hands" (to quote the bottle) thanks to their world-renowned hand lotion formula?

Perhaps it's as my wife says. Americans equate "high culture" with "European", but since the Swiss thing and the French thing have been overdone, they picked another country. Perhaps there were involved marketing meetings where they discussed what country they would use next.

What about Denmark?

Hmm. "Danish Formula." No, sounds like a pastry. We'd have law suits from people seeing "danish" and trying to eat it for breakfast, we'd have to have a whole awareness campaign about not eating hand lotion...

Sweden?

"Swedish Formula." I don't know, makes me think of the Swedish Chef.

Maybe we could get the Swedish Chef to market it for us!

No, the licensing fees alone would bury us. Besides, we're selling skin care products, not food, remember?

How about...looking at a map of Europe...Finland?

Finland, Finland, Finland... "Finnish Formula"? Sounds like something you'd use to treat wood, not skin.

I've got it! Norway! "Norwegian Formula." It's still white European, but has a bit of an exotic sound to it.

Why, that's brilliant! Good work, everyone! Let's break for lunch.

2007-11-08

No more Money for my money

Several years ago, I switched from Quicken to MS Money for managing my finances. The two programs were virtually identical, and I think I had a free offer or something for Money, so the choice was pretty easy. And for a long time, I was fairly satisfied with what I got.

Lately, though, I have started to be more and more frustrated with the program. The major issue is one of performance. Upon launching Money, the CPU will peg at 100% for minutes at a time, when it seems to be doing nothing. Downloading transactions can take 15 minutes to a half hour, with the added frustration that it will sit there and do nothing until I go to enter a transaction, and then, only then, will it start "updating transactions" and lock the form I'm working on ("operation could not be completed at this time") until it gets to a stopping point. It's like it's deliberately wasting my time. When it downloads a transaction that matches a scheduled bill, quite often it will match the downloaded copy to the next instance of the bill (instead of the instance on the exact same date). If I'm not careful, it will consider that next bill paid, and I won't get reminded when it is due. And when I click "Change" to match it to the correct date's instance, it's another 5-minute-or-so wait before it shows me the list of transactions to match.

The straw that has broken the camel's back, however, is this new feature they've been trying to push for a while. The gimmick is, you link your Money file to a Passport ID, and you can access your financials from anywhere with a web browser. Sounds neat, but it doesn't take a genius to figure out this means uploading your information to Microsoft's servers. Call me paranoid, but I don't want my bank accounts on a publicly-accessible server that can be accessed from anywhere with a web browser.

It started with simple "reminders" that you can secure your data file with a password -- a move which automatically enables the "access anywhere" feature. However, now they have locked out one of the main features behind this "requirement". For some reason, the link to the online services for one of my credit cards disappeared, meaning I couldn't download transactions for it anymore. When I went to set it up again, Money insisted -- nay, required -- that I enable the Passport link. It also does this for new accounts, even new accounts at existing institutions. For example, it refuses to acknowledge the new savings account I just opened up, even though I'm sure it's already downloading it with all the other accounts from that same bank with the same login; certain, because before it decided to play this little "give me all your data or I start taking away features" game, I had opened new accounts at existing banks, and the very next update, Money offered to set up the new account it found. Not anymore, though.

Probably the most insulting chapter of this story is that it did not happen when I upgraded versions. It is the same Money 2006 I've had for over the past year. At some point, it must've downloaded a program update that took away a feature of the program that I use, and held it hostage in trade for uploading my account information to their servers.

And to think I used to joke about Microsoft requiring your bank account information before their software would work.

I don't know if the open source projects are mature enough for my needs yet -- they weren't the last time I checked, but that was a few years ago. I have a feeling I'll be purchasing a copy of Quicken in my immediate future.

2007-10-31

Put it in this box and send it nowhere.

It's time for another Xbox 360 Wireless Racing Wheel update!

I got a very large box on Monday. Enclosed was a strip of packaging tape and a sheet of picture instructions showing what to do. Take the wheel -- not the pedals or mounting bracket -- and put it in the box, with the sides folded like so. Use the strip of packing tape to seal the box. Put the return shipment label over the original shipping label.

Hang on a second. What shipment label?

Yes, it seems they forgot to include that critical piece of equipment.

So, I called my friends at 1-800-4MY-XBOX. I got past the automated gatekeeper and to (I assume) a living person. I told him my situation, he looked something up, and then told me that the wheel retrofit works differently, and they won't send me a box, I need to send my own.

Er? But I have a box, it was sent to me. After explaining this, he says he needs to put me on hold and talk to "his resources". (But first, he asks me to verify my information, including my 360's serial number; good thing I decided to make this call working from home today.)

20 minutes of bizarre techno-pop hold music (singing in English, with an occasional female voice in between songs who said a few words in a language I couldn't identify) later, he comes back on the phone to tell me they will be sending another box with the return shipment label, and he gives me a new reference number to write on the outside of the box.

I admit, buying the wheel was an indulgence. I haven't used it that often. Although I have been looking forward to PGR4, it was released early this month, but I still haven't picked it up, knowing full well that Halo 3 will continue to monopolize my time for a long time yet. So I'm able to view this whole retrofit saga with detached amusement. After all, it could be worse...

2007-10-21

Can I stop being sick now?

Three weeks ago, I was sitting in church, and I started to get a cramp in my stomach. This was about quarter to 10 in the morning. About quarter to 11, it was getting worse, so I spent some time in the bathroom to try and get whatever what was in there causing problems, out. I got plenty of crap out (so to speak), but the pain persisted.

I got my family home quickly, and since it was Fast Sunday, my wife thought it was probably hunger-related, so she gave me an ice cream sandwich. It did nothing for me, and I took myself upstairs and laid on the floor outside the bathroom waiting for whatever was in my stomach to pass in one direction or another and get out. The pain just kept getting worse and worse. Nothing came out the back, and the most I could do the other way was dry heave. My wife wanted to take me to the emergency room, which I resisted for some time -- if I was going to be miserable and (as I assumed) in need of a bathroom at some indeterminate yet immediate point, I'd rather be at home than in an uncomfortable hospital emergency room where my chances of immediate attention would be slim. After a while, though, the pain was just too intense, and I couldn't take it anymore.

Fortunately, the hospital was fairly new, and pretty vacant on a Sunday afternoon. I was hooked up on painkillers administered by IV. Initially, they figured it was a kidney stone, so they did a CAT scan. Sitting perfectly still and holding your breath is not easy when you're in intense pain (even on painkillers). The scan came up negative for kidney stones, but it did show that my appendix was on the edge. If the pain was in the right side, they would have been calling for an appendectomy, but since it was on the left, they weren't sure exactly what it was. They just kept me on painkillers until either the pain passed so I was able to go home, or they could figure out what to do for me.

Eventually, my wife had to take the kids home, so she did so and made me an overnight bag. Then she called our home teachers to come deliver the bag and give me a blessing.

After the blessing, the pain moved over to the right side of my stomach. Unfortunately, they had decided to admit me to the hospital proper, a process that took a couple hours, during which the ER doctor wasn't interested in me (since I was supposed to be out of there, and with a football game just ending and people starting their stupid party tricks, they were starting to get busy), so it took some time before I could get seen. Once I got checked into my room, though, I could talk to the nurse and tell her what was going on, and she got the on-call surgeon, and he confirmed the appendix needed to come out.

Well, everything went pretty fine, all things considered, and I came home a couple days later. It took some time to recover, and fortunately I have a job where I could work from home. After a week and a half or so, though, just as the antibiotics wore off, I started feeling sick again. My wife was coughing a bit, so I figured I just caught whatever was going around. But after a week of this, I went in to see my doctor (I had already had this appointment as a follow-up to some migraine treatment), and he diagnosed me with atypical pneumonia.

This was just a few days ago. I'm just finishing up the antibiotics for this, so hopefully I'll stop coughing and being tired and out of breath soon. I am concerned, though, because last year I had a sinus infection that took two courses of antibiotics to cure, and it ended up killing all the wrong bacteria in my gut and I had to go on another set of medication to put everything right again. I really want to avoid that this time around. :-/

2007-10-11

Something new to report?

Just got this letter from Xbox Support:

Dear Wireless Racing Wheel Owner,

Thank you for registering to receive the free wireless wheel retrofit. We are contacting you to let you know that you will be receiving a pre-paid shipping carton for you to send your Wireless Racing Wheel in to Microsoft for the necessary retrofit. The carton will be sent to your registered mailing address, and will contain packing materials, a return postage label, and instructions for the return.

You should receive your retrofitted Wireless Racing Wheel within 2-4 weeks of its receipt at Microsoft. After the retrofit, the customer can use the AC DC adapter.

For further information and support, please contact www.xbox.com/support.

Thank you

XBOX360

A phone call to tell me this same thing wouldn't surprise me.

What does surprise/concern me, though, is that last line in the second full paragraph: "After the retrofit, the customer can use the AC DC adapter." Suddenly they talk to me in the third person?

Call me a snob or grammar nazi if you will, but I expect communication to be gramatically correct, especially if it's customer service from a multi-billion dollar company.