Wednesday, October 12, 2011

Outdoor office


I tried a fun experiment last week: making an outdoor office and working outside.  I'm sure many others like me hate to be indoors all day when the weather is perfect outside.  I'd tried taking my laptop outside to work before, but ran into some issues.  With a little bit of effort though, I was able to make it work quite well and was able to spend most of my time out there for a week.  The advantages to working outside are pretty clear if you love the outdoors: fresh air, nice scenery, less stress, etc.  Here are some of the issues that I found needed some effort to make working outdoors work:

1) Weather.  Again, this is great when the weather is perfect.  Even when it cooled down a bit, I was fine wearing some fleece.  But don't leave your computer out there if it looks like rain!

2) Furniture.  When I tried this unsuccessfully in the past, I just took my laptop to our outdoor table and chairs. The ergonomics were bad, it was on a patio that was too hot... it just didn't work.  What did work is I had a spare simple rolling desk made of light weight metal and glass.  I rolled it out into the grass and the ergonomics were much better.  Sometimes I'd bring a keyboard and mouse to make it even better, sometimes I wouldn't.  Mine was light and small enough that I brought it in each night.  Since it was metal and glass, I think I could've kept it outside even.

3) Power and Wireless. So if you take special furniture outside, you'll want to put it somewhere where you get a good wireless signal.  Hopefully your router isn't too far from your back yard.  You may also want to be close to a power outlet if you want to stay out longer periods of time.  I just brought my laptop inside at lunch time to recharge.

4) Glare.  This is another factor in picking your location.  You'll probably want to be in the shade, if possible.  Since shade moves, I had to adjust my position a bit later in the day.

5) Bugs.  In Kansas City, summer is often too hot to be outside for a long time with no A/C, and conveniently that's when the mosquitoes are out anyway.  When the weather is nicer in spring and fall, there are far less mosquitoes, but still a few.  I used a bit of bug spray on my hands.

6) Wind. If you're totally paperless, then wind isn't a big issue, other than the occasional leaf particle falling in your keyboard.  If you need to use some papers, then you may need a paperweight some days.

That's really about it.  The only other issue is that if you enjoy it too much, then you may be a bit distracted and not get as much work done. But there are plenty of distractions inside as well, so I didn't find that to be too much of an issue.

If you try it, let me know how it went!

Wednesday, September 14, 2011

AjaxToolkit:CalendarExtender display problem

I've been using the AjaxToolkit:CalendarExtender for quite a while. Its always worked really well for me... until today.  I added it to a site and the header was not displaying properly.  The month name and the next arrow in the header were not there, only the previous arrow displayed in the calendar header.

As I saw in many posts, the cause is a CSS conflict.  Sure enough, in the designer's CSS, he had a style defined for all div tags that was messing up the calendar header.  I think it was a combination of a position:relative and a display:block that caused the problem.  I tried everything I could think of to fix it without having to modify the designer's CSS file.  I gave the calendar its own class and tried to override the div settings.  I tried defining styles for .ajax__calendar_header.  Couldn't get anything to work for two hours.  I never found a solution for the CalendarExtender, but I did find an alternative.

After doing a search for "javascript calendar date picker", I found the Tigra Calendar.  There is a live demo on the page linked to there.  It looks better than the CalendarExtender and it was even easier to implement.  No AjaxControlToolkit.dll is needed, just a .js file and a .css file.  Their examples use an HTML input control as the target for the calendar, but I found that it worked just as well with an asp:TextBox control.  And its free!  They do have some nice features in the paid version, and that's only $29, so I could definitely see using the paid version on some project in the future.  Particularly for the ability to restrict to certain dates.  Very glad to have found this calendar.

Monday, September 5, 2011

CustomValidator doesn't run / execute / fire

This problem drove me nuts for a while the other day.  I had a CustomValidator on my page that had some client validation code and it was not running.  the page just kept validating successfully even though the validation should have failed.  The issue was that I had set the ControlToValidate attribute of the validator to one of the form fields on my page, and that field was blank, so the validator thought that it didn't need to run since no value was provided.  The field was only required if another field had a certain value, that was the point of the validator.  So I couldn't add a RequiredFieldValidator to the control too.

