Source Control, MVC3 and architecture

I’ve been poking around a bit with MVC3. It’s pretty cool, I like the controller, view and model framework, Razor looks nice, but I don’t like the overreliance on javascript and ajax etc for the client side work – but hey, that’s the web these days. I also hate, hate the dynamic objects malarky! Isn’t this meant to be a type safe language? I mean honestly. If you can’t catch the error at compile time then things will start to break. Yes you can always write tests… but tests aren’t there to check that your code compiles! They are there to check that your code does what you think it should!

Anyway, I’ve also been looking at source control systems! Should I use TFS, VSS (ha), SVN, Git or Mercurial? I’ve had a close look at Git, and it looks really cool, but I can’t find a nice and easy way for it to integrate with Active Directory. The visual studio support seems to be ok… but it’s all a bit clunky and unsupported. At the moment the one with the best security and active directory integration looks like SVN – Visual SVN just looks great. It also happens to be the one that I know really well…. so it’ll probably be SVN again, which is a bit of a shame, Git looks really cool, I love the way it handles renaming of files! It’s magic!

I also found a great microsoft press book on software architecture… but wow it’s >500 pages! Should be a great read…. just gotta print it out :)

Posted in technical | Leave a comment

VirtualBox setup for Drupal Development

I’m developing a new site using Drupal, and the production environment will be Linux. So I could develop the whole site on my windows machine… but I don’t like doing that. There’s always weird environment problems and it’s just nicer developing in the same environment that the production box will be on. Plus Drupal and PHP run so much faster on Linux!

Using Oracle’s VirtualBox you can have a local Linux server running on your windows machine! From here you can setup apache, mysql and drupal, share out your working folders and then do your development on your windows computer. It’s the best of both worlds.

My instructions below will show you how to run Apache on a different port (8088) so that your IIS will continue to work on port 80. The VM setup is also extremely unsecure so make sure that your machine is behind a very secured firewall!

So how do you do this?

Setup VirtualBox

First off, download your linux install. I used CentOS, and I downloaded the 64bit DVD iso’s. The file is about 4 gig… so bittorrent is the best option!

Next, download and install sun’s virtualbox:

http://www.virtualbox.org

When installing CentOS, I created new user account, username: lachlan, password: lachlan

To make troubleshooting easier, I completely turned off the firewall. Go to System, Admin, Security Level Configuration -> Firewall options, set the firewall to “Disabled”, inside the SELinux tab Management, set SELinux setting to “Disabled”

Setup Hostname

Give the box a hostname by editing:

/etc/sysconfig/network

and change it to:

HOSTNAME=LachDrupal

also edit:

/etc/hosts

and set it to:

127.0.0.1 localhost.localdomain localhost lachdrupal
::1 localhost6.localdomain6 localhost6
192.168.56.10 LachDrupal

Network Configuration

Shut down VM. Inside VirtualBox add a new network interface by going to box settings, Network, Adapter 2, setting it to “Host only Adapter”. Startup the machine.

Grab IP Address of host VM by typing:

/sbin/ifconfig

on my machine it is 192.168.56.10

Edit the network file for this network interface and set it to static IP instead of DHCP:

/etc/sysconfig/network-scripts/ifcfg-1

and it should contain:

DEVICE=eth1
BOOTPROTO=static
IPADDR=192.168.56.10
NETMASK=255.255.255.0

On my machine SSH was already running by default (if not, do this:)

yum -y install openssh-server openssh-clients
/sbin/service sshd start

I could then SSH to my virtualbox instance on port 192.168.56.10!!

Setup Apache

The directories that you need to look at for configuring apache are:

/etc/httpd/conf <-- config files
/var/www/html <-- base directory (similar to /inetpub/wwwroot)
/var/log/httpd <-- log file directory

open /etc/httpd/conf/httpd.conf and change/add the following lines:

Listen 192.168.56.10:8088
ServerName LachDrupal:8088
DocumentRoot "/var/www/html/drupal-7.8"

and right down the bottom put:

NameVirtualHost *:8088
<VirtualHost *:8088>
ServerAdmin me@example.com
DocumentRoot /var/www/html/drupal-7.8
ErrorLog /var/log/httpd/errorlog.log
</VirtualHost>

find the location of the 'Directory "/www/var/html"' line and change it to:

<Directory "/var/www/html/drupal-7.8" >
Options Indexes FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
</Directory>

(This is for enabling clean URLs in Drupal).

start up apache:

/sbin/service httpd restart

The URL should now work:

http://192.168.56.10:8088

Now that http://192.168.56.10:8088 works, you'll notice that no-one else on your network can go to http://192.168.56.10:8088, as it's a virtual port and IP only accessable from your machine. So what you need to do is to forward a port on your _external_ IP to the internal one.

So, shut down the VM.

Go back to adapter 1, click on "Port Forwarding". Enter a new rule, set the Host IP to be your machine's IP address (in my case 192.168.2.154) and set it to be port 8090. Set the Guest IP to be 192.168.56.10 and set the Guest Port to be 8088.

Startup the VM, startup apache, and then visit

http://192.168.2.154:8090

and it'll be accessable to all! You should also be able to use your hostname instead of your IP address.

Setting Up Mysql

First step, install mysql:

yum install mysql-server

Start up mysql:

/sbin/service mysqld start

Set the root password for mysql:

/usr/bin/mysqladmin -u root password 'lachlan'

Connected to mysql:
./mysql -p

(enter password 'lachlan')

create a database:

create database Drupal7;

then create an account under the name 'lachlan' :

CREATE USER 'lachlan'@'localhost' IDENTIFIED BY 'lachlan';
GRANT ALL PRIVILEGES ON *.* TO 'lachlan'@'localhost'

Download drupal 7:

cd /var/www/html
wget http://ftp.drupal.org/files/projects/drupal-7.8.tar.gz
tar xzvf drupal-7.8.tar.gz
chown -R apache:apache drupal-7.8

