Entries from Jun 2004 ↓

Mea Culpa, Dell

Last Wednesday I blogged about how bigger companies, like Dell and Sony, do a poor job of providing a rapid response to online orders and customer concerns.  However, I was hasty in my blogging and need to (partially) apologize to Dell (but not Sony in this case.)

The computer arrived on Monday, one day after I needed it, but it turns out one day wasn’t a problem.

Sorry Dell.  Mea Cupla. You done good! :)

P.S. The reason I said "partially" apologize was Dell’s online order tracking system quoted the delivery date as if the computer had to first be built instead of recognizing it was a Dell Outlet purchase and hence was already built. Further, when I emailed to ask about it, they replied with another wrong date that was sooner, but still a long way off.  So the info they gave me about the delivery was wrong and needlessly caused concern, but the timing of the delivery was actually acceptable.

Tags: , ,

Mort, the “Hobbyist”, and the “Occupational” Programmer get their due


Several months ago I blogged about the need for a much simpler way to get into .NET, and I named my proposed solution VBScript.NET (in hindsight the name was a poor choice because people assumed I was proposing porting VBScript to .NET instead of providing a simplified VB.NET, but highsight often is 20/20…) And I was not the only one, lots of others blogged about the same topic (see here, here, here, here, here, and here to list a few.)

It looks like Microsoft was listening after all! Check out the New Visual Studio Express products, in beta at this point! I haven’t downloaded any of them yet, and I don’t know if they’ll address all the issues my proposal was meant to address, but even if not at least they are trying!

Kudos Microsoft!

UPDATE (2007-01-01): I’ve since come to the conclusion that the Express Edition still does not address the needs of the occupational programmer.