The solution turned out to be just removing the ControlToValidate attribute.  That attribute is not required for the CustomValidator.  Without that attribute set, the validator runs any time the form is submitted.  And you can still display a potential error message next to whichever control you like just by placing the CustomValidator next to that control on the page.

Monday, August 1, 2011

Disable Google Docs PDF viewer

This has been driving me crazy for many months.  Somehow both my main browsers, Chrome and IE, got configured to open all PDF files in the Google Docs PDF Viewer.  That would be fine if it worked all the time, but often it would give an error saying "Sorry, we are unable to generate a view of the document at this time.".  Always I would see this when trying to open my Groupons from Groupon.com, which are stored as PDFs.  I looked at all my plug-ins and couldn't find anything about Google Docs.  I tried turning off and on different PDF Viewer plug-ins.

CHROME: Finally, I found this solution in the Google Forums.  Essentially, the Google Doc PDF viewer is *not* a plug-in, but an "extension".  So if you browse to chrome://extensions/ in Chrome, then you will see it there and you can disable it.  Probably need to refresh the page you're on to update the links too, or close browser and re-open

IE: Thankfully, Internet Explorer 9 just groups plug-ins and extensions as "add-ons".  So to disable the viewer in IE, go to the Settings Gear > Manage Add-ons.  Still I had a difficult time from there just because I was expecting that the Add-On to be made by Google.  But when I disabled the "Adobe PDF Link Helper", that seemed to do the trick after I refreshed the page.

Screen shot of Internet Explorer 9 Add-On Manager:

Friday, July 15, 2011

Everest Advanced Edition 5.0 API versus eStorefront

My client that uses Everest Advanced Edition business software built a web front end for online orders using the eStorefront provided by Everest.  I wasn't involved in that part, but as I understand it, Everest generates all the pages in the eStorefront for you based on some parameters you can set within Everest.  There is some possibility of customization after the eStorefront pages are generated, but there are a couple problems with that:


A) If you upgrade Everest, then apparently the existing eStorefront ends up not working.  That means you have to regenerate all the eStorefront pages, so all your customizations get wiped out
B) The code generated for the eStorefront is really quite ugly and is in classic ASP.  There is no separation of the interface from the logic so with all that ugly code mixed in there, customization is not easy


So the client asked me to build a new store front using the Everest 5.0 API and ASP.Net.  I've built a project with the Everest API already, so I know most of its abilities.  I noticed pretty quickly that the eStorefront pages could do some things that didn't seem possible with the API.  So I looked a little more closely at the code in the eStorefront pages.


As it turns out, the auto-generated eStorefront uses a completely different set of objects and calls than the 5.0 API.  I don't know if the eStorefront is using an old version of the API or if its an undocumented API reserved just for their eStorefront.  There is plenty of documentation about the new 5.0 API, but I could find nothing about these eStorefront objects.  It doesn't help that on the Everest support site, neither their Customer Forums or the Knowledge Base are functional, both produce errors (at least for our support account).  I saw one reference to the "shopping cart" objects in the list of COM objects installed with Everest, so I think that's what they might be called.  I considered trying to re-use some of that code to get some of those more powerful features.  But even if I could find documentation on those other objects and decided to use them, I'm not sure it would be a good idea to use them anyway since they seem to have problems when Everest is upgraded.


So far I already know of a couple small consequences of using the new API instead of the eStorefront objects:

1) In the API, you can not update a customer's billing address once they have been invoiced. Once a customer is invoiced for anything, then you can only update some things in their profile, like phone number and credit cards, but some things like billing address become locked.  This is consistent with the interface of the Everest desktop application.  But there is a way around it in Everest, and there seems to be a way around it with the eStorefront objects too.

2)  The eStorefront claims that it can email you your password if you forget it.  I say "claims" because this feature wasn't working in our eStorefront.  Regardless, the API does not allow this because there is no way to retrieve a person's password for the sake of emailing it to them.  Again, this is consistent with using the Everest application, as you can't see a person's password in their profile.  The API allows a check to see if a provided password is valid, so that's how a login can be checked.  If users forget their password, they can answer their secret question correctly so that they can reset their password to something else.  The secret question and secret answer are retrievable from the customer profile using the API.

