Saturday, November 25, 2017

Switching web hosting companies (and database and email hosting)

This week I had to switch the web and database hosting company for a client's web site.  The original host (Intermedia) was discontinuing their web hosting service.  The company they tried to transition our site to (Hostway) was very slow in transitioning our site and in their support responses, so we decided to go to another host, A2 Hosting.  They have a Plesk control panel, which I hadn't used before.  I like the idea of using a control panel that is used by more than one hosting company rather than a proprietary one, so that's just one of many reasons we chose A2.

The whole process of switching went well, partly because of the robustness of the Plesk control panel.  Since there were a lot of steps, I wanted to document them here for myself and others who might be switching hosts.  These steps are mostly not specific to any web host, either the original or the destination.  They're also mostly not specific to a platform, Window or Linux, but this happens to be a Windows environment.  I will add a few notes related to how to do these things on Plesk, but hopefully you can find an equivalent if your new host's control panel is different.

1) Open new hosting account.  They will ask what primary domain name you'll be using, but it doesn't have to be registered at the web hosting company.  After starting the account, you should get temporary web and ftp addresses.

2) Enforce a freeze on making web page updates on existing site.

3) Make a database backup of current site.  Its harder (in my case anyway) to enforce a freeze on the database, so this is just a temporary backup to get the new site running.  The final backup will be made later.  For MS SQL Server, this would be a .bak file

4) Download all files from original web server.  This can take a long time, depending how big your site is.

5) Upload all files to new web server

6) Restore the temporary backup to the new hosting environment.  In Plesk, they call this uploading a dump.  Uploading the .bak file retained all of the user logins for the database, BUT those logins still are not logins on the new server, so they didn't actually work for logging in.  So I had to...

7) Delete the logins that were created by the upload and recreate them, specifying the passwords.  (If you added the SQL logins before ever uploading your backup, then I guess you'd save the step of deleting the ones automatically added, but that wasn't a big deal, so I'd probably do it the same way again next time)

8) Change your database connection strings in your code to point to the new server.  Of course only upload those changes to your new server, not your original one that is still the live server at this point.

9) Change the email / SMTP server used to send email via ASP.Net.  More specifically, you will probably need to change the host used by the System.Net.Mail.SmtpClient object. A2 also requires credentials for any mailbox created in Plesk that is a true mailbox with Control Panel access, not just a forwarder.

10) Update folder permissions to give Write access on any folders where uploads are received.  In Plesk, use the File Manager.  When you see the folder listed on the right side, scroll all the way to the right to get to the button that allows you to Change Permissions.

11) Move any SSL certificates.  This involves
a) Generate a new certificate request at the new host
b) Go Rekey your certificate wherever you purchased it.
c) Download your new rekeyed certificate from where you purchased it
d) Upload the new certificate file to the new host
e) In Plesk, there is an additional step to go to your web site settings and specify that the SSL certificate to use for the site is the new one that you just uploaded

12) Create all mailboxes.  If you have email mailboxes on your original server, then you need to create the same ones on the new server with the same forwarding settings, if any.

13) Create all domain pointers.  On Plesk, these are called Domain Aliases.  You'll need one for each domain that will have its name servers pointed to the new host.  i.e. probably any domain that you displayed in the browser address bar for different parts of your site.

14) Test your new server using the temporary URL provided by the hosting company.  For Plesk, the temporary URL looked like http://111.222.333.444/plesk-site-preview/mydomain.org .  That extra "plesk-site-preview" in the path did mess some things up, and the hosting company actually recommended changing your hosts file instead for testing to point your domain to the IP address of your server.  Be sure to test different content types, such as ASP data-reading pages, ASP data-writing pages, ASP.Net data-reading, ASP.Net data-writing, video formats, etc.  You also could run into issues if the new server uses different versions of software than the old server.  For example, our new database server was MS SQL Server 2016 and the old one was MS SQL Server 2012. It didn't affect the site, but I had to upgrade my SQL Server Management Studio (SSMS) in order to connect to the newer version.