Now apparently the version of php that comes with CentOS is too old - by default it's 5.1 - so it needs to be updated to 5.2. At the moment 5.2 isn't certified for CentOS so you need to tell CentOS about the "testing" respository. Following these instructions: [http://wiki.centos.org/HowTos/PHP_5.1_To_5.2]

1. Create a file named:

/etc/yum.repos.d/CentOS-Testing.repo

2. Put this stuff in it:

# CentOS-Testing:
# !!!! CAUTION !!!!
# This repository is a proving grounds for packages on their way to CentOSPlus and CentOS Extras.
# They may or may not replace core CentOS packages, and are not guaranteed to function properly.
# These packages build and install, but are waiting for feedback from testers as to
# functionality and stability. Packages in this repository will come and go during the
# development period, so it should not be left enabled or used on production systems without due
# consideration.
[c5-testing]
name=CentOS-5 Testing
baseurl=http://dev.centos.org/centos/$releasever/testing/$basearch/
enabled=1
gpgcheck=1
gpgkey=http://dev.centos.org/centos/RPM-GPG-KEY-CentOS-testing
includepkgs=php*

3. run

./yum php update

voila.

Drupal PHP Dependencies

You will also need to install GD, DOM and PDO.

To view which php packages you can install you can do:

./yum list php *

then:

yum install php-gd.x86_64
yum install php-pdo.x86_64
yum install php-xml.x86_64
yum install php-mysql.x86_64

Next, visit:

http://192.168.56.10:8088/install.php

then restart apache:

/sbin/service httpd restart

And Drupal should be all ready to go!

Samba (filesharing)

In order to access the drupal files from your windows machine, you need to setup a fileshare in samba. To do this, edit your

/etc/samba/cmd.conf

file to have the following:

[global]
workgroup = intrepidtravel.local
server string = Samba Server Version %v
security = share
passdb backend = tdbsam
wins support = yes
dns proxy = no
cups options = raw
guest ok = yes
guest account = lachlan
[drupal]
comment = Public Stuff
path = /var/www/html/drupal-7.8
force user = lachlan
force group = apache
browseable = yes
writeable = yes
guest ok = yes
map archive = yes

Then restart Samba:

/sbin/service smb restart

You should then be able to access this fileshare by going to:

\\LachDrupal\drupal

these files should be editable too! If not, check the linux file + directory permissions (make them 775 just to be safe).

I have setup my machine so that the drupal folder is owned by the user lachlan and group apache.

cd /var/www/html
chown -R lachlan:apache drupal-7.8
chmod 775 drupal-7.8
/usr/sbin/useradd -G apache lachlan
/usr/sbin/usermod -G lachlan apache

Setting up services to run at boot

By default, apache, samba and mysql won't run at bootup. Enter the following commands as root to set this up:

/sbin/chkconfig --level 235 httpd on
/sbin/chkconfig --level 235 mysqld on
/sbin/chkconfig --level 235 smb on

Et voila!

If anyone can suggest any better or simplier ways to set this up I'd love to hear from you!

Posted in technical | Tagged , , , , , | Leave a comment

Disconnecting users from sql server database via c#

I’ve been setting up an automated build for our project. Our project has a very large SQL server database that we write “upgrade” scripts for – basically anything that modifies the schema – like adding new columns, modifying data etc as part of the release process.

We’ve found that over the past few releases that these upgrade scripts didn’t often work. They were buggy and not tested properly – primarily because testing them was a pain. You’d need to grab the latest backup of the production database, restore it, run the upgrade scripts against it, run the stored procs into it and then test your apps.

So instead I’ve automated it. Now it copies the latest production backup, restores it, runs the upgrade scripts, runs in the stored procs, compiles the code and then runs the unit tests. It is very cool, and has already saved us days of work.

Part of the fun is restoring the latest database backup. It’s all been working fine for a while, but sometimes we run into a problem – when restoring the latest backup we find that someone is already connected to the database. Normally because they wanted to check their upgrade scripts.

So I need to automatically disconnect anyone from the upgraded database. And yes, everyone is warned that this DB is blown away every night, and not to do anything in it! Here’s how I did it. The only thing that I’m not crazy about it using sp_who2 – it would be nice to interrogate the DB directly.. but hey, it works.


string conn_str1 = "Server=" + serverName + ";Trusted_Connection=True;Database=master";

using (SqlConnection conn = new SqlConnection(conn_str1))
{
    conn.Open();
    SqlCommand cmd = new SqlCommand();

    // give it 5 minutes:
    cmd.CommandTimeout = 5 * 60;
    cmd.Connection = conn;
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.CommandText = "sp_who2";

    using (SqlDataReader sqr = cmd.ExecuteReader())
    {
        while (sqr.Read())
        {
            int dbNameColumnId = sqr.GetOrdinal("DBName");
            int connectionIdColumnId = sqr.GetOrdinal("SPID");
            int loginColumnId = sqr.GetOrdinal("Login");

            if (sqr.GetValue(dbNameColumnId) != DBNull.Value &&
                sqr.GetValue(connectionIdColumnId) != DBNull.Value &&
                sqr.GetValue(loginColumnId) != DBNull.Value)
            {
                string dbName = sqr.GetString(dbNameColumnId);
                int connectionId = Int32.Parse(sqr.GetString(connectionIdColumnId));
                string username = sqr.GetString(loginColumnId);

                if (dbName.ToUpper() == newDatabaseName.ToUpper())
                {
                    Console.WriteLine("Disconnecting user: " + username);
                    DisconnectUser(connectionId);
                }
            }
        }
    }
}

and then the vital function:

private void DisconnectUser(int ConnectionId)
{
    string sqlKillConnection = "kill " + ConnectionId.ToString();
    string masterConnection = "Server=" + serverName + ";Trusted_Connection=True;Database=master";

    using (SqlConnection conn = new SqlConnection(masterConnection))
    {
        conn.Open();
        SqlCommand cmdKill = new SqlCommand();
        cmdKill.Connection = conn;
        cmdKill.CommandType = CommandType.Text;
        cmdKill.CommandText = sqlKillConnection;
        cmdKill.ExecuteNonQuery();
    }
    
}
Posted in technical | Tagged , , , , , , | Leave a comment

sqlCmd or oSql

As mentioned in my previous posts, you can use oSql or sqlCmd to execute SQL against a database. In my case I often have hundreds of these files that I wish to run (a bunch of stored procs into the DB) – and it turns out that if you want to do this it will connect to the DB, run the script, close the connection. Repeat.

All this adds up after a while and now running in all of my stored procs can take 10 minutes.

So instead I wrote my own c# application to connect to the DB, find any .sql files and run them all in. It’s 1000 times faster without all the overheads of establishing the connection each time.

The only gotcha is the “GO” command! Often you find yourself writing SQL like this:

UPDATE TABLE1 ADD NewColumn int
GO
update Table1 set NewColumn = OldColumn+1

but SQL Server doesn’t actually understand the GO command. The GO command merely separates “batches” of SQL. So my lovely little c# app has to look for these GO commands and execute the code one block at a time. Easily enough done and it now works magically. If anyone wants the code let me know… but really, you could write it yourself in half an hour.

Posted in technical | Leave a comment

Using osql or sqlcmd to execute scripts

I would like to complain to the management.

<rant>

Sql Server has a handy function that lets you run SQL against your database. Similar to running “mysql < SqlFile.Sql” you can use oSql, or it’s later variant, sqlCmd.

Anyway, so if you tell oSql to execute your script against the database, and that script fails, the default behaviour is to NOT return an error level. That’s right, not. You need to specify the “-b” parameter. Why? Who knows! If I was to guess I’d say it’s probably for some backwards combatibility reason. But either way it’s very annoying.

</rant>

Posted in technical | Leave a comment

Technical Blog and Zencart

I’ve separated out my music blog (which is now just metaltheater.com) and all of my technical programming blogs – which are now at metaltheater.com/tech. This technical one is now using wordpress as a bit of a test run.

Is there anything new going on in Lachlan’s technical world? Well I’ve been doing a bit of work on the Intrepid Foundation’s website – it’s a PHP thingamebob running something called ZenCart. What do I think of Zencart? Meh. It works… most of the time. Is it customizable? I guess it is… but it’s pretty hacky. At the moment I’m thinking that it would be nice to upgrade to the latest version – apparently all it takes is 3 easy steps. To summarise:

1. Download the latest version and install it into a new directory

2. Download WinMerge and compare the files in the new directory to the ones in the old directory. Copy across or merge the differences.

3. Copy the data from your old database into your new one.

No, this is not a joke. Can you believe this? What rubbish. I really don’t want to do it but it looks like I’m going to have to. What makes it especially fun is that I didn’t do any of the original customisations to the existing site – so when it comes to running the merge I really have no idea what’s meant to be there or not. Fun!

Posted in Uncategorized | Tagged , , | Leave a comment

Friendly URLs in classic ASP

Classic ASP, is there anything it can’t do?

Well, if you’re looking at doing nice and friendly URLs, like the one for this post:

http://www.metaltheater.com/post/Friendly-URLs-in-classic-ASP

Yes, you can do it in ASP!

Your first step is to open up IIS, click on your home directory and then go to properties. Then go to the “Custom Errors” tab, and scroll down to “404″:

Setting up nice URLs in classic ASP

edit this entry, and change the message type to be “URL”, and set the URL to “/404.asp”:

Setting up nice URLs in classic ASP

(Oh yeah, create a file named 404.asp in your root directory).

Alright, now you’ll notice that any request that goes to your site will go to this file. So try it, go to:

http://localhost/test-page

and you should get a blank screen. This is hitting your 404 ASP page! Now you need to put some logic in redirect the user to the page that shows your blog post. Eg, my links used to look like this:

http://www.metaltheater.com/code/article.asp?Id=200

So now, I need to scan the URL for the title of a blog post, check in the DB to see if it can find the blog title, and then transfer the user to the old URL. One little gotcha is that you cannot pass through parameters! So you actually have to transfer the user to “article.asp”, and put the ID value into the session. A little bit dodgy, but it works ok.

So my code looks something like this:

urlText = Request.ServerVariables(“Query_String”)
slashSpot = inStrRev(urlText, “/”)

if ( mid(urlText, slashSpot-4, 4) = “blog”) then

title = mid(urlText, slashSpot+1, len(urlText))
titletransformed = replace(title, “-”, “%” )
titletransformed = replace(titletransformed, “%27″, “”” )

sql = “select id from posts where title like ?”

set rs = dbwrapper.executeSql(sql, titleTransformed)

session(“PostId”) = “-1″

if not rs.eof then

session(“PostId”) = cstr(rs(“id”))

end if

rs.close

server.transfer “/code/article.asp”

Then article.asp checks the session object. If it’s set to -1, then it displays a 404 error page, but it needs to set the response code to 404, so sites like google recognise the page as not found. This is really easy in ASP, just do:


response.status = “404 File Not Found”

You can then return any content you like.

And voila! SEO friendly URLs :)

