Miguel A. Castro's Blog

# Monday, March 15, 2010

One of the reasons I took my blog off GeeksWithBlogs.com, despite the fact that I liked running it there for as long as I did, is so I can have source control over the site and be able to customize it as much as I want.  As before, I want people to be able to visit this site to learn about speaking engagements I do and to download session material, but rather than spread out the session material on individual blog postings (though I’ll do that as well), I wanted a single page where folks can go and download any material I’ve made available; hence www.dotnetdude.com/downloads.

So here’s where I tell you what I did and how I did it.  Now as usual, I anticipate criticism on what I did wrong and how better I could have done it and blah blah blah.  So while I really don’t care what people say about the way I do certain things, I will tell you what my goal was so you understand the methods I undertook.  I wanted a very, very simple downloads page.  Let me repeat that s-word, “SIMPLE”.  I didn’t want to have a database driven page or something with layers of categories.  I simply wanted a single page where anyone can go to get session, or magazine material.  Now that being said, I did want some amount organization while having ease of maintenance.  I simply ended up writing a page that read off a folder structure and manifested that structure in a tree.  In fact, in the interest of keeping it as simple as possible, I used Microsoft’s TreeView control.

The code is pretty generic (as you’ll soon see) and simply looks for a folder starting point, which I store in the config file.  From there it recursively iterates through the folders and files and builds the nodes of the tree.  This design let me manage the folder structure in whatever manner I want and allows for as much or as little hierarchy as I want.  I thought this was a good mix of simplicity and flexibility.

This was the easy part.  The harder part was digging around the dasBlog source code to figure out what I had to do in order to add custom pages to the site.  The dasBlog engine is very nice but does things a bit different from what conventional web forms application developers may be used to.  The site uses template files to determine the ASP.NET code for each section of a page.  For example, the main layout of every page in your blog is determined by a file called homeTemplate.blogTemplate.  This file contains what looks like conventional HTML code, and in fact it is.  However there are some keywords surrounded by <% %> tags (note, no equal sign) which will get replaced later when the template is processed and rendered.  This design actually made it pretty easy to customize the theme I chose for my blog because it is in this particular template file where I went to make alterations to the page layout.  When I wanted to customize what the blog posting area looked like, I went to the itemTemplate.blogTemplate file.  Here I could make changes like put the permalink on top instead of the bottom, or add an image to the left of my post header, etc.  Back to the homeTemplate.blogTemplate file; it is here where I added additional link tags and meta tags I wanted every page to use.  I also added the Syntax Highlighter here that you’ll see in practice below on code.  Rather than tell you a lot about this must-have utility, just check out Scott Hanselman’s post here.  Another customization I’ll save for another post is the Bing search box on the site.

So now that I knew how the templates worked, I wanted to add a custom page that appeared within the context of the main layout defined in the homeTemplate.blogTemplate file.  It didn’t take much digging into the existing pages of the site to figure out the repeating pattern they all have.

The page I wanted was to be called Downloads.aspx so I started by creating that page right off the root of my site.  Every page in dasBlog contains an empty PlaceHolder control which is later filled with a corresponding user control.

<%@ Page Language="C#" AutoEventWireup="False" CodeBehind="Downloads.aspx.cs" Inherits="newtelligence.DasBlog.Web.Downloads" %>
<asp:placeholder id="contentPlaceHolder" runat="server"></asp:placeholder>

 

The code-behind for this page follows the same pattern as other pages in the site.  The main thing is to inherit from the SharedBasePage class and implement the IPageFormatInfo interface.  The only required implementation for this interface is the BodyText property which returns a type of Control.  Here is where I would return an instance of a user control that will be the actual heart of my new page.  By instance, I mean a usage of the LoadControl command.  Another standard on the page is to expose the PlaceHolder by providing a property for it. 

Here’s the code-behind for the Downloads.aspx page:

using newtelligence.DasBlog.Runtime;
using newtelligence.DasBlog.Web.Core; 

namespace newtelligence.DasBlog.Web
{
    public partial class Downloads : SharedBasePage, IPageFormatInfo
    {
        protected override PlaceHolder ContentPlaceHolder
        {
            get { return contentPlaceHolder; }
        } 

        public Control Bodytext
        {
            get { return LoadControl("DownloadsList.ascx"); }
        }
    }
}

 

