Friday, September 28, 2007

This will be the first in series of posts I'll be writing about creating server controls.  I'll try to share some of what I learned from my research while I prepared for a recent presentation. 

With most software development, there isn't always a simple answer to a question.  This is of course true for creating Composite Controls for ASP.Net 2.0.  One area where this was apparent was the proper way to render a control.  Of the many examples I have found on the web it seems that most people put their rendering code within CreateChildControls() but some override the Render() method.  I'll show examples below.  So which is correct?  You know the answer...It Depends!   My personal preference seems to be outside of the norm but I prefer to include rendering code in the Render() method (as in Option A below) unless there is a compelling reason not to.

My sample CompositeControl will have 2 controls within it:

        private TextBox _textBox = new TextBox();
        private Label _label = new Label();

Option A:

        protected override void CreateChildControls()
        {
            Controls.Clear();
            _textBox.ID = "txtBox1";
            _label.ID = "label1";
            Controls.Add(_textBox);
            Controls.Add(_label);
            base.CreateChildControls();
        }
        protected override void Render(HtmlTextWriter writer)
        {
            EnsureChildControls();
            AddAttributesToRender(writer);
            writer.RenderBeginTag(HtmlTextWriterTag.Div);
            writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "1", false);
            writer.RenderBeginTag(HtmlTextWriterTag.Table);
            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            _label.RenderControl(writer);
            writer.RenderEndTag(); //</td>
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            _textBox.RenderControl(writer);
            writer.RenderEndTag(); //</td>
            writer.RenderEndTag(); //</tr>
            writer.RenderEndTag(); //</table>
            writer.RenderEndTag();
        }

In option A, CreateChildControls is used simple to set properties on the controls and add them to the Controls Collection.  The Render() method takes care of layout.  In particular, I like being able to use the HtmlTextWriterTag enumeration with the RenderBeginTag() method.  By the way, the RenderEndTag() method will "close" whatever tag is next in line to be closed within the nested hierarchy of tags.  Note that the Div tag I render isn't really necessary.  But I want all of my samples to render the same markup, so I put that in.  Use the AddAttribute() method to add attributes to whichever tag is written next after the AddAtttribute() call.  So in this sample, the CellPadding attribute will get written into the table as <table cellpadding="1">.

Option B:

        protected override void CreateChildControls()
        {
            Controls.Clear();
            _textBox.ID = "txtBox1";
            _label.ID = "label1";

            Controls.Add(new LiteralControl("<table cellpadding='1'><tr>"));
            Controls.Add(new LiteralControl("<td>"));
            Controls.Add(_label);
            Controls.Add(new LiteralControl("</td>"));
            Controls.Add(new LiteralControl("<td>"));
            Controls.Add(_textBox);
            Controls.Add(new LiteralControl("</td>"));
            Controls.Add(new LiteralControl("</tr></table>"));
            base.CreateChildControls();
        }

In option B, all of the rendering is done within CreateChildControls().  There is nothing wrong with this method, however, I don't like it as much.  I like my methods to do one thing only.  And since there is a method named Render(), doesn't it make sense to put the render code in it?  Also, within CreateChildControls, you don't get to use the RenderBeginTag() method with the enumerations.  That means more chances for mistakes, in my opinion.  If you are using this method within a CompositeControl, it is not necessary to override Render().  The default implementation of Render() will be called. 

Option C:

        protected override void CreateChildControls()
        {
            Controls.Clear();
            _textBox.ID = "txtBox1";
            _label.ID = "label1";
            
            Table table = new Table();
            table.CellPadding = 1;
            TableRow row1 = new TableRow();
            TableCell cell1 = new TableCell();
            cell1.Controls.Add(_label);
            TableCell cell2 = new TableCell();
            cell2.Controls.Add(_textBox);
            row1.Cells.Add(cell1);
            row1.Cells.Add(cell2);
            table.Rows.Add(row1);

            Controls.Add(table);
            base.CreateChildControls();
        }

Lastly, I put Option C to show what NOT to do (most of the time).  In this case, I have created my Table, Row and Cells as actual controls, not literals.  This is extra overhead and it is not needed because the only purpose for my table is to control layout.  The literal controls in options A and B will render quicker.  However, there are times when you NEED to have your Table, etc, included in the Controls collection.  In those cases, this technique can be used.  Once again, there is no need to override the Render() method with this technique.

Results:

So how does this all render in the browser?  I put this markup into an ASP.Net Page:

    <!--Option A -->
    <cc1:MyControl1 runat="server" ID="mc1" />
    <br />
    ------------------------------------------
    <!--Option B -->
    <cc1:MyControl2 runat="server" ID="mc2" />
    <br />
    ------------------------------------------
    <!--Option C -->
    <cc1:MyControl3 runat="server" ID="mc3" />