Now all the pieces are ready, so you just need to make the final switch

15) Turn off database updates.  For our site, this basically means take down the login form.

16) Get a final backup of the live database

17) Restore the final backup in place of your temporary one.  In Plesk, if you just Upload Dump again for the new file, it will overwrite the original database.  This is actually pretty scary and I'm surprised there weren't more warnings that you are about to wipe out the original database.  But in this case, it was just for testing anyway.

18) Repoint the name servers of all your domains to the new host.  Once you repoint name servers, they say it can take 24-48 hours to take effect, but its usually pretty much instant, at least for web traffic.  I found that email traffic did take longer to get redirected.  We also had many other domains that just had web forwarding set up to forward to our main domain, so those did not need any updating.

That's it.  A long list, but hopefully no individual step is too hard.  Unless you run into problems while testing.  Good luck!

Wednesday, October 14, 2015

GoDaddy Domain Forwarding

Every so often, I get asked to forward a domain purchased at GoDaddy to some other URL.  Its easy to do, but since I don't do it often, I forget exactly how to do it.  So I decided to document it here.

NOTE: This will forward both www.mydomain.com AND mydomain.com

1) Log in to GoDaddy and open up Domains

2) Find the domain name you want to forward and click the MANAGE button

3) When the "Domain Details" page appears, there is a Forwarding section down the page in the Settings tab.  It should say "Domain: Off" if it isn't forwarding.  Click the "Manage" link below that.

4) Then you will get a popup dialog box titled "Forwarding and Masking".  Click the green "Add Forwarding" button.  The dialog box will change to look like this:


5) Simply type/paste in the URL you want to forward to, without the http.  Be sure to change the dropdown to use the correct protocol you want, http or https. I keep everything else as-is: 301 (Permanent), Forward Only, and keep the check box checked.

6) Click Add on this screen, then Save when you get back to Forwarding and Masking

The changes can take a few minutes to take affect.  And www.mydomain.com my take affect some time before (or maybe after) mydomain.com, without www.  But within an hour or a lot less, both versions should be forwarding to the URL you specified.

Tuesday, June 2, 2015

Android Java Spinner for United States with postal abbreviations

For the Android version of Monster Cache, I wanted a spinner on my registration page that showed all of the 50 United States.  But when a user chose a state, I wanted to save the US postal abbreviation rather than the state name.  This seems like a common thing people would want to do, but I couldn't find any example, so I thought I would post mine.