Now I had to write the user control that this page was to load and display.  This user control was simply going to have an ASP.NET TreeView control on it.

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="DownloadsList.ascx.cs" Inherits="newtelligence.DasBlog.Web.DownloadsList" %>
<%@ Register Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    Namespace="System.Web.UI" TagPrefix="asp" %>
<div class="downloadHeading">File Download Section</div>
<div class="bodyContentStyle" id="content" runat="server">
    <div class="downloadArea">
        <asp:TreeView ID="tvwFiles" runat="server" NodeIndent="40">
            <NodeStyle CssClass="fileTree" />
        </asp:TreeView>
    </div>
</div>

 

The div-tag hierarchy is just standard div styling with which I’m sure most of you as more familiar with than I am.

The real meat of this page is in the building of the tree, but even this was not overly complex.  I simply loaded a folder starting point from my config file and started my recursive iteration.  Each time I went down a level, I sent the previously built tree node so that each subsequent child tree node can be added to its collection.  The ASP.NET TreeView control is a bit more limited than third party controls and only seems to allow node-searching through one level within the tree.  If I’m wrong on this, please let me know.

Before I show you the code for this user control, let me tell you about one more thing I came up with.  Even though a folder and file hierarchy is easy enough to follow for any of us, I wanted a tad more polishing to this page.  I wanted the option (not the requirement) to display friendly titles for both folders and files within the folders should I desire that (and I do).  To accomplish this, I knew I would need some kind of mappings file but I didn’t want one massive file to manage so what the code does is look for a file called index.xml in each folder during the recursive iteration.  This file, if it exists, will let me rename the folder itself as well as any of the contained files.

Here’s an example of the index.xml file which resides in a folder called Cairo2010:

<titles folder="Cairo Code Camp - Feb 2010">
    <title file="DynamicStateStorage.zip" name="Dynamic State Storage: An ASP.NET Provider-Based Feature" />
    <title file="Extensibility.zip" name="Extensibility: Software That Survives" />
    <title file="FunWithHandlers.zip" name="Fun With HTTP Handlers" />
    <title file="UnderstandingASPNET.zip" name="Understanding ASP.NET Under The Covers" />
</titles>

 

As you can see, based on the information in this file, the folder will display as Cairo Code Camp – Feb 2010 and each of the contained files will display as their corresponding title as show in each name attribute.  Should I forget to create one of these files for a particular folder or forget to map a particular file within a folder, or simply decide to not do it by choice, the tree will display the original folder or file name instead.

    public partial class DownloadsList : System.Web.UI.UserControl
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                string filesSubFolder = ConfigurationManager.AppSettings["files"];
                string filesFolder = Server.MapPath(filesSubFolder);
                string filesUrl = Request.ApplicationPath + "/" + filesSubFolder;

                string[] folders = ProcessFolder(filesFolder, null);
            }
        }

        private string[] ProcessFolder(string path, TreeNode parentNode)
        {
            string[] folders = Directory.GetDirectories(path);
            if (folders.Length > 0)
            {
                foreach (string folder in folders)
                {
                    DirectoryInfo dirInfo = new DirectoryInfo(folder);
                    string folderName = dirInfo.Name;

                    XDocument xmlDoc = null;

                    string indexFile = folder + "\\index.xml";
                    if (File.Exists(indexFile))
                    {
                        xmlDoc = XDocument.Load(indexFile);
                        var attrFolder = from node in xmlDoc.Descendants("titles")
                                 where node.Attribute("folder") != null && node.Attribute("folder").Value != ""
                                 select node.Attribute("folder").Value;

                        if (attrFolder != null)
                            folderName = attrFolder.FirstOrDefault<string>();
                    }

                    TreeNode folderNode = new TreeNode("&nbsp;&nbsp;" + folderName, folder);
                    folderNode.SelectAction = TreeNodeSelectAction.None;
                    folderNode.ImageUrl = "Images/Folder24.png";
                    
                    if (parentNode != null)
                        parentNode.ChildNodes.Add(folderNode);
                    else
                        tvwFiles.Nodes.Add(folderNode);

                    // retrieve files
                    string[] files = Directory.GetFiles(folder);
                    if (files.Length > 0)
                    {
                        string appPath = Request.PhysicalApplicationPath;

                        foreach (string file in files)
                        {
                            FileInfo fileInfo = new FileInfo(file);
                            string fileName = fileInfo.Name;

                            if (fileName.ToLower() != "index.xml")
                            {
                                if (xmlDoc != null)
                                {
                                    var attrName = from node in xmlDoc.Element("titles").Descendants("title")
                                                    where node.Attribute("file").Value == fileName
                                                    select node.Attribute("name").Value;

                                    if (attrName != null)
                                        fileName = attrName.FirstOrDefault<string>();
                                }

                                string fileUrl = file.Replace(appPath, "");
                                string fileAlt = fileInfo.Name;
                                string fileLink = string.Format("<a href=\"{0}\" alt=\"{1}\">{2}</a>", fileUrl, fileAlt, fileName);

                                TreeNode treeNode = new TreeNode(fileName, fileUrl);
                                treeNode.NavigateUrl = fileUrl;
                                folderNode.ChildNodes.Add(treeNode);
                            }
                        }
                    }

                    string[] subFolders = ProcessFolder(folder, folderNode);
                }
            }

            return folders;
        }
    }

 

