Steve Holstad's "the bright lights"

"Just because your voice reaches halfway around the world doesn't mean you are wiser than when it reached only to the end of the bar." - Edward R. Murrow
in

March 2006 - Posts

What is "My dreams finally realized?" Jeopardy! Online !!!!

For the first time ever, uber-popular game show Jeopardy! is offering online testing, from March 28-30.  Now you have the chance to take the application test without having to travel to an audition site...I'm fired up, I've wanted to be on this show since I was in California, but I never had the chance to head up to the auditions...carpe diem.

I'll see you in Final Jeopardy! folks!

http://www.jeopardy.com/announcement_20060322NationalOnlineTest.php

Posted: Mar 27 2006, 07:02 PM by sholstad | with 1 comment(s)
Filed under:
web deployment project vs2005 (exit code 1)

In our latest build using Visual Studio 2005 Web Deployment Projects, we were seeing the build fail with the following error:  aspnet_merge.exe exited with code 1.  Not the most helpful error text.

The fix is relatively easy, however.  Select Tools --> Options.  Then in the Projects and Solutions branch, select Build and Run.  You'll see a dropdown box for MSBuild Project Build Output Verbosity.  Change this to Diagnostic, and OK.

Then show your build output by selecting the View --> Output option.  Make sure that in the 'Show output from' box, you've selected "Build".  Then just build your project, and wait for the inevitable fail.  You should see something like:

An error occurred when merging assemblies: ILMerge.Merge: ERROR!!: Duplicate type 'OurAssembly.Login' found in assembly 'App_Web_9wlv1iu2'.
C:\Program Files\MSBuild\Microsoft\WebDeployment\v8.0\Microsoft.WebDeployment.targets(574,9): error MSB6006: "aspnet_merge.exe" exited with code 1.
Done executing task "AspNetMerge" -- FAILED
.

Then adjust your class names to eliminate the duplicate class name(s), save and rebuild.

NCAA Live Video feeds

Not that I would EVER do this, but if you check out http://www.ncaasports.com/, all games are available to watch for free via streaming video.  i signed up as a VIP, and its pretty great...

Tech wise, the video looks really good for a free service, and the audio is fine.  you can even hear the announcers setting up and discussing things before the game...they also have a hilarious "boss button" that loads up a dummy Excel spreadsheet.  :-)

now get back to work, minions.

Posted: Mar 16 2006, 11:32 AM by sholstad | with no comments
Filed under: ,
Applying Complexity Theory to Software

I just finished reading Emergence, written by Steven Johnson, which was recommended to me by Jeff Smith. I'd suggest this book to anyone who is looking to break out of the daily software development grind mentality, and wants to take a broader view of what is beginning to occur within the software industry.  Johnson examines in-depth the history and growth of complexity theory, the studying of bottom-up systems and how they develop without authoritative figures.  He writes some very interesting sections, which as a whole do a great job of linking the behaviors of social insects, urban communities, neurons and software development.

Johnson doesn't focus on the detailed inner-workings of software, but this book contains some really clever methods of problem solving that may lead you to new thoughts on your next project, and just might change how you think about everyone standing next to you on the El.

Some of his ideas tie very closely with Ray Kurzweil's thoughts on innovation via natural selection; here's a quick snippet:

But that control paradigm is slowly giving way to a more oblique form of programming: software that you "grow" instead of engineer, software that learns to solve problems autonomously, the way Oliver Selfridge envisioned with his Pandemonium model.  The new paradigm borrows heavily from the playbook of natural selection, breeding new programs out of a varied gene pool.  The first few decades of software development were essentially creationist in philosophy -- an almighty power that wills the program into being.  But the next generation is profoundly Darwinian.

Much of Johnson's writing refers to a simple software simulation of slime mold, which has since evolved into StarLogo, an educational program for children.  You can download it here.

ASP.NET 2.0 Web Deployment Projects Beta V2 Preview