Overall, it seems like the API can handle all the important features provided to a normal user in the application for setting up a new customer and handling orders.  So it should have everything we need for the new web interface.  It will be very nice having a custom built web interface that we can customize how we want and not have to worry about it breaking when Everest is upgraded.

Monday, May 23, 2011

Business Insurance

On a non-technical note, one of the things I had to do recently was to get business insurance for my company.  That turned out to be a much bigger pain than I thought it would be.

What happened is that one of my clients decided that they were going to pay all of their contractors through a third party billing agency called MBO Partners.  But MBO Partners had a requirement that in order to be paid through them as a contractor I had to have $1,000,000 of General Liability insurance and workers' compensation insurance.

I got one referral to a business insurance agent from a friend.  He had to collect a whole bunch of information from me over the phone in order to get a quote.  He had to call back to get more information he forgot.  After a couple weeks, he got me a quote from American Family that was about $1060/year.  But that wasn't even official, so I waited longer for him to send an official quote.  This was taking so long that I contacted another agent I just found using Google.  He quoted me a much lower number, but the application process was just as slow and he was slow to return my calls when I wondered what was taking so long.  I contacted yet another agency and they never even called back.  This all dragged on for over one month.

Finally, on my 4th try, I found the site I needed.  It's called NetQuote.  Similar to car insurance sites (and NetQuote also does car insurance quotes), you just fill out one form on their site and they send it to 5-10 business insurance agencies.  I got 3 or more return calls within minutes!  One sent me a great email with comparisons of two plans.  But I ended up going with the first agency that called me because they were able to get me an official quote within an hour, rather than the weeks it took for the first agents I contacted!  And their price for the GL and Workers Comp combined was $715/year.

By the way, I also looked into Professional Insurance, i.e. "Errors and Ommisions", which gives you coverage int he case that a software mistake costs your client money.  The application is *way* longer for that and the only quote I got so far for that was about $1000/year.

Wednesday, May 11, 2011

Amazon Cloud Player


There's been a lot of expectation that Apple's iTunes will eventually run "in the cloud", meaning that you would stream songs that you purchase from an iTunes web site rather than download them to your computer and iPod. Google is also supposed to be working on something similar.  But Amazon beat them both to it and has recently released their Cloud Drive and Cloud Player.  I've been trying it out quite a bit over the last couple weeks and its great.

Any MP3 song or album that you purchase from Amazon can now be stored on their server, the Cloud Drive, so that you can stream it to any device that has a Cloud Player.  Mainly, this would be your computer or your phone.  All music you purchase from them can be stored on the Cloud Drive indefinitely for free.  Also, up to 5GB of other music that you did not purchase from them can be uploaded and stored for free.  If you purchase even one album from them, they will upgrade you to 20 GB of free storage.  It isn't clear to me whether the free 20GB upgrade is for just one year or indefinitely, but I think its just one year.  Otherwise, the 20GB storage plan is $20/year (not per month).

The Cloud Player still lacks some nice features that iTunes has.  You can't edit song information once you've upload a song.  And you can't rate songs, which I found to be a nice feature in iTunes to quickly highlight the best stuff in a big collection.  But the fact that I could immediately listen on my phone to the music that I uploaded via my computer was a big enough plus that I can live without those things.

I imagine that if you're a heavy Apple user, then you'll probably want to wait for the cloud version of iTunes.  But if you use your Amazon account as much as you iTunes account and/or if you have an Android phone rather than an iPhone, then you'll probably want to check out the Cloud Drive and Cloud Player.

Thursday, March 24, 2011

Corning concept video

Friends of mine sent me links to some technology concept videos today.  I liked this one from Corning:

I also watched one from Microsoft.  They're fairly similar.

I like the idea that your phone becomes your main computer and everything else is just an input/output device that gives you more space to work instead of interacting with the phone itself.  Of course, the more we rely on our phones as our main computer, the worse it is when you lose your phone or spill water on it. But then again, if Internet enabled phones become sufficiently cheap and all of your data is stored in "the cloud", then maybe losing your phone isn't even a real big deal.