First I created two arrays -- one with state names and one with state abbreviations.  Then I loaded the array of names into the spinner using an ArrayAdapter.


                stateCodes = new String[52];  // 50 states + DC + blank
                stateNames = new String[52];

                // set first item to blank
                int stateCount = 0;
                stateCodes[stateCount ] = "";
                stateNames[stateCount ++] = "";

            // now add all US states
            stateCodes[stateCount]= "AL";
            stateNames[stateCount++] = "Alabama";
            stateCodes[stateCount]= "AK";
            stateNames[stateCount++] = "Alaska";
            stateCodes[stateCount]= "AZ";
            stateNames[stateCount++] = "Arizona";
            stateCodes[stateCount]= "AR";
            stateNames[stateCount++] = "Arkansas";
            stateCodes[stateCount]= "CA";
            stateNames[stateCount++] = "California";
            stateCodes[stateCount]= "CO";
            stateNames[stateCount++] = "Colorado";
            stateCodes[stateCount]= "CT";
            stateNames[stateCount++] = "Connecticut";
            stateCodes[stateCount]= "DE";
            stateNames[stateCount++] = "Delaware";
            stateCodes[stateCount]= "FL";
            stateNames[stateCount++] = "Florida";
            stateCodes[stateCount]= "GA";
            stateNames[stateCount++] = "Georgia";
            stateCodes[stateCount]= "HI";
            stateNames[stateCount++] = "Hawaii";
            stateCodes[stateCount]= "ID";
            stateNames[stateCount++] = "Idaho";
            stateCodes[stateCount]= "IA";
            stateNames[stateCount++] = "Iowa";
            stateCodes[stateCount]= "IL";
            stateNames[stateCount++] = "Illinois";
            stateCodes[stateCount]= "IN";
            stateNames[stateCount++] = "Indiana";
            stateCodes[stateCount]= "KS";
            stateNames[stateCount++] = "Kansas";
            stateCodes[stateCount]= "KY";
            stateNames[stateCount++] = "Kentucky";
            stateCodes[stateCount]= "LA";
            stateNames[stateCount++] = "Louisiana";
            stateCodes[stateCount]= "ME";
            stateNames[stateCount++] = "Maine";
            stateCodes[stateCount]= "MD";
            stateNames[stateCount++] = "Maryland";
            stateCodes[stateCount]= "MA";
            stateNames[stateCount++] = "Massachusetts";
            stateCodes[stateCount]= "MI";
            stateNames[stateCount++] = "Michigan";
            stateCodes[stateCount]= "MN";
            stateNames[stateCount++] = "Minnesota";
            stateCodes[stateCount]= "MS";
            stateNames[stateCount++] = "Mississippi";
            stateCodes[stateCount]= "MO";
            stateNames[stateCount++] = "Missouri";
            stateCodes[stateCount]= "MT";
            stateNames[stateCount++] = "Montana";
            stateCodes[stateCount]= "NE";
            stateNames[stateCount++] = "Nebraska";
            stateCodes[stateCount]= "NV";
            stateNames[stateCount++] = "Nevada";
            stateCodes[stateCount]= "NH";
            stateNames[stateCount++] = "New Hampshire";
            stateCodes[stateCount]= "NJ";
            stateNames[stateCount++] = "New Jersey";
            stateCodes[stateCount]= "NM";
            stateNames[stateCount++] = "New Mexico";
            stateCodes[stateCount]= "NY";
            stateNames[stateCount++] = "New York";
            stateCodes[stateCount]= "NC";
            stateNames[stateCount++] = "North Carolina";
            stateCodes[stateCount]= "ND";
            stateNames[stateCount++] = "North Dakota";
            stateCodes[stateCount]= "OH";
            stateNames[stateCount++] = "Ohio";
            stateCodes[stateCount]= "OK";
            stateNames[stateCount++] = "Oklahoma";
            stateCodes[stateCount]= "OR";
            stateNames[stateCount++] = "Oregon";
            stateCodes[stateCount]= "PA";
            stateNames[stateCount++] = "Pennsylvania";
            stateCodes[stateCount]= "RI";
            stateNames[stateCount++] = "Rhode Island";
            stateCodes[stateCount]= "SC";
            stateNames[stateCount++] = "South Carolina";
            stateCodes[stateCount]= "SD";
            stateNames[stateCount++] = "South Dakota";
            stateCodes[stateCount]= "TN";
            stateNames[stateCount++] = "Tennessee";
            stateCodes[stateCount]= "TX";
            stateNames[stateCount++] = "Texas";
            stateCodes[stateCount]= "UT";
            stateNames[stateCount++] = "Utah";
            stateCodes[stateCount]= "VT";
            stateNames[stateCount++] = "Vermont";
            stateCodes[stateCount]= "VA";
            stateNames[stateCount++] = "Virginia";
            stateCodes[stateCount]= "WA";
            stateNames[stateCount++] = "Washington";
            stateCodes[stateCount]= "DC";
            stateNames[stateCount++] = "Washington DC";
            stateCodes[stateCount]= "WV";
            stateNames[stateCount++] = "West Virgina";
            stateCodes[stateCount]= "WI";
            stateNames[stateCount++] = "Wisconsin";
            stateCodes[stateCount]= "WY";
            stateNames[stateCount++] = "Wyoming";

            Spinner dropdown = (Spinner)findViewById(R.id.register_state);
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(m_thisActivity, android.R.layout.simple_spinner_item, stateNames);
            dropdown.setAdapter(adapter);