As you can see, the code uses Linq-to-XML to access the index.xml files.

The last thing I wanted to do is to give a user the easiest URL possible so although you can navigate to www.dotnetdude.com/downloads.aspx to get to this page, I want you to be able to simply type www.dotnetdude.com/downloads.

IE7 allows for extension-less URL, my current hosting server still uses IE6 so I needed a sure-fire technique to accomplish this.  The easiest thing to do was to create a sub-folder in my site called Downloads and place an empty Default.aspx page in it.  In fact, I eliminated the code-behind for this page so it is truly empty.  I eliminated the code-behind because I didn’t need to put a code-driven redirect to my actual Downloads.aspx page.  This is thanks to a URL mapper that comes with dasBlog.  To take advantage of this, I went to the web.config file and fouind the <newtelligence.DasBlog.UrlMapper> sesion.  Following the pattern I saw in there already, I added an entry that looked like this:

<add matchExpression="(?&lt;basedir&gt;.*?)/downloads" mapTo="{basedir}/Downloads.aspx"/>

 

This should be easy enough to follow.  Suffice it to say that navigating to www.dotnetdude.com/downloads now takes you to the actual Downloads.aspx page.  In fact, I added another couple of lines to shortcut to the email page on the site and to an bio posting as well.

<add matchExpression="(?&lt;basedir&gt;.*?)/aboutme" mapTo="{basedir}/2010/03/02/AboutMeShamelessBioPost.aspx"/>
<add matchExpression="(?&lt;basedir&gt;.*?)/contact" mapTo="{basedir}/Email.aspx"/>

 

Now you can simply type www.dotnetdude.com/email to contact me, or if you’re really bored you can type www.dotnedude.com/aboutme .

The last thing I want to point out here is that the TreeView control is not using JavaScript to expand and collapse itself.  I haven’t yet figured out why as this is supposed to be a built-in feature of the ASP.NET TreeView control.  I’m suspecting that it has to do with the way dasBlog turns templates into code and renders pages.  I need to put some time into it cause I don’t really like the fact that it posts each time you collapse or expand a node.  Clicking on a file doesn’t post, since the display text for each file is literally an HTML anchor tag to the actual file to download.  I tried simply putting the control in an ASP.NET Ajax UpdatePanel control and it was ignored.  This is what tells me it’s something within dasBlog rendering since the Ajax UpdatePanel functionality is also not working.  If anyone has any ideas on this, please let me know.

I hope this has been useful to anyone who uses dasBlog and wants to customize it to their liking.  Now I just gotta fill the download page with all my session material from past event.

Until next time.

Monday, March 15, 2010 7:48:06 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [0] - - Follow me on Twitter

# Tuesday, March 09, 2010

In the process of readying my new blog site, I wanted to place a couple of badges that point to my various profiles around the web and I found a site that showed me this link:

http://www.linkedin.com/profile?promoteProfile

It’s weird but trying to find this page within the LinkedIn site itself seems impossible.  In any case, each badge comes with the script that you can include in your own site so there’s not even the need to copy the image to your local store.

Here are some examples of what the page has:

View Miguel Castro's profile on LinkedIn

View Miguel Castro's profile on LinkedIn

View Miguel Castro's profile on LinkedIn

View Miguel Castro's profile on LinkedIn

Tuesday, March 09, 2010 3:59:12 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0] - - Follow me on Twitter

# Monday, March 08, 2010

Well, Code Camp in NYC is over and I have to say it was really a lot of fun.  Kudos to Steve, Andrew, and the rest of the organization staff for a great job.  The only thing that really holds that code camp back is the fire code in the Microsoft building on 6th Avenue.  There always seems to be a waiting list because the attendance registration fills up real fast, but be that as it may it was still great.

