Thursday, November 10, 2005
Chicago .Net Launch
I just got back from the Chicago .Net Launch, and it was very impressive. It looks like Microsoft is releasing new products for the entire enterprise spectrum. I'm especially interested in the new Visual Studio and Team System that finally makes it easy to build good development process, and the new features of ASP.Net. I also had some great experiences with the ask-the-experts. The Microsoft guys were on as usual, but the non-Microsoft experts were great too. In particular, Jon Henning of DotNetNuke nailed a bunch of my ASP questions. I also stopped at maybe 50 different vendor booths to see every kind of tool and service in the .Net ecosphere. A good day all around.
Tuesday, November 8, 2005
Making backups with the free RoboCopy
I had gotten an external harddrive to backup my laptop, but now I needed a way to copy only changed files. For example, if I have 5GB of files to backup, but perhaps only 10-100MB of new files each time I do the backup, for performance reasons I only want to copy the new stuff. Initially I thought "oh well, I'll just write my own program to do this", but then I realize that this is such a common task that there has to be free stuff out there (principle: don't reinvent the wheel). Someone pointed me to Robocopy, which you can download for free, along with 50+ other tools, as part of the Windows Server 2003 Resource Kit Tools.
Robocopy, for "Robust File Copy Utility ", is a command line tool for copying files from one location to another. It has all the switched that you'd expect: only copy changed files, ignore hidden files, number of times to retry copy a file if there are errors (such as a process locks the file and you can't copy it). It's a convenient thing. I created a batch script to do my master backup:
|
I stored the target drive as an environmental variable, and then used the following options:
Switch | Purpose |
/S | Copy Subdirectories, but not empty ones. |
/R:2 | Number of Retries on failed copies: default 1 million. |
/W:10 | Wait time between retries: default is 30 seconds. |
/XA:H | Don't copy hidden files |
There's tons of other switches to configure.
It's quick, yet extremely helpful if your main hard drive crashes.
Tuesday, November 1, 2005
Reminders for Text Editor Settings
Developers use Text ASCII files for tons of things - source code, Xml, html pages, etc... There are tons of different editors for these different kinds of files (Visual Studio, XmlSpy, FrontPage, NotePad, etc...). Given that multiple developers are working on the same files and storing them in source control, there are two potential options that should be consistent between your text editors:
- Make sure they have the same tab settings (such as a tab = 4 spaces)
- Make sure they use the same line break character (such as CR & LF).
For example, if you have XmlSpy use regular tabs, but Visual Studio use tabs=4 spaces, then when the same file is edited in both, it may get totally reformatted. This can cause merge problems. However if they both have the same tab and line break settings, then they won't be reformatted differently.
Most tools have these settings stored under something like Tools > Options. It's a quick thing to check, but an annoying thing if it goes unchecked.
Monday, October 31, 2005
HtmlControls vs. WebControls
Plain Html provides form controls via the tag. These are standard controls like textBoxes, dropdowns, and radiobuttons. ASP.Net provides its own version of these controls. Ultimately the ASP.Net version gets rendered as a html. For development you can use either the WebControls or the normal html controls run as server controls. The table below offers some comparisons:
WebControl | HtmlControl runat=server | |
Description | The ASP.Net controls residing in System.Web.UI.WebControls | Normal html controls that are run at the server. These reside in System.Web.UI.HtmlControls. Setting a HtmLControl to be runat=server does not automatically make it an ASP.Net webControl. |
Pro |
|
|
Con |
|
|
The Pros and Cons mean that they each have scenarios where one is better than the other. For cases like textBox and dropdown where both can provide the same control: HtmlControls are good for high performance apps because you use only the functionality that you need, WebControls are good for rapid development because it automatically gives you more stuff (which then must be paid for with performance).
Thursday, October 27, 2005
Using a single html file for easy management
Normally you want to split your html objects (like styles, scripts, and data) into separate files to make things more reusable. However sometimes when you're creating an internal developer report (for status, confirmation, quick info, etc...), it's easier to give the user a single html file than a whole collection of files. For example, suppose you're making an internal WinForms tool that assists with some development task, and then generates an Html status report. As a single file, it's easier to mail to others or copy into different directories,.
An html page can have several components, each as separate, physical files:
- The main html page itself
- A style sheet
- External JavaScripts
- Inline frames
- Images
- An Xml data source
We can embed both the style sheet and JavaScript into the head of the main html file itself:
|
We can imitate some features of inline frames via CSS by scrolling inline tables.
If you're already automatically generating the report, then you've already essentially split data from presentation and therefore you can also hardcode the data directly into the Html itself.
That leaves us with Images - which I'm not sure of any way to embed images into an Html file.
However all in all, having the option of putting your styles, scripts, inline frames, and data all into a single file may make it easier to manange for internal reports.
Sunday, October 23, 2005
CodeSmith CodeGeneration: Super XSLT
It's very common to have an XML data file, and then based on that to generate something else. Several years ago EXtensible Stylesheet Language Transformation (XSLT) was developed to handle this. The intent is that given an initial file, XSLT lets you program a template to transform that file into something else. For example, you could store just the raw data in an Xml file, and then have an XSLT template transform that into an html file. This new file is usually bigger and more redundant because it's doing something with the data, like adding extra html to format and present it. Another example would be storing base data in an Xml config file, and then transforming it to a lengthy SQL script.
The problem is that XSLT requires a entirely new skillset, isn't as powerful as a full-fledged language (like C#), and lacks the supporting development tools and IDE that make writing and debugging easier. You could use C# and the System.Xml namespace to manually transform the file, but that's tedious.
Another solution is to use a code-generation tool like CodeSmith. CodeSmith can take an Xml document, and given its XSD Schema, create a strongly typed object (which includes intellisense and collection capabilities). You can program a template in the CodeSmith IDE using C#. It's essentially like Super XSLT. By letting you use a language that you already know (either C# or VB), creating the strongly typed object, and using a standard IDE with debugging, using CodeSmith for batch (i.e. compile time) xml transformations can be a real time saver. It's also probably much easier for other developers to read and maintain a C#-based template than an XSLT one.
Tuesday, October 18, 2005
Validation Tips for Validators
ASP.Net provides a convenient, pre-built validation system. It consists of individual validation controls (like required fields), custom validators, potentially your own controls derived from BaseValidator, and a summary control to tie it all together
Sometimes we want to force, or bypass, validation on the client. We can do this by calling ASP.Net's own auto-generated functions. Drag a Required Validator onto a WebForm, run it, view the page source, and you'll see some javascript auto-generated by ASP.Net. This includes both a Page_ClientValidate and __doPostBack function.
Goal | Explanation | How to do it |
Force validation on the client | Be able to check as much at the client before posting back. | call Page_ClientValidate() |
Bypass client validation checks | Be able to have certain controls bypass validation checks. For example you may two unrelated sections on a page, and you'll want to click a "calculate" or "search" button on the first section without triggering the unrelated validators on the other section. | call postBack: __doPostBack('','') |
Also keep in mind as you develop your validation system:
- Validators (including custom) don't fire if their ControlToValidate fields are empty (except for RequiredValidator itself).
- Recall that disabled html fields do not persist their value to the server. This may throw off validators on fields that the user can disable at run time.
- You can debug you client side validators, as they are just JavaScript.
ASP.Net provides custom validators. These are great for fine-tuning your validation. Some tips to keep in mind:
- You can embed extra attributes in the validator's innerHtml, and then reference them in the client & server functions. This is useful to make validators reusable (control independent).
- You can omit the controlToValidate property to ensure that validation only fires on postback as opposed to when focus leaves that individual control. This is very useful when validating groups of controls.
- You can use the methods in WebUIValidation.js to access and compare values.
- You need both client and server validation functions.
Here's a sample custom validator:
Client Code - Validator Html:
|
Here we added the MaxLength attribute. We can reference it in both the client and server validation functions.
Client Code - JavaScript validation function:
|
Server Code - validation function:
protected void ValidateMaxLength (object source, ServerValidateEventArgs value) { try { int intMaxLength = Convert.ToInt32( ((System.Web.UI.WebControls.CustomValidator)source ).Attributes["MaxLength"] ); if (value.Value.Length > intMaxLength) value.IsValid = false; else value.IsValid = true; } catch { value.IsValid = false; } } |