Posted in technical | Tagged , | Leave a comment

Playing frogger on the atari

When I was young I had frogger on my atari. It was awesome. You play a frog who has to dart across a road, dodge the traffic, and then dart across a river and into your frog-home. If you were too slow you’d get hit by something. You had 3 lives, after you’d used them up the game was over.

Now that I’m grown up and all, I have no wish to try to recreate it in real life. I only have 1 life, and I’m pretty happy with it.

Posted in technical | Tagged , | Leave a comment

MetalTheater.com on your mobile – getting it to work for my iphone

metaltheater on an iphoneMetaltheater.com now works on your mobile! If you pop out your iPhone, Blackberry, Android, Nokia or whatever, and go to metaltheater.com, you should find a nice and easy to read version of the site!

I used a couple of techniques. The first one that I investigated was using an alternate CSS stylesheet just for the mobile, using the ‘media=handheld’ attribute. Just the way the web was always meant to work! But did it work?? Well…

  • My iPhone completely ignored the stylesheet! The iphone thinks it’s better than your average mobile browser, so it ignores it. Brilliant. The website looked exactly the same. Pointless for iphones.
  • Even if I got that way to work, the entire websites HTML is still sent down the wire to the phone, and then you hide it using CSS. That’s crap. I don’t want to force the user to download extra data that they don’t need to, and I don’t want to run the extra code on my server.
  • Even if I overcame all of that, I couldn’t find an easy way to test both CSS stylesheets. It was a pain in the bum.