I always submit one or two intro talks and behold, they still get chosen.  I did an intro talk on WCF and the room was so packed that they asked me if I’d repeat it in the afternoon (packed too).  It seems that WCF is still an intimidating technology so I’m always glad to clear it up for people and prove that at its basics, it really is easy to hit the ground running with it.

You can get the code and slides in the downloads section of this site.  I didn’t go through all the slides because after all it is Code Camp and not Slide Camp.  However, the steps I took to write all the code from scratch and the order in which I took them is thoroughly highlighted in the slide deck amongst the slides I did not go through.

All in all, I think everyone seemed to have enjoyed the presentation and I’m always glad to add to the numbers of people getting up to speed on this technology.

Monday, March 08, 2010 12:58:31 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0] - - Follow me on Twitter
Speaking Events
# Saturday, March 06, 2010

Well, Tuesday I got back from Cairo Code Camp in, yeah you guessed it, Cairo.

No, I’m not talking about the umpteen cities in the US called Cairo; I mean the one in Egypt.  I think the only way I can describe the trip and the place is to use the word surreal.  I’m a long time history buff so by the mere concept of being there was unbelievable to me.  Add to that the couple of visits we made to those gargantuan structures in the desert and it was more than enough to keep me in awe for the entire time I was there.

The so-called code camp was not really a code camp, it was really more of a real conference.  It’s attendance and organization both had the feel of such.  This thanks to the folks at DashSoft and the incredible help they acquired for this event.  These folks are all part of .NETWork, a user group based in Egypt.  This conference was hands-down, one of the best trips I’ve ever taken.

My take on Cairo:

Being raised in the United States (though not born here), overseas trips tend to have their share of fascination with me but after going to several western European countries, I’ve grown quite accustomed to it.  There are several aspects of my visit to Cairo for which I could not have been prepared.

 

1. The first is the traffic.  I don’t know where to even begin here.  The only thing I can possibly say is that you should all go to YouTube and do a search on “Cairo Traffic”.  It will give you hours of pleasure.

 cairo_traffic_jam
 2. The second is of course the sheer awesomeness of the Great Pyramids at Giza.  I found out that Giza is actually a province of Greater Cairo and the Pyramids are in fact just outside the city in the area where the desert starts.  I got to see these twice, at night and in the day time.  At night, they weren’t lighted since it was 1:30 in the morning but it’s pretty incredible seeing the black triangles against the black of the sky as you’re on horseback headed toward a Bedouin camp.  Forget about the immense allergic attack (shown in the picture) I got because of the horse, it was totally worth it.  The following day we went to visit them at daylight and it was a completely separate and equally awesome experience.  As if the allergic attack the night before was not enough, this time I suffered a pretty severe cluster phobic attack while entering one of the pyramids.  I’m 6’4” and I had to duck into a passageway about 50-75 feet long, 25 degrees down, with dimensions of about three feet high and two and a half feet wide – not pleasant.

night_horseride_cairopyramid_and_sphynx
3. The third and most incredible thing about Egypt was the people.  The Egyptian people were the friendliest, warmest bunch I’ve ever met.  Their culture in intertwined with their religion in a way that I didn’t expect.  I guess I was expecting more of a Muslim state like Saudia Arabia, but that was not the case.  The Egyptian Muslims take their religion very seriously.  It becomes part of their guide through life and they respect and follow their customs; but at the same time they enjoy themselves and party no different than any of us, except of course without the drinking.  There is a 20% Christian population there and they get wasted with the best of us :).  I can’t say enough good things about all the people I met and spent time with.  The best thing about this trip is the number of new friends I met, and I hope to stay in touch with them for a long time. cairo_girlscairo_guys

 

My Sessions:

The folks that ran the conference gave me four sessions to do and the turn-out for all of them was insane:

  1. ASP.NET Under The Covers
  2. Extensibility: Software That Survives
  3. Fun With HTTP Handlers
  4. Dynamic State Storage: Custom ASP.NET Provider Features

The skill and understanding level was above average with this crowd and even the language gap turned out to be a non-issue.  The most challenging thing for me was making a conscious effort to lose my New Jersey accent and to speak slower, but it all turned out great.

The slide deck and code for all my sessions can be found on this blog’s download page.

The rest of my pictures from the trip can be found on my Picasa album.

Thank you to the folks at DashSoft, .NETWork, and most of all to the attendees of Cairo Code Camp for making my first visit to Egypt so memorable !

A very special thanks to the Zakari family for the unbelievable spread they put out on Monday.  Thank you for your incredible hospitality !

