Copy/paste internet code kills. Runtime comments on .net development, SharePoint WCM, and software engineering
Tuesday, 26 June 2007
Closing Tag Identifier
For example:
<div id="myTag">
</div> <!-- end myTag -->
This is also sometimes helpful with C-like languages that use braces to delimit blocks of code.
Although modern development tools highlight closing tags and braces, HTML code in particular isn't always read within one of these tools (View-->Source in IE opens the source code in Notepad, for instance).
To assist, I think it would be helpful to have the option of attributing a closing tag with the same id used by the opening tag:
<div id="myTag">
</div id="myTag">
Our fancy editors would keep the opening/closing ids in sync and browsers could safely ignore the additional attribute.
In practice, this works quite nicely with the caveat that a page built like this is invalid.
Monday, 25 June 2007
Thursday, 21 June 2007
Must-Have Web Development Tools
- IEDevToolbar (like FF's Web Developer toolbar for IE)
http://www.microsoft.com/downloads/details.aspx?FamilyID=E59C3964-672D-4511-BB3E-2D5E1DB91038&displaylang=en - Fiddler (a reverse HTTP proxy, inspect headers, view traffic)
http://www.fiddlertool.com/ - Firebug (inspect and modify web pages, debug Javascript, view network stats)
http://www.getfirebug.com/ - Firefox Live HTTP Headers (view HTTP headers)
http://livehttpheaders.mozdev.org/ - Firefox Modify Headers (change your IP address, among other things)
http://modifyheaders.mozdev.org/ - Firefox User Agent Switcher (change your browser user agent string)
http://chrispederick.com/work/user-agent-switcher/ - Firefox Web Developer Toolbar (inspect and dynamically modify web pages)
http://chrispederick.com/work/web-developer/ - .NET Reflector (inspect .NET assemblies)
http://www.aisto.com/roeder/dotnet/ - .NET Resourcer (inspect and edit resource files)
http://www.aisto.com/roeder/dotnet/ - Page Saver (save an entire web page as an image)
http://pearlcrescent.com/products/pagesaver/ - SysInternals (Inspect everything Windows with Filemon, Regmon, PsTools)
http://www.microsoft.com/technet/sysinternals/default.mspx - The Regulator (edit and test regular expressions)
http://regulator.sourceforge.net/ - WinMerge (compare and merge files and directories)
http://winmerge.org/ - Wireshark (sniff traffic and inspect the lot across various protocols)
http://www.wireshark.org - YSlow (determine why web pages are slow to load)
http://developer.yahoo.com/yslow/
ASP.NET Fragment Caching in MOSS
Things look like this:
Masterpage:
<%@ Register tagprefix="CustomControls" tagName="Container" src="~/UserControls/Container.ascx" %>
<%@ Register TagPrefix="CustomControls" TagName="ToCache" Src="~/UserControls/ToCache.ascx" %>
<CustomControls:Container id="container" runat="server"/>
<CustomControls:ToCache ID="toCache" runat="server"/>
Container.ascx:
<%@ Register tagprefix="CustomControls" tagName="ToCache" src="~/UserControls/ToCache.ascx" %>
<CustomControls:ToCache id="toCache" runat="server" />
The resulting HTML looks like this:
<body>
<div id=”container”>
<div id=”toCache”>... </div> // This caches
</div>
<div id=”toCache”>... </div> // This won’t cache
</body>
The ToCache.ascx user control sets a simple @OutputCache directive in the markup and I can't see anything that would limit output caching in the master page, the hosting .aspx page, or the web.config.
I haven't ripped this apart and tried it in a clean site but I'm definitely experiencing this behaviour within the context of the wa.com development environment. I know MOSS controls (and somehow enhances) output caching but I have yet to look into how this works--as far as I know, I'm using the default output caching configuration.
Update: I wonder if this has anything to do with the control being hosted in a master page instead of an aspx page layout. Slim chance...
Disabling the "Reply to All" email button
Surely there's a Dilbert strip for this?
From: xxx
Sent: Thursday, 21 June 2007 10:25 AM
To: All Staff
Subject: Disabling the "Reply to All" email button
The CEO has requested that Corporate IT disable the “Reply to All” button for all staff in order to assist with email and time management.
We will trial this for a few weeks and then I will seek feedback on how effective this has been and request executive directors to bring the feedback to the executive management team for discussion.
The process will happen progressively over the next few days.
Thanks
xxx
Executive Director
Wednesday, 20 June 2007
Units of Time
One millionth of a second = 1 microsecond (µs)
One billionths of a second = 1 nanosecond (ns)
See http://www.wilsonmar.com/1clocks.htm for great discussion about time in a networked world.
Monday, 18 June 2007
Visual Studio 2005 Debugger Won't Break
Here's the scenario:
- A standard user control with a code-behind file is hosted in an insignificant ASPX page;
- The user control code-behind is doing some work to render the control and also has a handler method subscribing to a button click event;
- The relevant assemblies are built in debug mode and are deployed to a separate development server along with the associated markup files;
- The assemblies on the server are the same version as those on the development workstation;
- The application is configured as it should be in IIS and the debug attribute on the web.config's compilation element is set true;
- The VS 2005 remote debugger is installed and running on the dev server;
- The VS 2005 "client" is attached to the remote server's ASP.NET worker process (w3wp.exe in this case);
- Two breakpoints are set on the user control code: one on Page_Load and one on the button click handler;
- Browsing to the host page doesn't cause the debugger to break (except intermittently, sometimes following an iisreset)...
Here's the problem:
The user control in question had an OutputCache directive set to cache the control for sixty minutes. Removing this little devil resulted in a slap of the forehead and allowed the debugger to break as expected.
The OutputCache directive prevents the control being added to the control tree of the hosting page at runtime; ASP.NET loads an existing version from the cache instead of executing the control code.
...kind of a silly problem since the debugger gives you no inidication the control is loading from the cache but it's all too easy to forget about this sort of thing!!! The golden rule I usually try to apply is to hold off on performance tuning until the very end of the development/testing process and this should generally include large-scale caching. Obviously this doesn't apply in a maintenance situation.
- Double-check the deploy location of your assembly; if it's in the GAC you can deploy to the bin directory until the cows come home but ASP.NET will continually load the assembly from the GAC. Either remove the GAC'd assembly or deploy to the GAC (you can also deploy PDB files to the GAC but you need to drop them under gac_msil using the command line).
- Once you've attached the debugger, bring up the Modules window (Debug -> Windows -> Modules); locate your assembly and verify whether symbols have been loaded and the location where the assembly was loaded.]
Monday, 11 June 2007
Top Ten of Programming Advice NOT to follow
http://www.chrylers.com/top-ten-of-programming-advice-to-not-follow
Friday, 1 June 2007
Everything you always wanted to know about Javascript but were too afraid to ask
http://odetocode.com/Articles/473.aspx
The article is reasonably short, very concise and explains a lot about the language itself. Better still, the article is targeted at .NET C# developers who know more about classes and method than prototypes. The examples are great as well.
Looks like Javascript isn’t going away any time soon so I’d suggest this article as a great intro to the rest of your life as a Javascript developer ;-)
Thursday, 31 May 2007
Localizing Web Parts, Custom Controls, and Class Libraries
Localization is a good thing because it:
- Allows you to refactor hard-coded strings for labels, menus, and so on out of your code and into .resx files;
- Enables your application to display a user interface relevant to users of different languages.
Localization won't translate your interface for you--that still has to be done manually.
Visual Studio 2005 now takes care of all the hard work needed to develop a fully localized app in no time at all. Firstly, it provides a convenient designer for creating resource files through which you can add strings, images, icons, and text/script files. Secondly, any .resx file added to your project are automatically compiled to a .resources file and linked to your main assembly. Finally, a resource file wrapper class is generated automatically, granting you strongly-typed access to the contents of your resource files. What more could you ask for?!?Working with resources is really straight forward if you're writing user controls or web pages (apparently WinForms are just as straightforward but I don't know much about WinForms) because both the UserControl class and Page class both derive from System.Web.UI.TemplateControl. TemplateControl exposes the protected GetGlobalResourceObject ( ) and GetLocalResourceObject ( ) methods. When a user control or web page has a resource file available to it, you also get strongly-typed access to the file like this:
Resources.MyResourceFile.MyKey;
(where 'Resources' is some weird namespace that only comes to life when you've got .resx files in your project)
On the other hand, if you're writing web parts, custom controls, or class libraries, you're probably not deriving from TemplateControl (especially in the web part case where you class inherits WebPart). You can still add resource files to you project and use a ResourceManager to pull out the stuff you need but there's an easier way.
- Create a new class library project; name it MyCustomWebParts or whatever you like. The name you give your project will also become the name of the assembly and be used as the default namespace for any classes you add and any classes added by Visual Studio (this last bit is really important).
- Create a new resource file (Add new item...) named strings.resx in the root of the project (you can also place your resource files in an arbitrarily-named folder but doing so will change how the file is accessed programmatically). Add a new string with a name of labelText and a value of Hello World.
- Create a new class that derives from
System.Web.UI.WebControls.WebParts.WebPart; name it MyWebPart or whatever you like. - Add a CreateChildControls ( ) method to your class and within the method body, instatiate a new Label object and add it too the Controls collection.
- Immediately after the Label is instantiated, set its Text property from the resource file. You do this by referencing [the default namespace for the assembly].[the name of the resource file with no extension].[the resource key name].
- Add or update a globalization element to your web.config file and set both the culture and uiCulture attributes to auto:
<globalization uiculture="auto" culture="auto" />
This works on a regular ASP.NET site but MOSS doesn't automatically assign the browser's current language to the System.Threading.Thread.CurrentThread.CurrentCulture and CurrentUICulture properties so you may wish to do this yourself and forego the above web.config setting. - Build the project and register the web part in a .aspx page--and that's it!
namespace MyCustomWebParts
{
public class MyWebPart : WebPart
{
protected override void CreateChildControls ()
{
Controls.Clear ();
Label label = new Label ();
label.Text = MyCustomWebParts.strings.labelText;
Controls.Add (label);
}
}
}
As mentioned, adding a .resx file to your project prompts Visual Studio to generate a strongly-typed wrapper class for accessing the file; this class is created in the project's default namespace. If your web part or control is the same namespace you don't need to qualify your resource file within the MyCustomWebParts namespace--you can access it directly: strings.labelText. If you've got multiple namespaces in your project (or not) it's probably a good practice to always qualify the resource class name.
If you do drop your .resx files into a folder you'll need to modify the way you reference them:
MyCustomWebParts.MyFolder.strings.labelText;
Either way, IntelliSense will help you out as you go if everything's in the right place.
To tweak performance, you can tell ASP.NET which resources are contained in the default assembly by adding an attribute to your class library's AssemblyInfo file:
[assembly: System.Resources.NeutralResourcesLanguageAttribute ("en")]
And the end result: localized web parts, custom controls, and class libraries. Cool.