When I process the registration form, I just index the stateCodes array using the index selected in the Spinner, like this:

                Spinner states = (Spinner)findViewById(R.id.register_state);
                String selectedState = stateCodes[states.getSelectedItemPosition()];

Thursday, April 30, 2015

Step-by-step guide to purchase SSL certificate at GoDaddy, install at 3rd party host

My last blog post was a Step-by-step guide to transfer a domain name to GoDaddy.  Another process I have to do occasionally that involves quite a few steps is purchasing and installing an SSL certificate.  To me, these steps are easier to figure out than the domain transfer steps, but there are still enough of them that I wanted to write them down. I'm installing my SSL Certificate at DiscountASP.Net, but the process should be almost identical for installing at any other 3rd party web host.

One thing to note before purchasing the certificate...if you have an existing certificate, then you'll probably want to "Renew" it.  If you have an existing certificate that is expiring and you follow these steps, then you'll be completely replacing it with the new one.  If your existing one actually has two months before it expires, then you'll really be wiping out those two months since your new certificate will be good for 1 year (or however many you purchase) from the day you create it.  Existing certificates can be renewed, but these instructions are for a new one.

1) Log in and go to the SSL Certificates section of your "My Account" page.  First we need to buy a new SSL certificate credit.  Click "Buy Additional Plans"


2) The next screen that comes up is just a promotional splash screen.  Just click "Get Started" to get to the next page.

3) The next page lists the types of SSL certificates.  I've always just purchased Standard SSL.  It protects one full domain name, like www.mydomain.com.  It does not cover subdomains like mysub.mydomain.com.  I don't care about that.  I usually have a server side script on all my pages that require SSL  that checks if the page is using https, and if not, then it redirects them to the URL that does use https.  So at that time, I can also change the domain name to the specific domain name that I'm purchasing the certificate for.  Then select your term (one to three years) and click "Add to Cart"

4) Enter a promo code if you have one, otherwise just click the "Proceed to Checkout" button

5) Check your contact info and payment type, agree to terms and click "Place Order".  Hopefully you'll see a confirmation that says something like "Go Time".  If so, click on the SSL Certificates button, which takes you back to SSL Certificates section of My Account.  Now you should see a new entry that says "STANDARD SSL (1 YEAR) (ANNUAL)", or something similar for whatever type and term you purchased.


6) Click "Set Up".  Then there will be a pop-up that asks "Which order do you want to associate with this SSL Certificates account?".  You probably will have only one item in the drop down list, so just choose that one.  When the popup closes, you won't see the new certificate right away.  But if you just leave the page open a little while, it will refresh itself and then you'll see the new certificate listed as "NEW CERTIFICATE", as below

7) Click Manage.  That will take you to the Certificates management area.  There is a line for each of your certificates.  On the line for your "New certificate", there is a Set Up icon.  Click that.

8) Finally, we've reached the screen to enter the Certificate Signing Request (CSR).  This CSR must be generated by the server on which you plan to install he certificate.  That means its time to move to your 3rd party host.  In my case, this is DiscountASP.Net.  Keep this window open.

9) In a new window, log in to your web hosting account.  You should have some option for SSL Management on your hosting account.  When you find it, it should let you generate a CSR.  Here is how it looks at DiscountASP.Net


10) Generate the CSR. It will ask you to supply the fields shown above: Common Name, Organization Name, Organization Unit, City, State, Country.  The Common Name is the specific domain for which you want the certificate to work, so be sure to choose and enter that carefully.

NOTE: Your web hosting company may charge you an additional fee in order to install a certificate.  This is because they may need to give you a static IP address if you don't already have one.  The SSL Add-on at DiscountASP.Net is $10/month.