Saturday, March 06, 2010 12:36:00 AM (Eastern Standard Time, UTC-05:00)  #    Comments [3] - - Follow me on Twitter
International | Speaking Events
# Tuesday, March 02, 2010

Like if you care, but here’s my bio posting.  My resume can be found here.

Business headshot1

I got started in the computer industry just after high school.  During that part of my life, I spent a lot of time at the local Radio Shack learning Basic on the old TRS-80s.  I learned programming by reading code in David H. Ahl’s Basic Computer Games and More Basic Computer Games while programming Apple IIs and Ataris.  I put myself through college by working as a programmer at a Miami-based software company.  My area of expertise at that time was something called the PICK operating system.

Advance to 1989 (September 11 actually).  I moved to New Jersey and got started working in Microsoft technologies with the release of Visual Basic 1.0 (actually, I did some QuickBasic and Turbo Pascal back in Miami).

I moved into the consulting arena in 1994 when I started to work for what used to be Coopers & Lybrand Consulting, one of the then-big 6 firms (now it’s joined with Price Waterhouse into what’s known as Price Waterhouse Coopers).  A year later, I got the opportunity to contract for a startup and branched out on my own.  I’ve been independent ever since and am incorporated as SteelBlue Solutions (just happens to be my favorite web color).

In 2004 I got started doing a lot of community involved work including speaking at user groups and writing for CoDe Magazine and was awarded Microsoft MVP in 2005.  Several months later, I was picked up by INETA as one of their speakers.  In 2006 I got my conference break with VSLive and have since spoken at all the major conferences around the states including DevConnections and Tech-Ed.  I’ve also spoken at several overseas conferences.

In 2007 I started doing training with Dunn Training & Consulting, a company owned by my good friend, Mark Dunn.  Later that year, myself, Mark, and Rocky Lhotka put together a class on Rocky’s famous CSLA business framework and later that year we held a pilot class with 30 students.  I’ve taught that class over 30 times since then and it still runs once in a while.  In early 2009, I joined the ranks of the IDesign Architects under the recommendation and support from a good friend of mine, Brian Noyes.  The consulting and training with IDesign is what keeps me busy today and is both challenging and enjoyable work.

Something else that took place along this time was the release of my product, CodeBreezeCodeBreeze is a code-generator that was born out of a personal need at many of my consulting assignments and grew into a commercial product.  CodeBreeze is currently at its 2.0 release and I’m working on releasing 3.0 sometime in the middle of this year.

Personalvictoria

I was born in Havana, Cuba and came to the United States in 1972.  Our departure from our country came after a two-year tour in a cuban field-labor concentration camp that my father served in to gain an exit visa (now you may understand why I’m so anti-commie and so politically conservative when it comes to certain security issues).  We left the country in 1969 and went to Madrid, Spain and after three years there, moved to New York City.  One year later we did what every other good Cuban does, moved to Miami, FL.

elenaI’m the oldest of four, the others being two brothers and one sister.  Between them I have 3 nephews and 2 nieces.  All of them as well as my parents still live in Miami (shit, all in the same town actually).

I married a wonderful woman from Belarus in 2003 after dating her for about three years and in December of that year we had my daughter, Victoria.  Victoria is  currently 6 years old (well, 6 and a quarter if you ask her) and is more computer literate than I was when I was 12 (and most people that are 30).

Other things I enjoy is riding my Harley or riding around in my convertible with daughter.  I enjoy cigars and scotch and am always in the middle of a book.  I love military tech novels from Coonts or Clancy but am also an immense fan of Clive Cussler.

 

 

 

 

The Future

So what’s in store for me in the future.  I guess the easy answer is tech and family.  Don’t get on my ass for not having a life; I have a great life.  I have the good fortune that my hobby and my profession are one in the same.  I spend an incredible amount of time reading and keeping up to speed in new technologies, a task that does not get any easier.  I’m either working on CodeBreeze on a regular basis, or some other pet project (typically more than one at the same time).  I believe that as a consultant, it would be a disservice to my clients, both present and future, to do otherwise.

 

Passion for technology
   
is my strategy for success

Tuesday, March 02, 2010 12:40:00 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0] - - Follow me on Twitter

Search
Me & My Flair

Read all about me here.
Download my Resume here.

Check out where I am here.
 
Click on logos above for profiles.
Archive
<March 2010>
SunMonTueWedThuFriSat
28123456
78910111213
14151617181920
21222324252627
28293031123
45678910
Statistics
Total Posts: 40
This Year: 0
This Month: 0
This Week: 0
Comments: 93