In the browser, I used "View Source" and got the following:

        <div id="mc1">
            <table cellpadding="1">
                <tr>
                    <td>
                        <span id="mc1_label1"></span>
                    </td>
                    <td>
                        <input name="mc1$txtBox1" type="text" id="mc1_txtBox1" /></td>
                </tr>
            </table>
        </div>
        <br />
        ------------------------------------------
        <div id="mc2">
            <table cellpadding='1'>
                <tr>
                    <td>
                        <span id="mc2_label1"></span>
                    </td>
                    <td>
                        <input name="mc2$txtBox1" type="text" id="mc2_txtBox1" /></td>
                </tr>
            </table>
        </div>
        <br />
        ------------------------------------------
        <div id="mc3">
            <table cellpadding="1" border="0">
                <tr>
                    <td>
                        <span id="mc3_label1"></span>
                    </td>
                    <td>
                        <input name="mc3$txtBox1" type="text" id="mc3_txtBox1" /></td>
                </tr>
            </table>
        </div>

Looks pretty close, huh?  There was one extra trick I did to make these match up.  First, remember that in Option A, I added an extra <div> tag when I rendered my control.  Without it, my option A control's outer tag would have been <table>.  Either way may work fine in your application.  Second, Options B and C also have the following code included:

        protected override HtmlTextWriterTag TagKey
        {
            get { return HtmlTextWriterTag.Div; }
        }
Without this override, my controls in Options B and C would have an outermost tag of <span> instead of <div>.  Many people prefer to have controls render with <div> tags and this is how to do it!

I hope this information is helpful to you.  Unfortunately, there isn't always a clear answer of which method is best. 

Friday, September 28, 2007 10:34:04 AM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Thursday, September 27, 2007

Diamond Technologies is teaming up with Microsoft to present: Technology Day.

Date: Tuesday ~ October 23, 2007

Time: 1:00 p.m. - 5:00 p.m.

Place: Diamond Headquarters

From the invite...

Do you have questions about IT, Vista™ , or Sharepoint? Would you like to see the latest technology in mobility solutions? Is your company looking for new ways to improve decision-making, productivity, or collaboration? Is your IT team challenged by evolving security threats, rising deployment, support costs, or increasingly complex desktop infrastructures?
As a part of our commitment to deliver quality products and services that help your business succeed, we are offering you the opportunity to participate in Technology Day.

Join us for lunch, participate in a demo or Q & A session, tour the Microsoft Bus and enjoy learning about the exciting new releases from Microsoft:  including Vista™ and Sharepoint.  Network and request a song from WSTW live at lunch.

Click here to get some more information or register to attend.

Thursday, September 27, 2007 12:38:45 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Wednesday, September 26, 2007

If you live in Central Maryland, you should check out CMAP's Code Camp on October 13, 2007

I know Chris has been working hard to put this together.  I'm sure it will be a great event.

Wednesday, September 26, 2007 9:04:15 AM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Monday, September 24, 2007

As of Monday, 10/1, I'm starting a new job for a Web 2.0 startup.  I'm really excited about this great opportunity, I think it will be a big challenge in many ways.  This new job has a very high technology "cool" factor in my book.  For instance, they've been using VS2008 since May!  In addition to ASP.Net, I'll also use LINQ, AJAX, Silverlight and other cool stuff.  The team seems like a really smart group and I'll have a lot of catching up to do. 

Did I mention that the office is 5 miles from my house?  I haven't had that short a commute since I was 22!  For the past 3 years I've been in the car about 50 minutes each way commuting to and from work.  Many days were much longer.  I'm looking forward to getting that time back.  Also, this is much better, environmentally speaking.  This should make my personal carbon footprint much smaller!

I've enjoyed worked at Diamond for the past 3 years.  They've got a great team and I hope to stay in touch with many of them.  Leaving Diamond was not a simple decision but when a good opportunity presents itself, you have to take notice. 

Monday, September 24, 2007 10:09:19 AM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Wednesday, September 19, 2007

I just heard about a cool contest Red Gate is having.  It's called Break The Code prize draw and there is no cost to enter (and no purchase necessary).  The catch is, you need to decipher a code posted on their web site.  How you do that, I have no idea.  I just pass these things along. 

Thanks again to Red Gate for their support of Philly.Net Code Camp.  They provided an iPod for us to raffle, as well as some software.

Wednesday, September 19, 2007 1:22:04 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Tuesday, September 18, 2007

