29 November 2007

ASP .NET 2.0 User Controls

I'm struggling to find a good use for User Controls.

All I wanted to do was wrap some standard web controls (like a login box) in a pretty container. .NET's default theming is insufficient for this, as it allows you to theme certain properties, but doesn't allow you to customize the control to any large degree. For instance, what I wanted to do was create a pretty table-based box, which is about 19 lines of normal HTML/ASP:


<table class="prettyBox" cellpadding="0" cellspacing="0" border="0">
<tr>
<td class="nw"><br /></td>
<th class="n"><asp:Label ID="title" runat="server" Text="Label"></asp:Label></th>
<td class="ne"><br /></td>
</tr>
<tr>
<td class="w"><br /></td>
<td class="contents">
<asp:PlaceHolder ID="content" runat="server"></asp:PlaceHolder>
</td>
<td class="e"><br /></td>
</tr>
<tr>
<td class="sw"><span></span></td>
<td class="s"><span></span></td>
<td class="se"><span></span></td>
</tr>
</table>


And be able to specify them like so:


<uc:prettyBox ID="pb1" runat="server" Title="Log In">
<asp:Login ID="login1" runat="server"></asp:LoginControl>
</uc:prettyBox>


or even:


<uc:prettyBox ID="pb1" runat="server" Title="Log In">
<ContentTemplate>
<asp:Login ID="login1" runat="server"></asp:LoginControl>
</ContentTemplate>
</uc:prettyBox>


I was able to get the latter to work to a very limited degree, but it had enough limits that it wouldn't work for me.

First, I looked at a templated control from MSDN. Unfortunately, Microsoft's idea of a templated user control revolves more around the data than the UI, so this example is no help.

Another way is found here, and it correctly renders the controls inside the PlaceHolder, but in VS 2005, the designer refuses to keep tabs on any controls inside my user control, so without some manual accounting on my part (i.e. declaring the controls as page variables manually), I lose programmatic access to any controls inside the user control, which is unacceptable.

I found that I could user Mr. Seder's code and make the code designer behave correctly by putting these lines over the class declaration of the user control:


[Designer("ContainerControlDesigner")]
[ParseChildren(false)]


But this caused the ContentTemplate to be completely ignored, so all the controls inside my user control would render after the pretty box rather than inside it's PlaceHolder.

The closest working thing I found was this, but that was a lot more hassle than I wanted just to save myself 15-17 lines of code for each box, and all the controls were created dynamically. It's essentially a server control, which defeats the whole point of a user control that you can see more easily from a visual design standpoint.

I find it very frustrating that I can't make a simple user control that wraps HTML around other controls in ASP .NET 2.0. Probably what I'll end up resorting to is making two user controls, one called prettyBoxStart with a title attribute, and one called prettyBoxEnd, both of them being unary tags:


<uc:prettyBoxStart ID="pbs1" runat="server" Title="Log In" />
<asp:Login ID="login1" runat="server"></asp:LoginControl>
<uc:prettyBoxEnd ID="pbe1" runat="server />


It's pretty lame, and it's barely better than an include, but at least it works, unlike all that user control junk.

26 November 2007

Leopard Tricks and Changes

I've installed Leopard a few times now. (2 home machines and 1 work machine twice). Here are some tips from my experience.

P.S. ps is different

[Edit: As of 10.5.1 or 10.5.2, they changed it back to the BSD style command-line arguments.]
Those of you who do linux system admin probably know the ps command. In Tiger, the ps command used BSD syntax (e.g. ps -aux to get all processes, with -e not working), but in Leopard, it seems that the Linux syntax is now favored (e.g. ps -ef to get all processes). The -u flag of ps no longer works and will give a warning.

Build a New Firewall

When I was restoring my laptop, one of the things that did not translate over (probably because it didn't translate from the upgrade) was my firewall. I had to reconfigure the firewall in Leopard. Fortunately, I only had one custom entry, but still...

Restoring From an Unsupported Drive

You may or may not have seen the nice little command that lets Time Machine backup to SMB shares:

defaults write com.apple.systempreferences TMShowUnsupportedNetworkVolumes 1

Well, one of the things that was sketchy about the whole thing (aside from backing up over wireless) was how you're going to restore that backup. I did this and I'll tell you how.

Note: I used the User Migration Assistant, not the Leopard DVD to restore the backup. I played at using the DVD, but couldn't get the defaults write command to work (read-only filesystem of the DVD, I guess), so I figured it was pointless. However, I didn't actually try to mount_smb the filesystem, hoping that Time Machine would already be able see it.

Assumptions:
You used the defaults write command to allow Time Machine to backup to unsupported network drives (e.g. SMB share).
You successfully made a recent backup to the SMB share.

Firstly, you need to do a fresh install of Leopard on the target machine. When you get to the point where it asks you for a username, make sure the new username is different from the other usernames on the old system. I'd do something like tmpadmin (Temp Admin).

Secondly, log in and run the defaults write command to get Time Machine cooperative.

Thirdly, mount the SMB share you want to restore from and double-click the .sparsebundle inside the SMB share to mount it. Then start the User Migration Assistant (under Applications -> Utilities). Select the option to use a Time Machine backup. It may take it a while to pop up the SMB share as an option. Afterwards, select what you want to restore. I selected everything I could check.

Lastly, log out and back in as your normal user (assuming it's an Admin account also). Then delete the temporary account, so you don't have an extra admin account floating around.

I was actually really impressed with this. It even restored a custom /etc/hosts.allow that I created!