September 2004 - Posts

Props to Peter Blum
30 September 04 01:40 PM | Scott Mitchell

Just wanted to give praise to Peter Blum and his ASP.NET server controls over at PeterBlum.com (some free, some for sale). I have used Peter's Date Package on a small personal project about a year ago, which was quite useful. Lately, however, I've been working with a client on a project who has a ton of data entry pages. (For example, one data entry “wizard” spans six Web pages, with each Web page having about 25 form fields for data entry.) In any event, a number of the pages require date entries, so I recommended that my client pick up a copy of Peter's Date Package.

He followed my advice, and we've been using the DateTextBox and MonthYearPicker controls (along with the more advanced validation for date field entries) quite a bit. In fact, I've gone back to several of this client's existing applications and replaced the old TextBox Web controls with the DateTextBox. A big improvement.

Anywho, shortly after buying Peter's Date Package, my client found Peter's Validation and More controls. These controls include a number of professional validation controls missing from ASP.NET 1.x. The true gems from this set of controls are the masked TextBox controls, like the DecimalTextBox, IntegerTextBox, and CurrencyTextBox. These use client-side JavaScript to ensure that the user can't enter offending characters, and can also utilize “spinners” (little up and down arrows) to let the user toggle through the legal values rather than having to type them in directly. I'm using these controls like there's no tomorrow, and the users are really liking the new UI, too, which improves their data entry speed, making them more productive.

I've mentioned before how verbose I tend to be, but my verbosity is nothing compared to Peter's documentation. For the Date Package there's a PDF document with nearly 200 pages of documentation (installation instructions, setup, documentation, examples, etc.). Insane. (Admittedly, I've read about four pages in total - it's pretty easy to figure out how to get the controls to do the simple stuff. There is a lot of added features, though, that I've yet to have time to explore.)

My only complaint (and this is really nit-picking) with Peter's tools is the hassle of setting up the license files. Peter requires that a license file be placed in an appropriate directory and the serial number provided (either in each page that uses the control, or once in Global.asax). My first time through took me five to ten minutes to get everything correct, and the same headache happened again when deploying from the test server to the production server. The ease of use of the controls had me spoiled where having to tinker around with a license file seemed less than ideal. This, of course, is the pea in the princess's bed - these controls really are worth checking out, especially if you have to create a number of data entry forms. Not only will it save your end users much time, but it will save you gads of time as well, and provide a better-looking, easier-to-work-with user interface.

Filed under:
URL Rewriting, the Image Web Control, and ~
29 September 04 09:20 AM | Scott Mitchell

Recently Scott McCulloch found that when using URL rewriting technique in ASP.NET 1.x I discussed in URL Rewriting in ASP.NET, Image Web controls with the ~ in the ImageUrl property don't resolve correctly. Specifically, if you have an example of an actual page of, say, /RewriterTester/ListProductsByCategory.aspx?CategoryID=1 that has a “friendly URL” of /RewriterTester/Products/Beverages.aspx, and that page includes an Image Web control with an ImageUrl like ~/images/Logo.gif (meaning there's a file /RewriterTester/images/Logo.gif), then when visiting /RewriterTester/ListProductsByCategory.aspx?CategoryID=1 the image is displayed correctly, but visiting the “friendly URL” results in a broken image. (Whew, what a mouthful!) To further complicate things, if you use the ResolveUrl() method, it just works. That is, if on the page you display the output of ResolveUrl(”~/images/Logo.gif”), the correct URL is displayed, regardless if you visit the actual URL or the friendly URL.

After some serious head scratching and digging through the Base Class Library code with Reflector, I found the problem. When the Image Web control is rendered, its src attribute is formulated by calling the Control class's ResolveClientUrl() method. ResolveClientUrl() method is similar to the standard ResolveUrl() method (which works, remember), except for one important fact: it creates relative paths rather than absolute paths. So, ResolveUrl() gives us something like /RewriterTester/images/Logo.gif, but what ResolveClientUrl() gives us is images/Logo.gif. Since the path rewriting has occurred long before the Image Web control is rendered, the Image Web control - regardless of whether or not the person is visiting the friendly URL or not - thinks its path is /RewriterTester/ListProductsByCategory.aspx. So, when it resolves ~/images/Logo.gif, it says, “Ok, well ~/images/Logo.gif is really /RewriterTester/images/Logo.gif, but the relative path for that is just images/Logo.gif,” so it returns just this. This works great when visiting the actual URL, but when visiting the friendly URL, the browser gets the <img> tag with the src of images/Logo.gif. Since the browser has visited /RewriterTester/Products/Beverages.aspx, it requests the image at /RewriterTester/Products/images/Logo.gif. And that, in a nutshell, is the problem.

