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.

2007-09-17

It's dead, Jim. (epilogue)

Got an email from Xbox Customer Support:

Good news, your Xbox console has been shipped! You can expect to receive it in 3-5 business days.

For your convenience, your shipping information is provided below:

Carrier Name : UPS
Carrier Tracking Number : 1Zblahblahblah

You may track the status of your package using the UPS website and the tracking number provided above.

Yes, I just got that email, for the replacement console I received 2½ weeks ago. *eyeroll*

2007-09-11

Another week, and all's well

So glad the internet is back, because then I could get the phone call telling me that, yes, there is no change to the status of the wireless wheel retrofit kits. *insert eyeroll here*

To report a problem with your phone, please call...

Our internet service was out this morning. Since we have VOIP, that meant the phone was out, too. So I picked up my cell phone and called 1-800-COMCAST, hoping that if I reported the problem before I dropped the kids off at school, it'd be fixed by the time I came back home to work. The call went something like this:

Please enter the phone number where you have service, or wish to order service.
> ##########

For English, press 1. Para espagnol, numero 2.
> 1

To report a problem with your service, press 1...
> 1

For cable TV, press 1. For internet, press 2. For home telephone, press 3.
> 2

Did you know you can visit our website for service requests? Just go to www.comcast.com/service to chat with a live customer service operator!