The other bad thing it reminds me of though is how we're adding electricity dependency to every single device that we use.  For one thing, that will dramatically increase our energy consumption at a time in the world when we should be working to decrease energy usage.  And second, it increases our reliance on electricity to even use simple devices that shouldn't necessarily need power.  For example, a normal toilet flushes without electricity, but some modern business toilets don't flush if they lose power.  Old phones worked without electricity, but its hard to find one these days that will. If my house has photo-voltaic windows and the house loses power when they are in dark mode, is my house forced into darkness even in the day?? Losing power isn't all that common, I know, but it certainly happens in the winter in places that get big snow and ice storms, and in cases of large disasters, like earthquakes.

Overall though, it will be exciting to see if even a few of these devices in these videos become reality.

Wednesday, March 23, 2011

Screen sharing / web conferencing software

I've been looking into different options for screen sharing lately.  Basically, when I have a phone meeting with one or more people, I would like to be able to share my desktop so that they can see what I'm doing.  There are lots of tools out there to do this.  Many are geared towards allowing remote control of a computer.  I wasn't looking for that, just displaying my screen to others.  And I was hoping for minimal software install required by the clients.

The two free tools that I looked at were Skype and CrossLoop.  I tried the screen sharing on Skype with a friend and it worked on and off.  That may have been an Internet connection issue, but another friend mentioned that he had problems with it before too.  Regardless, the free version of Skype only allows sharing to one person.  When we got a third person on the call, the screen sharing turned off.  And I'm pretty sure CrossLoop is only a one-to-one sharing solution too.  So neither of these solutions is what I wanted.

The two most well-known solutions for screen sharing to multiple participants are WebEx and GoToMeeting.  I've been in several WebEx conferences that worked well.  Each of these solutions costs about $50/month though, which is more than I was hoping to spend.

The in-between solutions I found were Zoho and Yuuguu.  Zoho is only $12/month (or $115 for a year), Yuuguu is $19/month (or $79 for a year - HUGE discount).  The big difference that I found between them  is that Zoho has built in audio conferencing support too.  So they provide a number that your participants can call into for audio, and a URL that they can use to view the presentation.  Yuuguu did not provide a conference call number.  So I went with Zoho.  Clients are given the option to view the presentation with Flash, ActiveX control, or a Java plug-in.  It's nice for them to have the options.  For me, the presenter, the control installation could be better.  When I try to start a meeting through the browser, the plug-in installation always fails.  But they have an alternate link to download an executable that installs on your desktop.  When I start a meeting using the desktop app, instead of through the browser, then it works fine.  I've used it a couple times now and didn't hear any complaints from the viewers.  So even though the process to start a meeting is not optimal from my end, as long as my participating clients are happy, I'm happy.

UPDATE April 17, 2012
I've been using join.me as my screen sharing choice for many months now and it has been great!  It has all of the following for free!:

  • up to 250 participants
  • free domestic conference call
  • super easy for people to join from join.me home page
  • ability for host to transfer control of screen to someone else
I've found that last feature very useful in helping people who are having issues with their desktop computer.  Just have them install join.me and start a conference.  Then you can join and request control of their computer.

UPDATE October 2017
For the last year or so, the new service we've been using is Zoom.  They do audio and video and the quality is great!  The layout is very smart too, showing everyone's webcams in small windows and highlighting the speaker in the large window.  Or you can easily share your screen to the big window.  Free plan allows unlimited time meetings with a single person, and limited time with multiple participants.  Paid plans start at just $14.99 / month

Friday, March 4, 2011

Microsoft Access Combo Boxes

This week I was working on a project in Microsoft Access where I have one combo box whose values are dependent on the choice in the other combo box.  Microsoft calls this synchronizing the combo boxes in their article "How to synchronize two combo boxes on a form".  Their article is good, but even so I had some problems with it so I thought I'd mention them here.

Even though I thought I'd followed their instructions, the first thing that happened is that I would select a value in the parent combo box but the new values would not appear in the child/dependent combo box.  I could see in the debugger that AfterUpdate was getting called and the RowSource of the child combo box was getting set to the right query, but still the combo box ended up empty.  The issue was that I hadn't set the RowSourceType property of the child combo box.  The RowSourceType property of the child combo box must be set to Table/Query for this to work.  I think its easy to miss that.  Since the RowSource is being set dynamically, I wasn't paying as much attention to the Properties window and missed setting the RowSourceType to Table/Query.

