Month: February 2014

Note: my experience below happened in February of 2013, I’m just super late in publishing it.

There’s been a growing trend in the way corporations approach customer service. In industries that have become largely undifferentiated in the products or services they offer, the thing companies are trying to do is put forth the best possible customer experience. Which is great, you should always treat your customers well. But a recent experience has made me wish some of them would take a page out of the big book of common sense.

I recently had to contact Apple for technical support. As a very technical person, I don’t look forward to having to talk to tech support. I have to invest a certain amount of time going through the standard menu of questions about my problem. Sometimes the level 1 person can solve my issue, but often they can’t and things have to be escalated. Only they don’t always know (or are allowed?) to do that.

My Apple problem was strange and unexpected: I tried to buy an iTunes e-gift card for my mom’s birthday. I’m 99% positive I’ve made this kind of purchase before but it’s been a while. I hadn’t upgraded to iTunes 11 yet so that was the first thing I did. When I tried to complete the purchase I got a message saying it couldn’t be completed and that I’d need to contact Apple for assistance. So that’s fine. Only it was very not-fine.

I went to apple.com and filled out a request for support. I got a lengthy e-mail reply that started out with the words ‘A wonderful day to you!’ Why, thank you! The person indicated they were working on my problem, that I would get an e-mail after the matter has been investigated, etc. A day goes by and I get another reply, in which the same person says sorry but ‘my account is not authorized to obtain content from the U.S. iTunes Store. For this, we are unable to provide further information, but I strongly suggest you to review the iTunes Store Terms and conditions.’ Whaaa? That made no sense at all, and was entirely too cryptic.

My first thought was that they think I’m doing something fraudulent. I know all about Mat Honan’s experience and I’m sure Apple is still feeling some paranoia from that. And I did notice that the credit card I had on file in iTunes had expired when I went to make my purchase. I updated my payment info, but maybe they still weren’t sure things were on the level. That’s understandable.

I replied back saying that doesn’t seem right, I’ve bought a lot of stuff over the years through the iTunes store, could they escalate my ticket. What proceeded was two weeks of back and forth over why they wouldn’t let me give them money, and why they wouldn’t tell me what was really wrong. I don’t expect them to tell me every little detail about what’s in their records or their processes for customer disputes. But at least give me the overall reason, like ‘the payment info we got from you appears bogus’. More information is usually better than less. Instead in each e-mail they kept using phrases like ‘I acknowledge that you want to have an explanation for this’, apologizing profusely, thanking me for being a customer, and giving me a link where I could leave feedback.

Eventually they flipped whatever switch would allow me to purchase an e-gift card via iTunes, but by then the birthday I was buying it for had passed and I had already gone with Amazon. So sorry Apple, but I may need to look elsewhere for my MP3-buying needs in the future. My suggestion is you try to be more open and forthright when helping customers, rather than include so many nice platitudes in your e-mails.

Musing

Adobe uses a novel though hardly unique approach to distributing certain software. If you want to install say, Acrobat Reader onto your Windows machine, you go to their web site and download an installer. Only you don’t download an installer, you download a bootstrapper that downloads the right thing for you, based on your OS version, language, and platform. More and more vendors have adopted this approach over the years as different version of Windows have proliferated, 64-bit has became more widespread, and they have wanted to make the process easier on the user.

What Adobe does that is unique and unbelievable on Windows is once you launch the bootstrapper, it deletes the file. The program is running in memory but the actual executable file is gone. This means if something goes wrong during the download of the real installer or the subsequent installation, you can’t just restart it. You have to re-download the bootstrapper. Needless to say, this completely sucks and shouldn’t be necessary.

The Acrobat Reader bootstrapper has been like this for years and after recently rebuilding my laptop and installing it, I started to wonder if there was perhaps some technical reason, however outlandish, for that behavior. Is it because it needs to be chained together with other installers, or maybe bundled with some other completely different one? It needs to run silently and can’t leave any footprint on disk? They are trying to keep your machine clean??

Apparently Adobe has a direct download page that doesn’t try to detect the specifics of your machine, and will let you download a full installer that doesn’t have this behavior. A quick Google search reveals that several people have noticed this and none of them like it. Maybe Adobe should put a link on the Acrobat Reader download page in big type that says something like ‘Why we delete this file after you launch it’, which takes you to a page with an explanation. That would be nice.

Musing

It’s been over a year since I last touched my bookmark browser, and it needed some attention. There were a couple of outstanding bugs to deal with, plus it seemed like a good time to update the various libraries it uses.

One bug that occasionally cropped up is logging in for the first time and changing to the bookmark page, but having nothing show up. If I did a full refresh of the page then everything would be fine. I never quite figured out what was going on, until now. I assumed there was something I wasn’t doing right with Knockout, so I tried moving the code that does the bindings from the PageBeforeShow event for the bookmark page to right after the AJAX call that gets the data. But that didn’t help. Turns out it was something simple: the bookmark container is initially hidden, and I was never showing it after the first successful login, assuming the app was started in a logged-out state. The solution was showing the container right after the bindings were applied.

And speaking of content not showing right, it suddenly became necessary to add an explicit jQuery Mobile refresh call on the list that holds the bookmark data, like this:

Without such a call none of the jQuery Mobile styles would be applied unless I did a full page refresh. Not sure why, but whatever. The latest version did resolve a weird style issue with the bookmark menu list showing a double border around each list item, so that’s good.

Musing

This is part 1 in a series of posts about creating a mobile web app for browsing music databases.

In my continuing quest to up my web/mobile game, I decided to build a web app for searching the All Music database. There are a number of music metadata repositories on the web, some robust and some paltry. The one I like the best is run by Rovi and powers All Music, along with iTunes and several other big name media products. They have an iOS app that allows you to access all parts of the data store. It’s a great thing, but the search portion is not very user friendly and doesn’t always work the way you expect.

My goal was to create a basic search form that allows you to look up an artist, album, or song title. The native app had an all-in-one search feature where it tried to dynamically show you results for what it thought you were looking for, but it often failed to return what I wanted. I understand the ease and utility of having a single field for different types of information, but I wanted to run specific searches.

The first step was creating an API that would essentially wrap the calls to Rovi’s RESTful API. I didn’t want to interface directly with Rovi for several reasons: to allow the results to be formatted differently if I wanted, to make it easier to switch to a different data store in the future, and so I wouldn’t have to allow cross-origin requests. I went with the standard Web API project in Visual Studio 2013.

Getting the routing to work properly was the only real hurdle with the API. The default Visual Studio template sets up routes that include /api/<controller>. But I just wanted /api and not the <controller> part. It’s tricky because the base controller class is ApiController. The MVC convention is controller class names are of the form <my_ctl_name>Controller and then my_ctl_name becomes part of your route. Having my own class called ApiController wasn’t possible, so I called it SiteApiController. But how to tell all requests to use that controller? Enter WebApiConfig.

I removed all the default routes and added two new ones: one for searching and one for lookups. I was able to specify the exact controller class and a route template that only included /api and not a controller designation. Bonus points to Microsoft for allowing lots of route configuration options.

Even though I only needed to make single, synchronous requests to Rovi, I used HttpClient to do it. There might be a need in the future to make multiple simultaneous requests to build a query result, if so it will be easy to make them async. The next step was the front end.

Coding