The ASP.NET 2.0 Web Deployment Projects newest Beta has been released, and is available from the link below.  This Visual Studio Add-in provides a feature-rich user interface for enhancing your asp.net website.  We've started to use this tool for some of our client projects, and its quickly becoming a valuable tool for me:

Web Deployment Projects Beta V2 Preview

One useful feature for us is the ability to specify and configure separate build scenarios, including the omniscient Debug and Release.  You are also able to create your own custom scenarios, such as PreProduction, Staging, Testing, etc.  It is easy to specify which projects to build for each: for example, we only build Setup, Custom Build Action and Web Deployment projects for non-debug builds, which saves a lot of compile time.

My favorite option?  The ability to specify sections of the web.config to be replaced, depending on what build scenario is running, either by specifying a local .config file containing only the build-specific element, or an external config file.  Imagine, no more tweaking the local web config file after deploying to your staging server..its all handled during the build!

The link also directs you to two excellent documents that cover every feature of the web deployment Add-in, and suggest examples of when you would apply certain features.  A simple tool, and clear documentation...sounds good to me.

 

Scott Guthrie posted updates about this tool here.

Capture Master Page Events in Content Pages - ASP.NET 2.0

Using Delegates with Master Page Events:

For newer developers, using events and delegates can sometime seem pretty intimidating.  This article is aimed to give a very simple example of using events, delegates, public properties and subscribing forms to capture events from one form to the next.

The problem:  A challenge developers may have using ASP.NET 2.0's master pages and content pages is the ability to notify content pages that something has happened in the master page that may be of interest inside the content page.  For this example, let's assume our master page holds a list of buttons, and your content page needs to be notified that a new item is selected.  If you tried to assign the menu value to a public property and then check this value in the Page_Load event of the content page, you'd be dissapointed by the results.  Why?  The Page Load of the content page will fire before the Master Page's Button Click event, so the public property won't be changed yet.  For new developers, this is the point you curse the new technology and start wondering if your local pub is hiring bartenders.  Don't despair, you've got this handled:

The solution:  To solve this, we'll create a delegate.  Add this outside of the code behind class to expose it to the content forms.  Think of a delegate as a notification system that is avaiable for all to use.  Let's think of this as the Ding! download from Southwest Airlines. 

public delegate void MasterPageMenuClickHandler(object sender, System.EventArgs e);
We'll also create a public event we'll use to reference this button click event (this is inside the code behind class):
public event MasterPageMenuClickHandler MenuButton;

When the Master Page's button is clicked, its regular click event fires.  Inside this event, the delegate is called to tell any subscribing entities that something great has happened, and they should react.  I like to think of this action as the Southwest Airlines adding a new flight that should be broadcast to the Ding! users.  Here's how our master page is set up: 

<%@ Master Language="C#" AutoEventWireup="true" CodeFile="MasterPage.master.cs" Inherits="MasterPage" %>

<!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></title>
    
<link href="StyleSheet.css" rel="stylesheet" type="text/css" />
</
head>
<body>
    
<form id="form1" runat="server">
    
<div id="wrapper">
        
<div id="header">
            Header Area
        
</div>
        
<div id="menuArea">
            
<asp:Button ID="btnMenu1" runat="server" Text="Menu 1" OnClick="btnMenu1_Click" />
            <
asp:Button ID="btnMenu2" runat="server" Text="Menu 2" OnClick="btnMenu2_Click" />
        </
div>
        
<div id="mainContent">
            
<asp:contentplaceholder id="ContentPlaceHolder1" runat="server">
            
</asp:contentplaceholder>
        
</div>
        
<div id="footer">
            Footer Area
        
</div>
    
</div>
    
</form>
</body>
</html>

And the code behind class for the Master Page:

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

#region Public Delegates

// Expose delegates for Master Page Events
public delegate void MasterPageMenuClickHandler(object sender, System.EventArgs e);