So what's the solution? Well, I can think of one simple solution: don't specify the ImageUrl for the Image tag in the declarative syntax. Rather, specify it in the Page_Load event handler like so:

if (!Page.IsPostBack)
ImageID.ImageUrl = Page.ResolveUrl(”~/images/Logo.gif”)

This will work since ResolveUrl() gets the absolute path to the file, not the relative path like ResolveClientUrl(). This answer, for me, lead into another question: why does ASP.NET need two methods for resolving URLs? That is, why have ResolveClientUrl() at all (which is internal, by the way, meaning you can't call it directly - only classes in same assembly can). Looking at the Callee Graph in Reflector, the following methods call ResolveClientUrl():

  • HyperLink.AddAttributesToRender()
  • HyperLink.RenderContents()
  • Image.AddAttributesToRender()
  • Panel.AddAttributesToRender()
  • TableStyle.AddAttributesToRender()
  • HtmlControl.PreProcessRelativeReferenceAttribute()

I guess I'm missing why a relative path is ever needed. Won't an absolute path always do the trick? And if relative paths might be needed, why make ResolveClientUrl() internal? Why not make it public like ResolveUrl()?

Filed under:
The Future of GotDotNet Workspaces?
28 September 04 10:15 AM | Scott Mitchell

When .NET broke onto the scene, Microsoft created GotDotNet.com, which promised to be the end-all stop for .NET developers. Since its inception, it has served a lot of purposes: as a list of links to the latest .NET articles around the Web, a list of the CodeWise Community sites, blogs from Microsoftees (which was eventually moved to weblogs.asp.net, and then to blogs.msdn.com), user samples, the GotDotNet Workspaces, and more.

The GotDotNet site describes its workspaces as follows: “Workspaces is an online collaborative development environment where .NET developers can create, host and manage projects throughout the project lifecycle.” It contains bug tracking, message boards, source control, alerts, releases, and so on. My experience with the Workspaces is somewhat limited - I use them for skmMenu's messageboard and for RssFeed messageboards and release files.

GotDotNet Workspaces, in my experiences, leave a lot to be desired. The site is very often laggy, and a number of times is either down and out altogether, or results in assorted errors when I attempt to do various administrative tasks (such as approving members for the workspaces, deleting messages from the messageboard, working with the bug tracking module, etc.). What prompted this blog entry was the recent news that Microsoft has released FlexWiki as an open-source project. But here's the kicker: it's being released on SourceForge, just like Microsoft's other two open-source projects (WiX and WTL). Even though Microsoft is a company that dogfoods its own products, I can understand why these open source projects are not being hosted on GotDotNet Workspaces.

What I am wondering is what does the future hold for GotDotnet Workspaces? Clearly Microsoft knows that the Workspaces are not scalable and not user-friendly. People inside Microsoft have actively moved their projects from the Workspaces to other means (i.e., RssBandit). So what will Microsoft do? As I see it they have three options:

  1. Do nothing, leave the Workspaces as they are... (boo)
  2. Scrap the Workspaces altogehter. Basically say, “This sucks, there are better options out there, so we are taking this down.“ (Don't see this happening unless the “better option“ is a Microsoft controlled option.)
  3. Fix the Workspaces so that they are robust enough that not only will Microsoft employees gladly use them, but other folks as well, even non-.NET related projects. (fingers crossed)

All I know is that I need to move RssFeed and skmMenu from the Workspaces to some other medium eventually. (It's low on the priority list, but it's on the list...) Hopefully Microsoft will step up and greatly enhance the Workspaces so that I can leave the projects there, or will dismantle them, so I am sort of incentivized to hurry up and move the projects over to some other option.

Another Year Rolls By...
27 September 04 12:06 PM | Scott Mitchell

Late September is a special time for me personally, because it marks the anniversary of 4GuysFromRolla.com, the Web site I started with a couple of college buddies to serve as an outlet for my interest in ASP. This September, 4Guys turns six years old. (If you are interested, you can read a bit about the history of 4Guys.)

Time sure does evaporate right before your eyes, eh? I wonder where I'd be right now if it wasn't for 4Guys. Where I live, my wife, my dog, my career, my home, many people I know... all of it can be traced back to that decision to start a Web site. And that can be traced back to my internship at Empower (a now-defunct consulting/training company in Kansas City) in 1998 where I learned about ASP in the first place. It's amazing how many of life's very significant results can be mapped back to some very trivial action or decision.

Ok, ok, enough waxing on about pseudo-philosophical matters like an angst-ridden teen. Back to your regularly scheduled programming in the next post, promise. :-)

Filed under:
Version Control for the Solo Developer
23 September 04 06:32 PM | Scott Mitchell

I've been working for myself for over four years now, which has primarily entailed: writing, training, and software development. What I am a bit embarrassed to admit is that, through all those years of solo software development, I not once used a version control system. My technique for source code control was a rather crude one: I'd periodically backup the entire project to some separate directory on the harddrive, and periodically move those to CDs. That was my process.

While this approach worked well enough and helped guard against total loss of data, it did not provide even close to the amount of features and power a decent version control system would, which include a complete history of changes between code check-ins/check-outs, branches, tools to diff current versions with older versions, the ability to roll back the code to particular checkpoints with the click of a mouse (rather than digging through old CDs).

The four years of no version control ended a few weeks ago, when I finally downloaded and installed SourceGear's Vault. If you work on projects as a solo developer, there's absolutely no reason why you shouldn't go get Vault today - it's 100% free for a single-user license, easy to setup, configure, and get using, and uses Microsoft SQL Server (or MSDE) as its backend.

To get started with Vault, first you'll need to head over to the SourceGear Vault Downloads page and download the Server version. (At the time of this writing, Vault is at version 2.0.6, and the Server download is 15.2 MB.) There's a link there to download a Demo Serial Number, but if you are going to be using this as a single user, you don't need to bother with that - Vault works out of the box for single users with no need to license or demo keys.

Once you have downloaded Vault, begin the installation process. In the setup you'll be prompted to choose what features to install - go ahead and install everything: the Server, the Client, and the Admin Tool. Once you have everything installed, getting Vault to integrate with Visual Studio .NET is a breeze. Simply start the Vault Client, go to the Tools menu, select Options, and then check the “Make Vault your default SCC provider” checkbox. Once you do that, open up a Visual Studio .NET Solution. From VS.NET, go to the Tools menu and choose Options, and select the Source Control folder. Since you are a solo developer, go ahead and choose the Independent Developer option. The final step is to right-click on your VS.NET Solution and choose the “Add Solution to Source Control” option. Here you will be prompted to select what repository to add the project to. (You can add new repositories through the Vault Client).

Once you have Vault setup and have checked out, modified, and checked in some files, you can start to see the utility of a version control system. For example, through the Vault Client you can inspect the changes made to the file over different check-ins/check-outs, and roll back the file to an older version, if needed.

Eric Sink, the founder of SourceGear, has some good blog entries on the core logical entities of any version control system: Files, Folders, Repositories, Working Folders, and so on. A great place to learn more about the concepts is at Eric's Source Control HOWTO articles. So, in short, if you work on solo software projects, you owe it to yourself to get Vault today. It's free, takes only a few minutes to download / install / setup, and can potentially save you hours of work.


On a tangent, does anyone want to wager how long it will be before tools like Vault are just a built-in part of the operating system's file system? That is, anytime any file is changed, an old version is saved to some database, thereby giving a user the ability to easily say, “Restore file X as it was on December 14, 2003, 11:35 am.” With hard drive capacities showing no end in sight, it seems like this would be feasible in the near future, if not today.

For a potential implementation, refer to Santry, Feeley, and Hutchinson's paper titled: Elephant: The File System That Never Forgets (PDF) (written in 1999). I read this paper back in my graduate studies, and, IIRC, the Elephant file system allows a user to indicate how to save files, the options being: keep one (only saves the latest copy); keep all (saves every copy); keep landmark. Keep landmark was interesting, it assumed that the longer a file had gone without being accessed, the less likely the user cared about differences between two close versions of the file. So, if there was a flurry of modifications to a file marked as keep landmarks, and then the file wasn't modified for weeks, the file system would assume it was safe to delete some of those saved versions of the modifications of that file.

RSS Feeds You Can't Live Without
23 September 04 09:18 AM | Scott Mitchell

Over the past month I've had two blog entries asking you, my six readers, what programs and Web sites you can't live without. (See Programs You Can't Live Without and Web Sites You Can't Live Without.) Jeff Coon and others have suggested that I add a third entry: RSS feeds you can't live without.

So, what RSS feeds do you find required reading each morning? If you could share just one blog with someone who doesn't know about it, what blog would that be? How many RSS feeds are you subscribed to, and what RSS aggreagator do you use to consume those feeds?

My favorite RSS feeds for light reading are Dilbert (http://dwlt.net/tapestry/dilbert.rdf) and TheDailyWTF (http://thedailywtf.com/Rss.aspx). For sports, I am addicted to Bill Simmons's articles (http://sports.espn.go.com/espn/rss/columnist?name=simmons_bill), the NBA news on ESPN.com (http://sports.espn.go.com/espn/rss/nba/news), the latest posts on NBAWebLog.com (http://nbaweblog.com/nba/MainFeed.aspx), and Mark Cuban's insights (http://blogmaverick.com/rss.xml). For technical information, I find no blog more interesting than Raymond Chen's (http://weblogs.asp.net/oldnewthing/Rss.aspx). I also tend to subscribe to the blogs of prolific authors, as they usually have good things to say (Dino Esposito, Fritz Onion, etc.). I also have a feed to the articles on www.ASP.NET (http://asp.net/modules/articleRss.aspx?count=7&mid=64), the latest articles on ASPAlliance.com (http://aspalliance.com/rss.aspx), and (of course) the latest articles on 4GuysFromRolla.com (http://aspnet.4guysfromrolla.com/rss/rss.aspx).

If I could share just one blog with someone (assuming they're not a technical person), I'd share Matthew Haughey's Ten Years Of My Life (http://tenyearsofmylife.com/index.rdf). It's basically a photo journal of this guy's life. His plan is to take a picture each day for ten years, posting the picture on his blog. (And that's all it is - no side tracked text entries, just one picture each day.)

I am subscribed to ~40 blogs, and I use RssBandit as my aggregator. (In a previous entry I stated my preference for BlogLines over RssBandit, but since upgrading to a much better computer, I have preferred having my blog reader as a desktop application rather than through a Web site interface.)

Filed under:
A Tabbed Interface for Showing Parent/Child Data
20 September 04 10:36 AM | Scott Mitchell

Last week's 4Guys article looked at creating a collapsible details region using a Repeater and some nifty client-side DHTML. This technique allows for a page with potentially gobs of information to be presented in a more readable format, as can be seen in this live demo. (The astute reader might have noticed that this technique is identical to a collapsible RssFeed demo I provided a while back...)

Anywho, I was playing with the client-side code a bit and thought that it would be cool to take this concept a bit further and have collapsible-like regions for displaying parent/child data. After a lot of tweaking, I was able to create a demo that had the look and feel I wanted. Now, I have to warn you I am pretty limited when it comes to my client-side / CSS skills, so any suggestions on improving the code would be most appreciative. Also, note that it works best on IE - in FireFox it “works,” but doesn't look good.

In any event, here's a live demo: http://aspnet.4guysfromrolla.com/demos/TabInterface.aspx. To view the client-side code, you'll have to do a view/source. The output was generated with some hardcoded HTML markup and a Repeater (for getting the parent/child database data). Eventually I'd like to make this into a custom server control, but one thing at a time... So, if you want to take a look at the demo, feel free, and leave a comment if you have ideas on improving the CSS. The plan is to write up an article on this for 4Guys sometime this week.

Filed under:
Upcoming User Group Talk...
18 September 04 03:41 PM | Scott Mitchell

I'll be speaking at the San Diego ASP.NET SIG this coming Tuesday, September 21st (6:30-8:00 pm). My talk is titled, “Adding Client-Side Script to ASP.NET Web Pages,” and is a presentation based off of my MSDN Online article, Working With Client-Side Script.

The meetings to the ASP.NET SIG are free, and occassionally include free pizza as well. You can learn more about the SIG at their Web site, which includes location and directions. For those who can't make it to the talk (perhaps you live in, say, Vermont), you can download my presentation slides and source code here.

Hope to see you there!

Filed under:
How Not to Take ASP.NET For Granted
16 September 04 01:28 PM | Scott Mitchell

ASP.NET has been around in beta form for over four years now, long enough that I have been taking the power and productivity gains ASP.NET made possible for granted. Couple that with the fact that I only did classic ASP development for two years, and have been doing ASP.NET for four, and it is understandable how I could stop spending hours each day thanking the ASP.NET team for making my life easier.

You'll be happy to know I no longer take ASP.NET for granted, thanks to teaching a three-day course on classic ASP.

The differences between these two technologies is very stark. It's interesting (in a theoretical sort of way, not really in practice) to return to classic ASP after spending years with ASP.NET. Even though the two technologies are fundamentally the same, the approach one takes when reading classic ASP code, or preparing to create a solution in classic ASP, differs radically when compared to ASP.NET. Furthermore, it was neat to see how these students were using classic ASP to accomplish tasks that their companies had come to rely on. These tasks would not floor anyone, but they were useful and thanks to the straightforward, cut-and-pastability of classic ASP, these were tasks that my students were able to accomplish, and likely would have had considerably more trouble trying to do the same in ASP.NET.

I don't plan on making a habit out of teaching classic ASP courses - it's 2004, after all. But it was still and interesting experience, and a nice trip back down memory lane. It makes me wonder if four years from now I'll be looking back at ASP.NET 1.x and having similar sentiments.

The Internet Eats 1.57% of Emails
09 September 04 02:12 PM | Scott Mitchell

According to this article, a recent study at the University of New South Wales has shown that 1.57% of emails sent never reach their intended recipients. These emails, the study notes, are not lost due to spam filters, but due to non-perfect routers and servers sitting between the sender and ultimate receiver. Hardly the five 9's uptime the phone company can promise for voice communications...

Filed under:
Going Independent Yahoo! Group
08 September 04 06:23 PM | Scott Mitchell

James Avery - who recently made the switch from working full time to working for himself - has started a Yahoo! Group for those who are independents or are thinking about going independent. The Group is called Going Independent, and already has over 65 members.

Right now the Group is serving as mostly a coffee house-type list, with people introducing themselves. The real power of this Group, in my opinion, will come once the Group has gotten large enough and people start utilizing it as a resource for advice and answers to common questions.

Filed under:
URL Rewriting Redux
08 September 04 10:51 AM | Scott Mitchell

Alert reader Gustavo Garcia emailed me recently with a small bug he found in my URL Rewriting in ASP.NET article:

I think the code:

if (HttpContext.Current.Cache["RewriterConfig"] == null)
HttpContext.Current.Cache.Insert("RewriterConfig",
ConfigurationSettings.GetConfig("RewriterConfig"));

return (RewriterConfiguration)
HttpContext.Current.Cache["RewriterConfig"]; //Could return NULL?!?!?!?

could produce race conditions, because the Cache could be freed between if
and return.

RewriterConfiguration config =
(RewriterConfiguration)HttpContext.Current.Cache["RewriterConfig"];
if (config == null)
{
config = ConfigurationSettings.GetConfig("RewriterConfig");
HttpContext.Current.Cache.Insert("RewriterConfig", config);
}
return config;

Best regards, and thank you for your article.

Good catch, Gustavo. This problem is discussed with a good explanation in Scott Cate's blog entry: Steve Smith's Awesome Caching Pattern.

Speaking of URL rewriting in ASP.NET, the #1 question I get is with regards to mapping all requests to the aspnet_isapi.dll ISAPI Extension. The blog engine software that I use to run this blog - .Text (or Community Server :: Blogs, as it will be called) - heavily utilizes URL rewriting and provides an option where all incoming requests can be mapped to the ASP.NET engine. So why not turn to Scott Watermasysk - creator of .Text - for some explanation on this? Scott recently posted an entry on some issues with mapping all requests to the ASP.NET process, including tasks you'll have to do once this mapping is made.

Filed under:
Web Sites Can't You Live Without
02 September 04 08:53 PM | Scott Mitchell

About a week and a half ago I posted a blog entry asking for programs you can't live without. I got a lot of great responses, and - thanks for the comments - have learned about a few new, cool tools (replacing WS_FTP with FileZilla, trying out Skype). Among the comments was this one, from Arif Khan:

Now that we have received so many suggestions regarding the programs that are a necessity, how about a post regarding 'websites' that are an intrinsic part of one's daily life?

So that is the purpose of this blog entry. I figured since I learned about a lot of neat tools from the last post, this would present an opportunity to learn about new sites that I'll likely come to find invaluable. So let me know what Web sites do you find yourself visiting every day, those sites that you couldn't live without. Here is my short list:

So what sites are on your must-visit list each and every day?

Filed under:
More Posts

Archives

My Books

  • Teach Yourself ASP.NET 4 in 24 Hours
  • Teach Yourself ASP.NET 3.5 in 24 Hours
  • Teach Yourself ASP.NET 2.0 in 24 Hours
  • ASP.NET Data Web Controls Kick Start
  • ASP.NET: Tips, Tutorials, and Code
  • Designing Active Server Pages
  • Teach Yourself Active Server Pages 3.0 in 21 Days

I am a Microsoft MVP for ASP.NET.

I am an ASPInsider.