11) Your host will generate a huge block of text that starts with "-----BEGIN NEW CERTIFICATE REQUEST-----" and ends with "-----END NEW CERTIFICATE REQUEST-----".  Copy *ALL* of that, including those BEGIN and END lines, and paste it in the CSR form back at GoDaddy.  Agree to the terms and then click "Request Certificate"

12) Now you just have to wait a little while.  If your domain is registered at GoDaddy, then they know you own it, and they will skip you through the Domain Ownership verification.  Otherwise, you may have to put a file on your server so that GoDaddy can verify that you own the domain


13) After waiting several minutes, your certificate will be issued and you should see something like below.  Click Download.  (If you have to complete  verification steps GoDaddy asks you to do, then you may not get to the Download option on this screen, but you can find it back in the SSL Certificates section of My Account.

14) Choose the server type on which you are installing -- IIS, Apache, etc. -- and click "Download Zip file".  Save it wherever you want.  The .zip file has the files that you need that are relevant to the server type you choose.  In the case of IIS, the file we'll be after is the .crt file in the zip file (that may be true for all server types)

15) Extract the contents of the zip file and open the .crt file in a text editor, like Notepad.  This file contains another huge block of text that starts with "-----BEGIN CERTIFICATE-----" and ends with "-----END CERTIFICATE-----"

16) Copy *ALL* the text from the file, including the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----, and go back to the SSL management at your web host.  There should be a text box where you can paste in this copied text.  At DiscountASP.Net its on the same page as the CSR, and it says "Install your SSL Certificate".  Paste your certificate text into that text box and click "Install Certificate" (Of course I got logged out while I was over at GoDaddy, so you may want to make sure your session is still active)

That's it! If the installation is successful, then your new certificate should be active right away.

Saturday, March 28, 2015

Step-by-step guide to transfer a domain name to GoDaddy

I've transferred domain names several times, usually (maybe always) to GoDaddy. Many people don't like GoDaddy for good reasons.  I already have many domains registered there for myself and clients, and I have always found that they have really good customer service, and their prices are good, so I'm not ready to switch yet.  Note that I am speaking strictly about having good experiences with their domain registration service, I definitely do not recommend using them as a web host.

Anyway, I don't do domain transfers often, and every time I do a transfer it seems like something goes wrong.  Or nothing goes wrong, but the process is just so confusing that it seems like something is not working, when really its just taking a while, or I misunderstood something.  So finally I am going to document the process so that I can refresh my memory for future transfers.  Here are the steps that I follow to do a transfer to GoDaddy.

1) Turn off "Registrar Lock" or "Transfer Lock" at your original registrar.

2) Turn off "Privacy Protection" at your original registrar.  If you have some kind of Privacy Protection, then the administrative contact email will not be your own email, but an address at the registrar company or some other company they contract with. Theoretically, whatever address that is *should* forward to you, but it may take a lot longer or it may not work at all.  So its best to just turn off the protection.

3) Log in to your GoDaddy account.

4) Purchase the transfer on GoDaddy.  In their main menu, its under Domains, and then choose "Transfer Domains".  You'll be asked to enter the name of the domain that you want to transfer, and then you will proceed through check out. They have good prices on transfers, like $9.99/year plus a free year, so I recommend buying a lot of years now.  I also usually buy Privacy Protection.



5) Once you make the purchase, TWO emails should be sent to the administrative contact for the domain.  The first comes from GoDaddy and should contain two keys:
  • Transaction ID
  • Security Code
The second email comes from your original registrar and should contain one key:
  • Authorization Code
In the current transfer I'm doing, we did NOT turn off the Privacy Protection ahead of time and it took over two hours before we received both emails.  Hopefully you'll get them much faster if you had already turned off Privacy Protection.

5) Go back to GoDaddy and again from their Domains menu, choose "Manage My Domains"

6) Now you'll be in the domain management area.  From there, go to the Domains menu and choose "Transfers"

7) Now you should see your Pending Transfers with your domain name listed in the table.  The Status column should say "Authorization code needed".  Click on that message.  You will see the "Authorize Transfer" dialog box.