#endregion Public Delegates

public partial class MasterPage : System.Web.UI.MasterPage
{
    #region Public Properties

    private string _currentButton;

    public string CurrentButton
    {
        get { return _currentButton; }
        set { _currentButton = value; }
    }
    
    #endregion Public Properties

    #region Public Events

    public event MasterPageMenuClickHandler MenuButton;

    #endregion Public Events

    #region Page Events

    /// <summary>
    /// Handles Page Load Event
    /// 
</summary>
    /// 
<param name="sender"></param>
    /// 
<param name="e"></param>
    protected void Page_Load(object sender, EventArgs e)
    {
    }

    /// 
<summary>
    /// Handles Button 1 Click Event
    /// 
</summary>
    /// 
<param name="sender"></param>
    /// 
<param name="e"></param>
    protected void btnMenu1_Click(object sender, EventArgs e)
    {
        // Assign value to public property
        _currentButton = "One";

        // Fire event to existing delegates
        OnMenuButton(e);
    }
    
    /// 
<summary>
    /// Handles Button 2 Click Event
    /// 
</summary>
    /// 
<param name="sender"></param>
    /// 
<param name="e"></param>
    protected void btnMenu2_Click(object sender, EventArgs e)
    {
        // Assign value to public property
        _currentButton = "Two";

        // Fire event to existing delegates
        OnMenuButton(e);
    }

    #endregion Page Events

    #region Virtual Methods

    /// 
<summary>
    /// Invokes subscribed delegates to menu click event.
    /// 
</summary>
    /// 
<param name="e">Click Event arguments</param>
    protected virtual void OnMenuButton(EventArgs e)
    {
        if (MenuButton != null)
        {
            //Invokes the delegates.
            MenuButton(this, e);
        }
    }

    #endregion Virtual Methods

}

Now, subscribing to this delegate is easy.  In the Page Load of the content page, we simply add an event handler to the public event you created in the master page:

Master.MenuButton +=new MasterPageMenuClickHandler(Master_MenuButton);
One important item to note: to reference Master in this fashion, you'll have to add a MasterType directive to the top of the content page's aspx page.
<%@ MasterType virtualPath="~/MasterPage.master"%>

To complete our airline thought, this is similar to your sister downloading the Ding! software onto your machine. 

So here's the process:

A new flight is made available (Master Page button click)
The Ding! service is told about the new item (Our delegate is called by the button click event)
The service tells your computer's Ding! client to show the flight (The subscriber is notified)
You book a flight to Norway (Your form handles the event and gets new value from master page's public property.

Delegates are so useful because they allow a class to notify others of an event, without being tied in any way to the subscribing forms.  Here's the default.aspx content page code behind:

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class _Default : System.Web.UI.Page
{
    /// <summary>
    /// Handles Page Load Event
    /// 
</summary>
    /// 
<param name="sender"></param>
    /// 
<param name="e"></param>
    protected void Page_Load(object sender, EventArgs e)
    {
        Master.MenuButton +=new MasterPageMenuClickHandler(Master_MenuButton);
    }

    /// 
<summary>
    /// Reacts to Master Page menu click event
    /// 
</summary>
    /// 
<param name="sender"></param>
    /// 
<param name="e"></param>
    void Master_MenuButton(object sender, EventArgs e)
    {
        lblOutput.Text = string.Format("Button {0} was pressed", Master.CurrentButton.ToString());
    }
}


Pretty simple explanation, I hope. Sometimes it just takes a basic example to get you thinking about a process correctly...hopefully this will push you towards answering the issue that brought you here. You can download my simple example here. If you work for Southwest, I do accept PayPal <g>

-steve

Here are some other articles that may help you out:
MSDN events
MSDN 2 events
newsgroup discussion

Hey, your ringtone sucks. Yes, yours.

Here's my favorite website of the week: http://mobile17.com

After creating a free account and specifying your phone model and provider, Mobile 17 allows you to upload any mp3 you like, specify the start time & duration, and they will create and send you your new ringtone.  Did it work for me?  No, but my LG 6000 is from somewhere in the Cell Phone Mesozoic era (2004). 

They also offer graphics and animation work, and delivery methods differ depending on your phone & provider.  Its time for me to upgrade, and then you'll all be rocking out to my official theme song...The Rowdies.

3/23/07 Update: I've switched to the Samsung-t629, and this site works really well for me.  Enjoy

Nested Master Pages...are you sure?

I came across a pretty simple issue this week that a lot of developers tend to over-engineer.  Many folks are using nested master pages or multiple, separate master pages to manipulate their asp.net 2.0 web app layouts.  We were developing a login screen and welcome page (header, footer, one content column), leading to the meat of the app, with a more complex layout (header, top nav bar, side nav bar, content area, footer).  These all needed to be branded using a common theme.  Master Pages, baby!  Ah, but what about handling the differing layouts?

Nested master pages (to contain our nav bars) open a can of worms if you are developing using the Forms Designer of Visual Studio 2005; content forms inside of nested master pages will work beautifully in Source View or runtime, but cannot be displayed using the Designer view, so we've lost a nice chunk of .Net functionality.  There are some ways to override this and force the form to show in designer, but this article is encouraging simplicity in function, not workarounds.

So just maintain two Master Pages, right?  But that exposes an annoying, bug-probable architecture: if a change is made to one master page, but is forgotten in the second, we've lost some of the global branding of the app.  Plus, this just FEELS goofy, doesn't it?

I'm all for using either of these models if the situation presents itself, but our very common example, a branded login and entry page show how to save yourself from maintaining nested or multiple master pages: overriding the ContentPlaceHolder controls.

<body>
    
<form id="form1" runat="server">
    
    
<div id="wrap">
        
<div id="header">
            My Header Content
        
</div>
        
        
<asp:ContentPlaceHolder ID="NavbarPlaceHolder1" runat="server">
           Upper Navigation Section
           
<!-- This will be overridden -->
        
</asp:ContentPlaceHolder>
        
        
<asp:ContentPlaceHolder ID="SidebarPlaceHolder1" runat="server">
         Side Navigation Section
           
<!-- This will be overridden -->
        
</asp:ContentPlaceHolder>
     
        
<div id="main">
         
<asp:ContentPlaceHolder ID="MainContentPlaceHolder1" runat="server">
            Main Content
           
</asp:ContentPlaceHolder>
        
</div>
    
        
<div id="footer">
           
<asp:ContentPlaceHolder ID="FooterPlaceHolder1" runat="server">
            Footer Content
           
</asp:ContentPlaceHolder>
      
</div>
   
</div>
   
</form>

</body>

In the master page's ContentPlaceHolders, I would insert content and/or web user controls to format the website, including nav bar controls inside of these ContentPlaceHolders.  Then when we create content pages for the login and entry pages (the ones with no nav bars), and simply include blank ContentPlaceHolder references for the sections we want to hide, voila, they are hidden.  As the Southsiders say, "HE GONE".  Here's my fully branded login page, with no unwanted nav bars:

<asp:Content ID="ContentMain" ContentPlaceHolderID="MainContentPlaceHolder1" Runat="Server">
    
<div id="LoginWrapper">
        
<uc1:loginControl ID="myLoginControl" runat="server" EnableTheming="True" />
    </
div>
</asp:Content>
<asp:Content ID="Sidebar" ContentPlaceHolderID="SidebarPlaceHolder1" runat="server">
</asp:Content>
<asp:Content ID="TopNavbar" ContentPlaceHolderID="NavbarPlaceHolder1" runat="server">
</asp:Content>
When you create content pages that require the nav bars, simply do not override the ContentPlaceHolder, and the default content you added to the Master Page inside the nav bar ContentPlaceHolders will shine on through.