Well, we did it again.  Thanks to the hard work of many people, Philly.Net's Code Camp 2007.2 was a terrific event.  I've already gotten some great feedback from many people about the day.  If you have any comments to add, please email me or comment here on this post.  We take the comments seriously.  Last time it was suggested to afternoon snacks and drinks, we had that this time.  Last time the day was a little too long, this time we shortened it.  Last time people wanted coffee in the morning, this time we provided it.  Our presenters did a great job, it was evident in the evaluations that we collected.  Thanks to everyone who filled those out, the presenters look forward to your comments.

I think my presentation went very well and I've gotten some good feedback from people.  I had a lot of fun presenting.  If you are looking for my code samples, you can find them here.  Also, I'm in the process of putting together a summary/wrap up email.  In that email, I'll include information about Code Camp including links to all of the presenters, just in case you lost their information.

Tuesday, September 18, 2007 12:18:53 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Tuesday, September 11, 2007

Growing up, I had always heard people around me say "Where were you when it happened?"  The it was a variety of different events.  It was usually referring to when JFK was shot or another significant event in our history.  It seemed that each generation had it's own events that brought on this question.  I always thought those conversations were weird.  Why couldn't people just move on?  Why did they feel the need to dwell on that stuff?  What I hadn't realized is how fortunate I was.  My generation was lucky, we didn't really have any events that were so significant that we could never forget. 

Here it is, Sept 11, 2007.  And I can't help myself from asking that very question.  Ever since September 11, 2001, I understand why people ask that question.  It's not just that we can't forget, it is that we don't want to forget.  We shouldn't forget. 

I'm typically not the kind of person that remembers all kinds of details about days in my life.  But 9/11 is completely clear in my head.  I remember waking up in North Carolina, I was there for a lengthy consulting assignment.  I had been having some remote connection problems with my laptop.  I needed to call the desktop support team after 9am and I needed to do it from my apartment so I could test the system.  If it were not for that situation, I would have been at work before it happened.  I had the TV on, I was watching Good Morning America.  After some typical morning stories, Charlie Gibson announced that they were going to a live shot of lower Manhattan, where a plane had hit one of the towers.  Of course, all of the information that Gibson gave out at this point was hearsay.  Maybe it was a commuter plane?  Maybe it was a suicide?  I remember watching that live shot when the second plane hit.  My jaw dropped.  Everything was obvious at that point, this was not an accident.  The newscasters were in just as much shock as I was, just as I'm sure everyone else was that was tuned in.  I immediately called my friend Steve.  He lived in Battery Park City.  Not only was his apartment a few short blocks from what we now call "ground zero" but I knew he took the subway from the World Trade Center each morning.  Luckily, he was already in his office up town and his wife was fine too. I watched the coverage for a while and of course, I saw the towers go down.  There was also the news of flight 93 and the Pentagon as well. The whole situation was surreal.  I was very sad.  I was very confused.  I called my friend/coworker Chris.  He was in the apartment downstairs and I knew he typically went to work late.  He came up for a while and we watched the coverage together.  Eventually I went to work for a few hours, just for a change of scenery.  I couldn't watch the coverage any more.   Everyone was talking about it of course.  So many people were worried for someone they knew who lived or worked in lower Manhattan or the other affected areas.  Having recently lived in Hoboken, NJ (right across the river from Lower Manhattan) I served as source of information for many people in the office who had never visited the area.  My sad mood lasted for a long time, just as it did for many people.  Days later, Chris and I had to drive home to the Philly area because the airports were still closed.  My friend Steve's apartment was a wreck.  His windows had all blown in.  The building had a lot of damage.  He never lived there again.  And of course, many people died or were badly hurt (none that I knew personally).

I'm not sure what is harder to comprehend, each obviously for a different reason - The will of man to execute such a plot against his fellow man,  the loss of life on that day, or the bravery of men and women who risked their own lives to help others?  Tragic events like 9/11 continue to prove the complexity and sadness of life.

With a child of my own on the way now, I really hope future generations never understand why we ask the question "Where were you when it happened?"  They should be so lucky.

Tuesday, September 11, 2007 8:40:18 AM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Monday, September 10, 2007

Sorry gang... Pub Night, scheduled for Tuesday, Sept 11 (originally scheduled for Wed, Sept 12) is now postponed again!

Because it was postponed, there wasn't enough time to ensure a good crowd for tomorrow.  Plus, a lot of us are still working on our presentations for Saturday's Code Camp.

I think it will be next week, probably Wednesday.  But don't put any money on that yet!

Monday, September 10, 2007 1:09:44 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [0]  |  Trackback