Loring Software, Inc

A Software Developer's Notebook
This is the first time I have used a Master Page on a web application. It is quite simple, and the behavior is predictable.  I have to say it is a long time coming. I wrote a templating language for HTML in Java right before they released ASP, and it had master pages.  Almost an identical implementation, too.  I think I will have to reformat the Flying Club's web site to use it.

While trying to merge my code into my original web site, written in JScript, I got a strange error. I added a link from this new blog's Nav Bar (on the left) to the index.asp page, and when I ran the debugger I received:


Server Error in '/' Application.


This type of page is not served.

Description: The type of page you have requested is not served because it has been explicitly forbidden.  The extension '.asp' may be incorrect.   Please review the URL below and make sure that it is spelled correctly.

Requested URL: /index.asp

Further investigation into the error shows that you cannot run the Visual Studio web server and navigate to an .asp page. When I tested this on the IIS server normally, it linked as expected. My guess is that there is no way to configure VS to work around this (and a search on the net tends to confirm this).


I needed a list placeholder for the list of blogs on the left hand side. Then I would write a piece of code in the load of the master page which would iterate over the files in this folder and find all the files with a date as the file name, look at the header tag inside the file, and create a URL to add to the list. First stop, the Bulleted List:

<asp : BulletedList runat="server" ID="BlogList" DisplayMode="HyperLink" />

As there are always many ways to skin this cat, I decided to first try the brute force, all in the code behind. In the Page Load code for the master page, I added the following:

            ListItem a_newItem = new ListItem("April 4, 2009 - Developing a .Net Blog", "20090404.aspx");
            BlogList.Items.Add(a_newItem);

So far, so good. I don't really like the bullet, so I look for just a generic list. I want something which I can later bind to, if I ever want to move away from populating the list from the code behind. Let's now try out the Repeater:

<asp:Repeater runat="server" ID="BlogListRepeater">
    <ItemTemplate>
        <asp:HyperLink runat="server" NavigateUrl='<%# Eval("Value") %>' Text='<%# Eval("Text") %>' ></asp:HyperLink>
    </ItemTemplate>
</asp:Repeater>

Now, of course, I need a new list to be a data source to the repeater. I like the ListItems object, so lets stick with that.

            ArrayList a_array = new ArrayList();
            ListItem a_newItem = new ListItem("April 4, 2009 - Developing a .Net Blog", "20090404.aspx");
            a_array.Add(a_newItem);
            BlogListRepeater.DataSource = a_array;
            BlogListRepeater.DataBind();

Last thing to do is Figure out the real list of items from a directory listing:

        protected void Page_Load(object sender, EventArgs e)
        {
            // create the data source
            ArrayList a_array = new ArrayList();
            // find any aspx files in the current directory
            FileInfo [] a_fileInfos = (new DirectoryInfo(Server.MapPath(".")).GetFiles("*.aspx"));
            foreach (FileInfo a_fileInfo in a_fileInfos)
            {
                // blog files have the date, in yyyymmdd format as the file name
                string a_name = a_fileInfo.Name.Substring(0, a_fileInfo.Name.IndexOf('.'));
                if (a_name.Length == 8)
                {
                    string a_year = a_name.Substring(0, 4);
                    string a_month = a_name.Substring(4, 2);
                    string a_day = a_name.Substring(6, 2);
                    string a_formattedDate = a_month + "/" + a_day + "/" + a_year;
                    DateTime a_result;
                    if (DateTime.TryParse(a_formattedDate, out a_result))
                    {
                        // looks like a blog file
                        string a_fileLink = a_fileInfo.Name;
                        // default a string in case there is no <title> tag in the file
                        string a_linkText = "Entry on " + a_formattedDate;
                        using (StreamReader a_sr = new StreamReader(a_fileInfo.FullName))
                        {
                            // ok, find the Title
                            string a_file = a_sr.ReadToEnd();
                            const string a_titleString = "<title>";
                            int a_ix, a_ix2;
                            if ((a_ix = a_file.IndexOf(a_titleString, StringComparison.CurrentCultureIgnoreCase)) > -1 &&
                                (a_ix2 = a_file.IndexOf("</title>", StringComparison.CurrentCultureIgnoreCase)) > -1)
                            {
                                // found it.  Extract everything between the tags
                                a_ix += a_titleString.Length;
                                a_linkText = a_file.Substring(a_ix, a_ix2 - a_ix);
                            }
                        }
                        // add the found blog to the list of blogs
                        ListItem a_newItem = new ListItem(a_linkText, a_fileLink);
                        a_array.Insert(0, a_newItem);
                    }
                }
            }
            // assign the source to the repeater, and we're off to the races
            BlogListRepeater.DataSource = a_array;
            BlogListRepeater.DataBind();
        }
 
 


The rest is the job of the eye candy specialists... Lacking that, perhaps I will mess with the colors a bit.

One thing I could actually do would be to save the array of blog entries into a Context. But file operations are so fast these days, I wouldn't bother considering it (unless of course this blog starts to get a million hits a day!)



Copyright © 2017 Loring Software, Inc. All Rights Reserved
Questions about what I am writing about? Email me