Posts Tagged ‘Code’

New Site, mat.tc API and Wordpress Plugin

// January 10th, 2010 // No Comments » // Uncategorized

Unless you’re reading this via RSS, you’ve already seen the new site I’ve rolled out. I really like it and hope you do as well. I did more than just redesign the way it looks though. It’s more than a pretty face.

I spent some time trying to clean up the information on the site too.  Specifically, I shortened the about page and really over hauled the portfolio page.  The portfolio is way better than it was:

New & Old Portfolio Pages

I think the new page is a lot cleaner and because there’s SO much less text, it should be easier to read and understand.

I also thought I’d play with some APIs and get into Wordpress a but while I built the new site.  I certainly brushed up my PHP and also learned a bit about Wordpress Plugins.  I wrote a plugin like Twitter Tools from Alex King – except mine uses my own http://mat.tc url shortener.  Obviously to do this I wrote a simple shorten API modeled after bit.ly’s API.  It works wonderfully.  I can tweet from the site when logged in.  Automatic new post tweets also use mat.tc now which saves me the extra steps.

Twitter Tools doesn’t use OAuth though, so I had to rewrite a bit of the code so Twitter would recognize my calls and show the correct “From: ” line for tweets.  But that wasn’t too bad.

To round out the new site, I created a new logo too.  The old logo (in the image above) was just a simple play on my initials.  While exploring new ideas I came back to this ‘letters in my name’ idea.  So the little dude is made up of letters in my name (the m, c, and 2 l’s).  I added the tie because I thought it clarified it was a person – plus the business tie-in worked (sorry).  Font is Insignia.

Anyway, I’m really glad the content on the site is updated.  The new design, logo and mat.tc/Twitter integration is also nice.  I threw in a little flash on the login page for fun too: check it out.

Enjoy!

Sites.Local – for developers with too many local sites

// December 5th, 2009 // No Comments » // Uncategorized

As an ASP/C# developer it’s key I work locally and save time wasted uploading files after every change to a page.  Then, when I’ve got a bunch of changes to share with a client and I want to update a staging/production environment, I can do it all at once.  Well, I resumed working on a project this afternoon that I haven’t worked on for a couple days – and I just couldn’t recall the local site address!

My laptop runs Vista Business and I use Internet Information Services (IIS) to run local apps.  To map the various apps and keep everything running on port 80 I take advantage of the Windows Hosts file to create custom urls for local apps.  For example, I can create an entry for clientname.localdev which enables me to setup and view a site at http://clientname.localdev/.  You can learn more about Hosts files here if they’re new to you.

Back to this morning: I couldn’t recall if I setup localdev.project, project.localdev, project.local, or local.project.  Only way to check is to open up the Hosts file and see what I had originally created.  That’s when I thought: let’s write a quick page to read all the entries in my Hosts file.  So I did, and I setup sites.local as my own, local directory of entries read directly from my Hosts file.  Check it out:

I figured I’d create some categories to group the multiple entries I’ve got in my Hosts file – and add a quick flag for showing a category collapsed by default (more on this later).  Here’s a modified (sample) Hosts file:

First, let’s look at a few changes to the Hosts file itself to make all this work:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# Copyright (c) 1993-2006 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host
 
127.0.0.1       localhost	#ExcludeFromSites.Local
::1             localhost	#ExcludeFromSites.Local
 
#Sites.Local.Category: New Projects Category#
127.0.0.1       project1.local
127.0.0.1       project2.dev
127.0.0.1       anotherclient.devel
127.0.0.1       project3.local
 
#Sites.Local.Category: Other Category Here#
127.0.0.1       project4.local
127.0.0.1       project5.dev
127.0.0.1       project6.local
 
#Sites.Local.Category: Archived/Past Por {start:collapsed}#
127.0.0.1       project7.local
127.0.0.1       project8.dev
127.0.0.1       client23.devel
127.0.0.1       project9.local
127.0.0.1       project10.local
127.0.0.1       project11.dev
127.0.0.1       clientname.devel
127.0.0.1       project12.local