The other issue that I had was not really related to the synchronization, but just to combo boxes in general.  I learned that its very important to set the following properties correctly based on the query that you're using for your RowSource:

  • ColumnCount - needs to match the number of fields that you are SELECTing in your RowSource query
  • BoundColumn - whichever of these columns that you want to be the actual value of the combo box that will be stored in a database field is the bound column.  Note that this is 1-based, not 0-based
  • ColumnWidths - this controls the display of the columns in the combo box.  You list the width you want for each column in inches, separated by semi-colons.  If your bound column is an AutoNumber key and you don't want it displayed, then list it as 0"
Microsoft set all these for the parent combo box in their example, but for some reason didn't mention them for the child combo box.  You'll probably have two columns in your query, with the first one being the numeric key, and so BoundColumn is 1 and ColumnWidths is 0";1".  Or you may just be storing strings, in which case you may just select the string as the only column, also make it the bound column, and just make the ColumnWidth as 1" (or whatever size).


Monday, February 7, 2011

CustomValidator - returns false but form submits anyway

I think this has bitten me a couple of times now.  If you implement a CustomValidator with server side validation in ASP.Net, then you set args.IsValid to true if the validation passes or to false if the validation fails.  But even if you return false, the form continues the submit process anyway!

The trick is that when you set args.IsValid, that sets a flag in the Page class called Page.IsValid, and you still need to check that Page.IsValid flag somewhere in your form processing.  For example, I check it in my button click handler and just return from the method if Page.IsValid is false.  The error message that you set for your CustomValidator will then be displayed.

I should mention that the post that got me part of the way to figuring this out was on Egghead Cafe, but it lacked example code and the actual property name.  Here is some example code of using this process to limit the file size on an asp:FileUpload control using a CustomValidator with server side validation.

.aspx file
...

<asp:FileUpload runat="server" ID="uplResume" />
<asp:CustomValidator ID="FileSizeValidator" runat="server" ControlToValidate="uplResume"
ErrorMessage="File size should not be greater than 2 MB." OnServerValidate="FileSizeValidator_ServerValidate"></asp:CustomValidator>
...

.aspx.cs file
...

    protected void FileSizeValidator_ServerValidate(object source, ServerValidateEventArgs args)
    {
        int fileSize = uplResume.FileBytes.Length;
        if (uplResume.FileBytes.Length > 2 * MEGABYTES)
        {
            args.IsValid = false;
        }
        else
        {
            args.IsValid = true;
        }
    }

    protected void btnSubmit_Click(object sender, EventArgs e)
    {
        if (!Page.IsValid)
        {
            return;
        }
        // do processing for valid form here
    }

Thursday, January 27, 2011

VB arrays vs. C# arrays in ASP.Net

As many long-time web developers may know, Visual Basic and VB Script used to have 1-based arrays for many years while just about every other language I used -- C, C++, JScript, JavaScript -- had 0-based arrays.  I didn't particularly have any strong preference for one over the other, but it was tricky to adjust your mind when switching from one to the other.

Then when .Net was released, Visual Basic changed to using 0-based arrays.  And with ASP.Net, Microsoft switched from using VBScript to using Visual Basic.  So now the two main languages used by ASP.Net, C# and Visual Basic, both use 0-based arrays.  That's good news in the long run, but I'm sure it caused a lot of developers some big migration headaches.  But there is still one annoying difference in the arrays of these languages that caused me some problems in a current ASP.Net application that is using VB.

The meaning of the boundary specified when you declare a fixed size array in C# versus VB is different.  When you declare a fixed size C# array with a boundary of 10, such as:

int[] myArray= new int[10];

then the array has 10 elements, which is what I would expect.  Since the array is 0-based, the elements are indexed as myArray[0] through myArray[9]

When you declare a fixed size VB array with a boundary of 10, such as

Dim myArray(10) as Integer

then 10 is the index of the last element.  So the array actually has 11 elements in it, indexed as myArray(0) through myArray(10)!  To me, this is very misleading.  So I thought I was filling my array up, but really I had a blank element at the 10th index that was causing problems.

For a more extensive comparison of VB and C# arrays using code examples, see the array section of this VB.NET and C# comparison.