OdeToCode IC Logo

Power Phases

Friday, September 9, 2005 by scott

This morning I was holding on to a precious idea and typing furiously into a remote desktop, when bleeeeeeep – the UPS units kick in and the network goes down. Power outage.

Mood: displeased.

After 15 minutes of rummaging, I found the phone book hiding between a book of salsa recipes and the classic “Joy Of Cooking” hardcover edition. The power was still off, so I started a manual search for the phone number of the power company.

Mood: irritated.

I found the number, but realized my landline didn’t work either. I picked up my cell phone and prepared to voice displeasure at the people who manage the local electrons.

Mood: aggravated.

Just before someone came on the line, I started to feel that perhaps I should be happy to have a roof over my head.

Mood: pensive.

I quietly reported the loss of power at my residence, and was told power would be back in an hour. I went for a stroll in the yard. Nice weather this time of year.

Mood: calm.

Themes for Custom Controls in ASP.NET

Friday, September 2, 2005 by scott

Q: How do you skin custom controls and user controls in ASP.NET 2.0?

A: You can use an @ Register directive in the .skin file. Once the control is registered, skinning works just as you'd expect. For instance, the following control:

namespace OdeToCode.WebControls

{

    public class MyCalendar :

          System.Web.UI.WebControls.Calendar

    {

      // ...

    }

}

Can be skinned like so:

<%@ Register TagPrefix="OTC" namespace="OdeToCode.WebControls" %>

 

<OTC:MyCalendar runat="server" BackColor="White" BorderColor="#EFE6F7">

  <SelectedDayStyle BackColor="#41519A" ForeColor="White" />

  <SelectorStyle BackColor="#41519A" />

</OTC:MyCalendar>

The above Register directive assumes your control is defined in App_Code, otherwise you'll need to add the Assembly attribute to specify the assembly. It’s also important to note that a skin defined using <asp:Calendar> will not apply to the MyCalendar control, even though they have an inheritance relationship. The theme algorithm does an exact match on the control’s type.

Colorful ASP.NET Themes

Thursday, September 1, 2005 by scott

The Colorful Web Site Starter Kit on .NET Treats and Tricks is a nice piece of work (via Cindy). On the site you’ll find a find 8 ASP.NET 2.0 Themes you can download and use. The themes not only look nice but have a great design.

For instance, Erika used styles from a CSS file whenever possible. I’ve seen some grumbling that themes and skins in ASP.NET 2.0 are an evil plot to subvert web standards, when actually themes provide a great infrastructure to manage multiple sets of CSS files. Select a theme for a page and the runtime will automatically inject link tags for all of the stylesheets in the chosen theme directory.

There are some server controls that are just not easily styled: WebPartZone, Calendar, GridView, for instance. The colors and other visual properties of these controls are set with a skin file in each theme (see my ASP.NET 2.0 Themes article for more details on themes and skins).

There is also an Images subdirectory for each theme. Images can be tricky with themes, and tricky with master pages, and even trickier with themed pages using a master page.

You never want to use an absolute path to an image in a theme directory. Absolute paths break easily, and you’d have to change them with your own code if you want to switch themes. Always use relative paths. For instance, here is a snippet from the default.css in one of the themes.

td.headerbar

{

    background-image: url(Images/bar.jpg);

    text-align: right;

    height: 24px;

}

When the above reaches the client, the browser will be smart enough to request bar.jpg from the App_Themes/MSN_Blue/Images directory (when MSN_Blue is the selected theme).

What about images you want to vary by theme on a page, or on a master page? We know the runtime will do some URL rebasing for paths in a master page (read near the end of ASP.NET 2.0 Master Pages for more details), but that doesn’t help in rebasing an image’s src attribute from one theme to the next if you have hard coded the full path to an image file in a theme.

The easy solution is the SkinID attribute for server side controls. You can only have one default skin for a control, but multiple skins are available with a skin id. For instance, the colorful web site starter kit uses two image skins, identified by SkinID.

<asp:image runat="server" Imageurl="Images/logo.jpg" skinid="logo" />

<asp:image runat="server" Imageurl="Images/bullet.jpg" skinid="bullet" />

Notice the src uses relative paths. The logo on the master page uses the following:

<asp:Image ID="Image1" runat="server" skinid="logo"/>

With this approach you can switch the logo for a web site just by using a different theme. Sweet.

.NET Is Hard

Wednesday, August 31, 2005 by scott

DonXML and Sahil have been talking about the E-week article “DBAs Bar Door Against Big Bad .Net Wolf”. Both guys have some good insight.

One paragraph in the article struck home with me:

Much of the problem has to do with the fact that .Net is just too hard, Dobson said. "Most IT pro people—I'm talking about the DBAs—did not embrace .Net" when it first came out in 2001, he said.

True, true. Just the other day I was working with a DateTime value in C#, but what I really needed was a string with a plain ol’ U.S. formatted date. After some intense concentration, I typed the following:

string date = someDate.ToShortDateString();