This obviously is not my Hosts file – I created a sample file for demo purposes.  But either way, there are a couple things to note here – most of which will make sense as you look at the upcoming .aspx and code behind:

  • Adding “#ExcludeFromSites.Local” to the end of the line will (you guessed) prevent the line’s display on our page
  • You can group entries by adding “#Sites.Local.Category: categoryname# to a line above that group, where categoryname is some text you’d like to refer to this category by
  • You can “{start:collapsed}” to a group name to display this group collapsed initially (each group can be collapsed/expanded by clicking the group name

Now onto the code – I made comments throughout the code behind to make things easy to follow.  The code could certainly be simplified, but for the sake of clarity I expanded some of it.

First, the .aspx page:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Inherits="siteslocal_default" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Local Site Addresses</title>
    <style type="text/css">
        * {
            font-family:Arial;
            font-size:13px;
        }
        body {
            background-color:#dfd;
        }
        div#centercontent {
            width: 800px;
            height: 500px;
            text-align: center;
            position: absolute;
            left: 50%;
            top: 50%;
            margin-left: -400px;
            margin-top: -250px;
        }
        div#header {
            text-align:left;
            font-size:23px;
            font-weight:bold;
            height:30px;
        }
        div#content {
            border: 1px solid #000;
            padding: 30px;
            text-align:left;
            height:360px;
            background-color:#fff;
            overflow-y:scroll;
        }
        div#footer {
            text-align:left;
            font-size:12px;
        }
        div.category {
            margin-bottom:15px;
            margin-left:10px;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <div id="centercontent">
        <div id="header">Local Site Addresses</div>
        <div id="content">
            <asp:Literal id="litHosts" runat="server"></asp:Literal>
        </div>
        <div id="footer">The contents of this page are being read directly
             from the hosts file in C:WindowsSystem32driversetc</div>
    </div>
    </form>
</body>
</html>

And for the meat of the page, here’s the code behind written in c#:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
using System.Web;
using System.Web.UI;
using System.IO;
 
public partial class siteslocal_default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        StreamReader reader = File.OpenText(@"C:WindowsSystem32driversetchosts");
        string line = string.Empty;
        while ((line = reader.ReadLine()) != null)
        {
            if (!line.StartsWith("# ") &amp;&amp;
                !line.StartsWith(" ") &amp;&amp;
                line != "#" &amp;&amp;
                line != "" &amp;&amp;
                !line.EndsWith("#ExcludeFromSites.Local"))
            {
                bool show_collapsed = false;
                string showhidecode = string.Empty;
                if (line.StartsWith("#"))
                {
                    /******* Append the HTML for the start of a new category *******/
                    if (litHosts.Text != "")
                        litHosts.Text += ""; //only append if we're not on the first category
 
                    if (line.Contains("{start:collapsed}"))
                        show_collapsed = true;
 
                    string catText = line;
                    catText = catText.Replace(" ", "").Replace("t", "");     //remove spaces and tabs
                    catText = catText.Replace("{start:collapsed}", "");       //remove from display
                    catText = catText.Replace("Sites.Local.Category:", "");   //remove category prefix
                    catText = catText.Replace("#", "");                       //remove any stray #'s
 
                    //prep the javascript onclick code and div id
                    string id = catText.ToLower();
                    string js = string.Format("document.getElementById('{0}').style.display",id);
                    showhidecode = _
                       @"onclick=""if({0}=='block'){{0}='none';}else{{0}='block';}""".Replace("{0}", js);
 
                    //append the &lt;div&gt; for this category's name
                    litHosts.Text += string.Format(@"&lt;div style=""cursor:pointer;"" {0}&gt; _
                    &lt;b&gt;{1}&lt;/b&gt;&lt;/div&gt;", showhidecode, catText);
                    //append the &lt;div&gt; opening tag for this category
                    litHosts.Text += string.Format(@"&lt;div id=""{0}"" class=""category"" _
                         style=""display:{1};""&gt;", id, show_collapsed ? "none" : "block");
                }
                else
                {
                    /******* Append the HTML for each item in the current category *******/
                    //first let's isolate the host name (assumes we don't need to display the IPs)
                    //so...let's the find the index of the first space or tab
                    string url = string.Empty;
                    line = line.Trim();
                    int spacer_location = 0;
                    spacer_location = line.IndexOf(' ');
                    if (spacer_location == -1)
                        spacer_location = line.IndexOf("t");
 
                    //display from the spacer to the end
                    url = line.Substring(spacer_location, line.Length - spacer_location);
                    url = url.Replace(" ", "").Replace("t", ""); //remove any spaces or tabs
 
                    //write out this line
                    litHosts.Text += string.Format(@"&lt;a href=""http://{0}/""&gt;{0}&lt;/a&gt;&lt;br /&gt;", url);
                }
            }
        }
        litHosts.Text += ""; //close out the last div
        reader.Dispose();
    }
}

The only other things to note are:

  • I setup this page to run at http://sites.local and site this as my home page in Chrome – in IIS I changed the anonymous user to my own username (to ensure the code has permission to access the file)
  • Be sure to not to start an entry in your Hosts file with a Tab – the code allows preceeding spaced, but would need to be changed to allow preceeding Tabs

That’s it, hope you find this useful and a bit of a timesaver too.  Only took about 30 minutes to pull together, and I think you ought to be able to set it up in less time than that.

Happy coding!