8) Click "Add Transfer Codes"

9) Now you will be asked for the Transaction ID and Security Code from one of the emails.  Enter those.

10) After adding those, you will be back at the "Authorize Transfer" box with your Transfer Code listed in the table.  Click Next.

11) Now enter your Authorization Code that came in the other email, check the box that says "I authorize the transfer..." and click FINISH!

That's it!  You'll see a message that says the transfer has been initiated, but could take 15 minutes to take effect.  If you refresh your Pending Transfers table, the Status should now say "Processing Transfer".  Clicking on that message gives a disturbing warning.  "We're waiting for approval from the sending registrar, which can take up to 7 days."  I will try to update later on how long it really took, but it does depend on your original registrar.  Some take longer than others.


Sunday, April 6, 2014

Simulated touch box in Excel for touch screen

I have a client that wants to build an Excel spreadsheet for use on a touch screen.  They would like to have about 15 columns of check boxes for about 600 rows. Reading articles about the check box controls for Excel, I was pretty sure I did not want to use them, for a few reasons:
  1. They're hard to create and associate with the cell if you need hundreds. If you copy and paste them, the underlying cell association isn't copied, so you'd have to manually click and set the cell for each one.  (Perhaps it could be programmed with VBA)
  2. Once you do get them all created and associated, deleting a row of the spread sheet doesn't delete the check box so it throws off all of the associations
  3. They are very small and can be hard to use and hard to see when printed
Instead, I started looking for a simulated solution.  What I really wanted was to handle the Click event for a cell and just set the text to X if it was empty, or empty if it was X.  Seemed simple enough.  First problem was that Excel does not provide a handler for the Click event.  The closest are BeforeDoubleClick and BeforeRightClick.  I wasn't sure how a right click would happen with a touch screen, but a double click sounded good enough.  So that's what I tried first.  I wrote my code and put it in the BeforeDoubleClick handler for the worksheet, and it worked great....for the mouse.

That brings up the second problem.  Touch events aren't handled the same as an actual mouse click.  Double tapping the screen did not create the same behavior as a double click, and it did not fire the BeforeDoubleClick event.  I needed to start looking at the other possible events to handle.  Eventually I tried SelectionChanged.  To select a single cell, you just click it once, or tap it once.  That's just what I needed.  I moved my code to that event and it worked great...for the mouse and touching!  I had to make one small change to ignore cases where multiple cells were selected, but that was trivial. The real catch is that you can't select a selected cell. So if you a click a cell to change its value, then you have to click somewhere else first before you can click/select that cell again.  We thought that was an acceptable catch since it would only be needed if the user accidentally clicked a wrong cell and needed to uncheck it.

Here's the final code for the event handler. The big If statement ensures that it isn't a multiple cell selection and ensures that its one of the cells that we want to use as a check box:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    If Target.Cells.Count = 1 And Target.Row >= 20 And Target.Column >= 27 And Target.Column <= 40 Then
        If Target.Value = "" Then
            Target.Value = "X"
        Else
            Target.Value = ""
        End If
    End If
End Sub

Saturday, February 22, 2014

JavaScript include not working

The other day I was trying to include a JavaScript file in my HTML page, and I could not get it to work. I read several  posts about how to do it.  I was sure the path and syntax in the tag were right.  I had:

<script type="text/javascript" src="../scripts/scriptFile.js" />


 The page would still not recognize the functions in the file.  Well, turns out I didn't have the syntax exactly right.  Above, I was using the shorthand syntax for closing an empty tag.  I figured that since there was no content for the script tag itself, I could close it the short way.  Apparently, it is not allowed to use the short notation for closing the script tag.  After I changed to the code below, everything worked great!

<script type="text/javascript" src="../scripts/scriptFile.js"></script>

Once I found the solution (probably in a comment on Stack Overflow, I don't remember), then I found a whole article on the subject at Stack Overflow.