I’m sure many of you have felt that pain. It’s particularly hard with Intellisense always popping up bizzare windows. I couldn’t take the foolishness anymore, so I wrote a T-SQL UDF instead, and used the following: 

SET @date = CONVERT(char,@someDate,131)

I was pretty happy with this version, but during testing I discovered I was getting strange output. It turns out the number 131 tells SQL Server to use Kuwaiti algorithm and the Islamic lunar calendar to produce a date.

Oops!

No problem - I tried 126, 108, 105, and then 6. No luck. Eventually I put in a 101 - and everything worked!! Tee-hee!

I spent the rest of the afternoon etching the T-SQL date format styles into a piece of corkboard using my trusty soldering iron. I'll hang this above my desk to make life even easier.

I won't tell you what happened when I implemented String.Split in T-SQL. I'll leave the wonderful experience as an excercise for the reader.

Something Moved

Monday, August 29, 2005 by scott

I sat down to my desktop this morning and my wrists reminded me I’ve been spending a great deal of time with the mouse and keyboard these last three weeks.

After logging in, I decided it was time for a change.

I stared intently at the taskbar on the bottom of my screen. I began to imagine applications launching, menus opening, commands executing. I could feel the energy start to form around me. I concentrated on synchronizing the patterns in my brain - pouring them into the silicon mind before me. I began to hum the note three steps below a middle c. The aura around me was terrific to behold.

Then it happened.

Something moved!

A window appeared!!!

The window said: “A newer version of MSN Messenger is available”.

Coincidence? I don’t think so.

I believe I just need some more practice….

Crushed

Wednesday, August 24, 2005 by scott

I’m crushed with some heavy duty projects.

The hours fly by like a compressed binary stream, and I’ve had no time to coalesce ideas into a well-formed post.

I do, however, have a collection of random thoughts I can share. You probably can’t tell the difference between this post and all the rest….

Marketing

On Monday I met the new marketing director. After shaking my hand he looks at me and says: “I never lie to potential clients – I always check with engineering first to know what we have”.

I’m going to take up an office collection to ship him this book.

Visual Basic really is the ugly step sister

I have one directory with 30,000 C# files (don’t ask). The Visual Studio “Find In Files” command just can’t cope.

Fortunately, the MSN search toolbar can cope. The .cs extension is already included as a default type to index, all I needed to do was add the right directory as custom folder to index.

The toolbar does not index .vb files by default.

Car Names

What’s up with car names these days? I saw a “Prius” in a parking lot last week and for some reason my first thought was of a prostate exam.

Yesterday I saw an “Armada”. I’m not sure why I’d buy a vehicle that evokes images of ships being set ablaze and battered by cannonballs, but I do wonder if the driver wears a naval cap while cruising.

Now, back to the grindstone.

Unit Testing and Refactoring in VS 2005 Beta 2

Wednesday, August 17, 2005 by scott

I started some new work on a .NET 2.0 project recently and decided to dive headfirst into the unit testing features in 2005. The auto-generated tests seem to have a fundamental flaw and I’d recommend avoiding them (at least in beta 2).

It’s easy to put the cursor on an existing class, right-click and select “Create Tests…”. Visual Studio will generate a boatload of code at this point, including a unit test class with a test method for each method and property on the target class.

The stubbed out test methods are setup to work through an accessor class. If you create an Account class, and use the “Create Tests…” option, Visual Studio creates an AccountAccesor class.

The accessor classes will proxy calls to the real object using reflective techniques, i.e. with an Invoke call. This approach allows you to test protected and private members of a class as if they were public members. The merits of testing non-public members of a class are debatable, but the layer of indirection an accessor adds takes all the fun out of refactoring.

One of the many benefits of the refactor feature is that you can change the name of a method or class and feel confident that the IDE can manage the aftermath. There is no need to do a global search and replace by hand – the IDE takes care of cleaning up.

Let’s say you want to rename your Account class to CAccount because you miss programming in MFC (in which case I suggest you look for professional help). The refactoring will not change the code in your unit tests, because the unit tests are using the accessor class instead of the real class. The instantiation of the accessor would look something like the following (except it’s actually a lot uglier):

_accountAccessor accessor = new _accountAccessor(target);

Of course, the accessor class needs to create a real instance of the Account class to test, but because it creates an instance in a late bound manner. The Account class type is only referenced as a string, like the following (except it’s actually a lot uglier).

protected static PrivateType m_privateType =

    new PrivateType("AssemblyName", "Namespace.Account");

The refactor feature can't make any changes to your unit tests because it doesn't know where you were using the Account class. The next time you run your tests you'll have a pile of exceptions about missing methods and classes.

You can regenerate just the accessor classes, but you'll still have a mess to clean up by hand.

I’m not sure what the generated tests will look like in the RTM versions of Visual Studio 2005 / Team System (or even what versions will support unit testing), but I’m staying away from the auto-generated tests in beta 2.

Something is fundamentally wrong if a testing feature makes refactoring more difficult ... or am I missing something?