It’s Always Something (#1): Wrestling with System.Xml.Xsl.XslTransform and the Document() function

It’s always something!

At Xtras, we have a rather sophisticated email broadcast system that we developed internally. Our system uses a set of tables in our SQL Server database that models the type of email, who it should go to, the mailing lists, etc. It loads each newsletter subscriber’s name and email address using a FOR XML EXPLICIT query from our SQL Server. It uses .XSL files to contain the HTML and/or Text content for each email, and then it uses a System.Xml.Xsl.XslTransform object to generate each HTML/Text email using a transform of the subscriber’s .XML fragment and the current newsletter’s .XSL file.  Once generated, it attempts to send using the SMTP component from /n software’s IP*Works!, and logs the success of failure into our database.

It is actually quite an elaborate and powerful system, and my hat’s off to Bill who developed it. However, it isn’t perfect. First, there is very little user interface; "the cobbler’s children go barefoot" as they say.  The second is our infrastructure doesn’t contemplate organization of .XSL files; there are literally hundreds all in the same directory.  But probably the biggest problem with it has been our approach to creating new email newsletters; we literally copy the XSL file from last newsletter issue and edit it, updating it for the current issue. 

Data driven?  Automated?  Modularized?  Yes it is, at least the parts that had to be are data-driven, automated, and modularized.  Like inserting the recipient’s email address and sending the emails.  But all other parts are manual!  Maybe you’ve gotten emails from us in the past where we’ve made errors like having two different dates on the same email in different places?  Now you know why…

Recently I grabbed a book on XSLT (Michael Kay’s XSLT: Programmer’s Reference; it’s actually quite good even though it’s four years old by now) and started learning how to write modular XSLT.  Of course it has taken longer than I planned so our next newsletter is late (our June newsletter for XDN; anyone notice its really late? Sorry…)  I managed to prepare a really elaborate stylesheet and pulled almost all of the content of the newsletter from data in our SQL Server database.  I then got the newsletter ready to go and passed it on to Bill to have him send it, and guess what?  It blew up his email system, giving code access security errors! 

Now you have to know Bill. He is very focused on completing his current projects, so Bill was not happy that my new .XSL blew up his "working" system!  But he understood that it would probaby take longer to rewrite than to solve the problem, and it is something we need to solve anyway.

The code access security error took us down the wrong path.  What I had added to the XSL file was a call to the XSLT document() function to load a second XML document (the newsletter content) from a URL, and we both thought XslTransform was telling us we needed to resolve a security problem in accessing a URL via HTTP.  Well, that wasn’t it; it was actually quite simple.  We needed an XmlResolver. More specifically, we needed an XmlUrlResolver.

So the moral of this long-winded story is, if you are using an XslTransform() and you add a reference to the document() function in  your .XSL file, you’ll need to add an XmlUrlResolver for it to work.  What follows is a self-contained simple example; copy into a class can call that class’ Exec method on a form click event to test (oh, and you’ll need to put an .XML and .XSL file at http://localhost/xslt/ for it to work):

Imports System.XmlImports System.Xml.XPathImports System.Xml.XslImports System.Text.EncodingPublic Class Test   Private Const outFile As String = "XsltOutput.html"   Public Sub Exec()      Dim xslt As New XslTransform      xslt.Load(FileUrl("XdnJun2004.xsl"))      Dim data As New XPathDocument(FileUrl("Subscriber.xml"))      Dim writer As New XmlTextWriter(outFile, UTF8)      Dim xmlr As New XmlUrlResolver      xslt.Transform(data, Nothing, writer, xmlr)   End Sub   Private Function FileUrl(ByVal filename As String) As String      Dim baseUrl As String = "http://localhost/xslt/"      Return CType(baseUrl & filename, String)   End FunctionEnd Class

I hope this post finds its way into Google’s index in hopes others with the same problem don’t have to spend as much time as we did trying resolving this problem.

Trying to help them, and they snub you!

Via Scoble, Mike of HackingNetflix.com blogs about Bloggers & Corporate Public Relations Departments.

Seems Mike’s site is a(n oddly naming) tribute site to NetFlix, yet when Mike asked to be on their press list they declined, and when he asked them to support an "Ask Netflix" column on his website they wouldn’t return his calls and were dismissive in their email replies.

Reminds me of a similar conversation I had with a local company about RSS, about which I then blogged. Our course Mike was probably more professional in his email than was I. :-)

The irony of this all type is Mike (and I) were really trying to benefit NetFlix (and TechLinks) by offering help and/or suggestions. But instead of at least treating the person offering help or suggestions with the courtesy most good companies would treat a customer, they respond dismissively at best, or with contempt at worst.

Is that any way to treat ones fans?

Tags: , ,

Often, Big Companies Suck when compared to Smaller Ones

I have a new employee starting on Friday and needed a new computer. Generally I like to buy from Dell because they keep all system info online for future retrieval. So yesterday (Monday, June 21st, 2004) I went online to Dell’s Outlet and selected a pre-built system and requested it to be shipped Fedex Saver (3 day) on my account. (I know, I always do things at the "last minute", but that’s because prior to the last minute, something else is always urgent!) So if it shipped on Tueday it would arrive Friday, no problem (the new employee is technical and will be tasked with setting up their own machine.)

Well, I go online to make sure it shipped, and notice it is "in process" with an estimated ship date of July 8th, 2004 (13 days after I need it)!!! I left an email message just now, but my expectations they will expedite it are less than 1%, and I’ll probably have to cancel the order and find something else locally.

What reminded me to check the shipping status was an email from NewEgg, which is where I placed an order after placing my Dell order for a really nice monitor to go with the new system I ordered from Dell. Contrary to Dell, NewEgg emailed me a shipping confirmation with my Fedex tracking number showing that my order will arrive tomorrow, a day early!  I selected NewEgg partly because they had a really good price, but primarily because their CNET rating was very high, and boy did they prove why!

This whole experience reminds me of a similar one about two months ago when I decided to buy a digital camcorder. After searching CNET for the best combination of price and rating I settled on buying from PCandPlasma (has anyone ever noticed how ALL online and mail-order camera stores are located in New York City? But I digress…)

After getting the annoying but ubiquitous (from a New York City online retailer) phone call saying they need to talk to me before shipping my order, and then attempting to hard-upsell me on cheap yet expensively-priced tchotchkes (which didn’t upset me as I went shopping for a low price, and the low price stores all do it), I stressed to the sales rep at PCandPlasma that my order absolutely had to arrive within three days.

I got everything within two days.

But PCandPlasma didn’t have everything I needed in stock so I went over to SonyStyle.com to pick of the remaining items, most importantly a tripod. I placed the order online, and then checked it the next day.

It hadn’t shipped.

I called, and found that their staff really couldn’t tell me exactly when it would ship because had different warehouses and couldn’t easily tell what was where. Sony’s customer support rep told me she thought it would arrive in time, and that she would call me back to confirm (to her credit she was very nice, but she also didn’t call back.)

I needed on Friday as I was planning to travel on Sunday. Guess what? It didn’t arrive on Friday. I checked online and it hadn’t even shipped. So I emailed and requested the order be cancelled (I didn’t call because the prior call took 45 minutes on hold to speak to someone.)

As an aside and not directly related to the core theme of this post, on the next day, Saturday, I went to local Wolf Camera to pick up the needed tripod. (Unfortunately the saleman there didn’t think to upsell me to a tripod with fluid head for video, even though I asked if the one I selected was okay for video. Who was I to know at the time what I really needed? I didn’t learn that until during and after the trip! Funny thing was he was on commission and the tripod I ended up getting from another salesman was $180 instead of the $30 I bought from him. Duh!)

When I got back from my trip, I found that my Sony order has been delivered on Wednesday. Not only had there not been any chance of getting it by the prior Friday, they didn’t even pay attention to my request to cancel! So I had to then go to the trouble and expense of sending it back (to be fair the accepted the RMA with no hassle though I wonder if PCandPlasma. But then I’m only conjecturing because of the hard-upsell.)

So the bottom line is this: If you want and/or need fast service, forget the big guys. They are either too big with disjoint processes that can’t serve you well if they try, or they are simply too big to care. Go with the small scrappy companies for whom your business is their lifeblood. They are the ones who will bend over backwards to make sure you get what you need, when you need it.

Good XSLT Tutorial

I did a web search for an XSLT tutorial a few minutes ago and came across a really nice one I want to remember at topxml.com.


Where do you buy your .NET Components and other Programming Tools?

Disclaimer: I run a company (Xtras.Net) that sells .NET components and other programming tools so this topic significantly affects my own livelihood as well as that of my company.

Over the past 10 years, since we launched our first printed VBxtras catalog, the state of Windows-based programming has changed.  In those days most Windows programmers wrote smaller departmental apps using VB3.  Today, Windows-based programming as is often server programming as not, and it is usually mission critical for larger enterprises using .NET. 

I think Windows programmers have also changed. Programmers used to have an almost naive can-do evangelistic attitude but didn’t often think about the maintenance of their app a decade later.  Today programming is business, and business brings all seriousness with it.  Yes I am painting with a broad brush, but this isn’t the point of the essay so I hope you can let that go.

With the change I believe programmers have come to view components and tools differently too.  Previously they were "cool toys"; things they could use to build even cooler apps.  Today components and tools are about saving man hours and reducing time-to-market.  Yesterday’s components and tools cost $50-$500, today’s cost $200-$2000 or more.  Again, a broad brush I know.

With this change has come a change in sourcing behavior too.  Used to be the programmer called up a cataloguer like VBxtras that had all the components and tools to help him select, he used his credit card to order, and had the product shipped to arrive within a day or two.

Today, it seems .NET developers do one of two things.  Either they start by Googling for something like ".NET SMTP Component", download the demo of the first one they find, and if it meets minimum requirements, they buy it direct from the vendor at full price.  The other approach is they do serious research into several competing products like PDF engines or what one of our main vendors calls a "presentation layer toolset" by speaking to each of the vendors for those products, and then they either buy directly from the vendor or simply pass on to purchasing.  "Purchasing" then simply goes with their corporate reseller such as Software Spectrum and doesn’t or even won’t consider going to a specialist in .NET Components and Tools.

So it seems to me sourcing of .NET components and other tools comes down to the following options:

  1. Buy direct from the vendor at full price
  2. Buy from a corporate reseller like Software Spectrum at whatever price
  3. Buy from specialty reseller like Xtras.Net at a discount price

In corporations saving a few dollars doesn’t seem important, so the upshot I have seen is fewer .NET components and tools and being purchased from specialty resellers like Xtras.Net, even if the developer first learned about the product at the specialty reseller’s website. If this sounds like sour grapes, well I unfortunately guess it is.  I tried to write this essay so it did’nt sound that way, but I think I failed.  But the rest of this essay should instead give you good food for thought why it makes sense to purchase from a specialty reseller like Xtras.Net.

Often I hear developers believe they will get better support if they buy direct from a vendor. Whenever I mention that to one of my vendors we have a very good laugh (my laugh being the sad one.)  Most vendors couldn’t keep track where someone purchased if they wanted to! Those that can track know it is bad business to be hostile to customers because they purchased from a convenient source.  So please know that buying from a reseller does not harm your prospects for support.  And if you know for a fact that a specific vendor will give you poor support if you buy from a reseller that vendor will certainly be hostile to you in other ways too, so seriously consider buying from a vendor that is not hostile towards segments of its own customers.

To introduce the next topic, I’m sure you realize using a 3rd party component is not something you should do without consideration.  Apps tend to have a long life, and you should consider maintainance 5 and 10 years from now.  Access to source code certainly helps, but knowing a component vendor will continue support is even better.  And what about royalty fees?  When you buy direct from a vendor, they will not go out of their way to show you their warts. But the job of a specialty reseller like Xtras.Net is to provide you with as much information as possible about each and every component so that you can make an informed decision. When you buy direct, you remove the funding specialty resellers need to do the research to help you make your best choice.

Another thing is developers often don’t give any thought to where their products are sourced.  They send a P.O. to purchasing and let purchasing decide.  Of course corporate purchasing usually doesn’t consider specialty resellers unless the developer almost demands they buy there (ironically, the specialty reseller is often the one with the lowest price.) And corporate resellers that purchasing so often uses don’t even know the first thing about .NET components and other programming tools.

So where is all this leading?  To this: I’m asking that next time you decide to purchase a .NET component or other programming tool you consider buying from a specialty reseller like Xtras.Net instead of direct, or that you do what you can to get your purchasing department to consider using the specialty reseller.

What’s in it for you?  Well, it is my goal to build Xtras.Net and related websites out to provide you with a tremendous resource for comparing and contrasting 3rd party .NET components and other tools; well beyond anything that is currently on the Internet in our space.  I also plan initiatives that will lower the average price of .NET components and plan others that will significantly reduce the problems associated with 3rd party components today as well as increase the reliability of using them. 

Every week we meet to plan and every week we have to decide where to put out resources. Since I don’t have venture capital nor do I have public money, I have to operate in a cash flow positive.  If sales are low for the month, we have to take our resources away from building out our infrastructure to provide these benefits of which I mention and put them into getting up sales in the short term.  I can’t tell you how frustrating it is when we realize that we have to stop working on these projects and instead have to put our resources toward yet another promotion.

But I need your help. 

When you are about to buy a 3rd party .NET component or other programming tool, please consider buying from Xtras.Net and/or please ask your purchasing agent to consider buying from Xtras.Net.  If enough of you do over the next year or two, I can promise that you will be very glad you did.

Thanks in advance for your consideration.

Tags: , ,

Features I REALLY want in TSQL, Part #3


Yes, I want refactoring in TSQL/SQL Server. What do I mean by Refactoring in SQL?

Specifically, I want to be able to evolve my database schema without breaking the application. For me at least, I frequently evolve the naming of my database schema as I’m adding features to deployed apps, but it is really hard to know for sure that I’ve updated everything that depends on those changes.

I have seen tools that generally hunt down all the references to tables, views, stored procedures, fields, etc. within SQL Server objects and update them for you. Some tools even look outside in VB.NET or C# code. But those techniques are, by their very nature, incomplete. I mean, what about dynamic SQL?

So what do I think is needed?

The first needed feature would be aliases for SQL Server objects. If I could define an alias for any SQL Server object such as a table, view, stored procedure, field, etc and have it behave when referenced exactly as the object it aliased, I would have part of what I need. For example, I envision you could define a alias called [Item] on the table [Inventory] like so:


Then the following two SQL statements would be identical in function:

SELECT * FROM Inventory

As would these SQL statements:

UPDATE Inventory SET Price= Price * 1.01
UPDATE Item SET Price= Price * 1.01

The second feature required would be the ability to tag an object as having all accesses to it logged:


Once you tagged a SQL Server object with “log access”, SQL Server would write a record to a special log table every time that object was touched in any way. Here is a potential Access Log Structure:

ObjectName nvarchar(255),
DateAccessed datetime,
AppName nvarchar(100),
ConnectionString nvarchar(255),
ConnectionID int,
ConnectionName nvarchar(100),
ExecuteStatement nvarchar(8000),
ExecuteID int,
ExecuteName nvarchar(100)

If you note some of the fields in my hypothetical access log you’ll see data that currently does not exist to be logged, such as ConnectionName and ExecuteID. A third “nice to have” feature would be the ability to give unique IDs and unique names in VB.NET and C# code where a connection is made and every place in code where a SQL statement is executed just like providing error numbers in error handlers.

With the first two features I could rename any SQL Server object, create an alias to that object using its old name, and then mark the alias to be logged. Then I could run my app, watch the log file, and see if I missed any references to the old names. If so I could easily use the logged data to track down the places I missed, especially if I had the third feature that allowed me to annotate ADO.NET calls with reference information. I could even deploy an app and let it run for a month or two while monitoring the access logs to make sure I didn’t miss anything.

I sure do wish SQL Server had those features. Don’t you?

Tags: ,

Unexpected Circumstances

Those of you who have paid any attention have noticed that it has been some time since my last post. Ahem. Saturday May 22nd around the time of my last post my left ankle started hurting. For no reason (except I rode my motorcycle that day, but I swear I didn’t do anything that hurt it.)

The next day I had trouble walking but I made my way to the airport destined for San Diego TechEd anyway.On Monday I had meetings all day, but by the end of the day I could barely walk. It took me literally an hour and a half to go from the meeting area by registration to my parked car (I just kept thinking: I don’t need a wheel chair!) Tuesday I couldn’t walk, and stayed in the hotel. The same was true for most of Wednesday, except I did make it out at the end of the day and to a CVC/CodeProject party.

Needless to say, TechEd was for me almost a complete waste! And no, I didn’t get any video footage, I just wasn’t up for it. :-(

Thursday morning I hobbled back to the airport for home, and then spent my Memorial day weekend housebound for lack of ability to move. Yeech. I guess I could have worked (or blogged) during that time, but the pain was just too annoying. Tuesday I was finally able to see my orthepedic, and learned I tore cartlidge in my ankle! Funny (sad?) thing is, the same happened to my knee two years ago, for no (discernable) reason! The only thing at the time I could figure was I had just turned 39. This time I guess it was I just turned 41. Jeesh.

So the last week after Memorial day was a blur as I tried to get caught up, and as I tried to prepare for going to .NET DevCon in Las Vegas, which I did Monday through Wednesday (I was only at the show on Tuesday, flying the other days.) NET DevCon was run parallel with a Lotus Notes and a WebSphere conference and wasn’t a well attended .NET show, but I had a long talk with John and Jeanie Banfield of Advisor after the show and there’s a chance based on their plans they can grow it into a really great show over time. (BTW, I’ve known John & Jeanie for over 15 years; back when I wrote for their now defunct Clipper Advisor magazine; and I think they are both really great people.)

Anyway, I’m finally back in town with no immediate travel plans meaning I can probably start blogging again, and my ankle is much better though I can tell it still is not completely well. The doc has me on meds, and I’ll see him in a month.