So stuff that method. Couldn’t I look at the user agent or something? Surely you can just detect if it’s a mobile? Well it turns out (of course) it’s not that easy. There’s no simple way to do it. I ended up using this code to detect a mobile browser in classic ASP. Perfect. It’s pretty simple, just looks inside the user agent string for a bunch of text. Cool.

Next step, modifying my code to spit out only the HTML that I want. That was pretty easily. Fortunately almost all of it is exactly the same, except for the left navigation and the header.

But then I really didn’t like the overall style of the site on my mobile… so I decided to link to a different CSS file depending on the user agent. For the mobile CSS file (you can see it for yourself at metaltheater.com/include/mobile.css) I actually just started from scratch. Fortunately when I first did the site I put a lot of effort into doing the HTML/CSS correctly. Ok so there’s a few tables in there but mostly the HTML is very good – very semantic and lightweight. The site actually looks pretty good without CSS, and on the mobile with an empty CSS file it looked pretty good too. I just got rid of the width settings, so that it nicely fits onto your screen, centered the header, and that was really about it.

So it’s best of both worlds really. You get only the HTML you need, it looks good on the phone, the server does a lot less work when accessing it on the phone, and you still get the full version on the web. Nice. Took me only about 1.5 hours from scratch to do! Including the googling and the changing :)

Posted in technical | Tagged , , , | Leave a comment

urban spoon displaying restaurant reviews from other sites..

Now this is pretty cool.

A few days ago I wrote this very quick and lame restaurant review, and put in an image and link back to urbanspoon‘s review page for that restaurant. The cool thing is that urban spoon then (presumably) look for the RSS feed on the site that link to their restaurant reviews page and display your review. Now that’s pretty cool.

Posted in technical | Tagged , | Leave a comment