August 2004 - Posts

www.DotNetToolbox.com, not www.AspNetToolbox.com
25 August 04 08:16 AM | Scott Mitchell

Back in August 2003, I created a site called - at the time - AspNetToolbox.com [see this old blog entry]. The aim of this site was to serve as reviews for free must-have ASP.NET tools, programs, applications, etc. I later enlarged the scope to .NET in general, and aptly renamed the site to DotNetToolbox.com. Recently the www.aspnettoolbox.com domain name expired, and I didn't bother renewing it. However, I have received a few emails, and even a blog comment, asking what's up. Sorry if I hadn't made it clearer in the past, but the site is live and running, just use www.DotNetToolbox.com instead...

In any event, I'm always looking for folks who are interested in writing a quick review of a free .NET tool they find they can't live without, one that helps them in their development, be it WinForms apps, Web applications, or Web services. If you are interested in contributing to DotNetToolbox.com, drop me a line.

Filed under:
Programs You Can't Live Without
22 August 04 10:50 PM | Scott Mitchell

Scott Watermasysk recently posted an entry asking for CSS book recommendations, in part due to the phenomenal response to an entry of his asking about FTP program recommendations. Reading through the FTP program recommendations there were a lot of posts that read, “Check out FTP program X, I use it everyday and couldn't live without it!” This got me interested in a number of FTP clients I had never even heard about, and prompted me to check out their homepages and even download and try out a few.

The wheels in my head began to turn, and I though that if one little post asking for FTP client recommendations could generate enough great suggestions to introduce me to a number of new FTP clients, imagine what wealth of information could be obtained if I asked for general “can't live without“ programs. I just might learn about numerous programs previously unbeknownst to me that become essential programs in my toolbox.

This entry, then, is my open request to the small handful of people who read my blog: What software programs (short of the obvious ones like Outlook, Visual Studio .NET, Word, etc.) can you not live without? Here is my list:

(In April 2004 I posted a somewhat related entry: What Programs Do You Have Running 24x7?)

Filed under:
Hosting Multiple Sites from One Web Application
20 August 04 10:50 AM | Scott Mitchell

Back in May of this year I wrote a blog entry on my first year of hosting ScottOnWriting.NET and other assorted sites with WebHost4Life. One of the pros of WebHost4Life that I mentioned in the review is that you could host multiple Web sites on one account, using one of two options:

  1. Paying $15/year to have a domain name map to a specific directory.
  2. Paying nothing, and having the default.aspx page in your site check the URL and redirect the request to the appropriate subdirectory.

The first approach is definitely more professional, as a request to www.somesite.com will remain as www.somesite.com in the user's browser, and not require an extra request to the Web server. With the second approach, however, when a user visits www.somesite.com, they'll be redirected to some other subdirectory on the site, like www.somesite.com/ss. I use this approach here on my blog (note that if you visit www.ScottOnWriting.NET you get auto-redirected to www.ScottOnWriting.NET/sowBlog).

Anywho, a poster named Chris had the following question:

Excuse me for being completely new to ASP.NET, but in I was wondering if you could point me to a tutorial on the "hosting multiple sites using default.aspx" method? I'd like to try this as I can't justify $15 per domain. Thanks!

Chris, here is the code I use in the root Web directory's default.aspx page to redirect the user to the appropriate subdirectory based on their URL (this code would go in the Page_Load event handler):

If Request.Url.Host.ToUpper().IndexOf("SCOTTONWRITING.NET") >= 0 then
Response.Redirect("/sowBlog/")
Response.End()
ElseIf Request.Url.Host.ToUpper().IndexOf("SKMMENU.COM") >= 0 then
Response.Redirect("/menu/")
Response.End()
ElseIf Request.Url.Host.ToUpper().IndexOf("NBAWEBLOG.COM") >= 0 then
Response.Redirect("/nba/")
Response.End()
End If

As you can see, there are three URLs that will redirect the visitor to a specific subdirectory: ScottOnWriting.NET, skmMenu.com, and NBAWebLog.com. This approach is used to host these hobby/personal sites all on one WebHost4Life account without having to shell out the extra $15/year for the Web server-level mapping of domain name to subdirectory.

Hope this helps, Chris!

Filed under:
Friday Quiz: Question on .NET 2.0 Generics
20 August 04 09:26 AM | Scott Mitchell

Here's a little question that has me stumped, perhaps someone out there in the intraweb can answer this for me.

With Generics in 2.0 you can impose constraints on the type that can be specified by the developer. For example, I could create a class:

class Foo<T> where T : Bar
{
...
}

This would only allow developers to create a Foo instance where the type specified via the Generic was of type Bar, or derived from Bar. Ok, great. Now imagine that I have a class SuperFoo<U>, and I want U to be of type Foo<T>, or a class derived from Foo<T>. That is, I want to be able to say later:

SuperFoo<Foo<int>> blah;

How do I specify that? If I try:

class SuperFoo<S> where S : Foo

I get an error because Foo is not a type, Foo<T> is the type. If I try:

class SuperFoo<S> where S : Foo<X>

It barfs because X is an undefined type. Finally, if I try:

class SuperFoo<S> where S : Foo<S>

It compiles the class in this instance, but I can't create a type of this class. That is, if I do:

SuperFoo<Foo<int>> blah;

It says that Foo<int> isn't convertible to Foo<Foo<int>>, which seems to make sense since in the class definition, S is Foo<int>, so if S must be of type Foo<S> then it must be Foo<Foo<S>>.

So does anyone know how to define a class that uses generics to constrain the generic type so that the type is a generic type itself?

Latest MSDN Article
17 August 04 09:59 PM | Scott Mitchell

My latest MSDN article - Working with Client-Side Script - is now available on the ASP.NET Dev Center on MSDN Online. This article is geared for beginners and examines how to easily inject script to perform common client-side tasks, such as opening a popup window, displaying confirm dialog boxes, displaying alerts, prompting a user to save if they leave a form after making changes, how to create a messagebox that, regardless of what is clicked, results in a postback, and so on. Specifically, the article looks at creating a class derived from Page that offers methods that hide all the dirty work involved with squirting out the appropriate client-side script. (I've used many of these techniques in a number of consulting projects I've done, as pushing more tasks to the client improves the overall user experience.)

Many thanks to those who reviewed the article (they're listed at the bottom of the article). If you'd like to receive advance copies of my MSDN articles to help improve them through reviewing, drop me a line.

Filed under:
Going Independent: Some Thoughts from James Avery
15 August 04 12:43 PM | Scott Mitchell

Back in April of this year I started a Going Independent series of blog posts, inspired in part by Johnathan Goodyear's articles on this topic. Anywho, it's been a while since I've updated that series, and I plan on doing so eventually, but in the mean time James Avery has started a similar series of posts on going independent on his blog. His most recent entry - Going Independent - Making the Decision - is definitely worth reading. I particularly enjoyed reading about James's epiphany on when to make the leap from being employed to being self-employed:

So starting my own company and working as an independent consultant while working on writing and software in my spare time seemed like the perfect solution, but the question was when to do it. This is when the fear started to kick in, no longer was I a single guy with no responsibilities, I am newly married with house and car payments, I needed to make sure that I had a semi-reliable income. For the last year or so I have been putting off this idea of going independent, writing it off to needing more experience or wanted to wait for the perfect time. Then I was out at the MVP Summit earlier this year and I was talking to a number of different developers and we were discussing going independent, I mentioned to Jonathan Goodyear that I was thinking of going independent and he said something like "What are you waiting for?"

I started working for myself back when I was still an undergrad at college, but I had a similar tough decision to make myself upon graduation. I had been offered a great job from Microsoft, an oppotunity to work with the Hotmail team in Microsoft's office in Silicon Valley, and needed to decide between pursuing that oppotunity or continuing to work for myself. I opted for the latter, figuring that I had to roll the dice and try my luck at working for myself. In the worst case, I reasoned, I could always go begging back to Microsoft if working for myself turned out to be a bust. (Of course this decision was infinitely easier than James's, seeing as I was single, had just graduated college, wasn't saddled with a mortgage, etc.)

In the end, I made the right decision for me. Striking out on my own forced me to grow in ways that working for a company wouldn't have afforded. Had I chosen to work for Microsoft, my life's script would have been a bit more spelled out - I would have moved to San Jose, I would have had help from Microsoft in finding a place to live, I would have gotten to know and socialize with coworkers, and so on. When I decided to work on my own, I packed up the car and drove out West, not knowing where I was going to settle, how I would meet folks, or what, precisely, I would be doing. It made for a bit more of an adventure and introduced challenges that would have likely otherwise not presented themselves.

Oh well, enough of this emotional ramble, check out James's blog entry, it's worth the read...

Is There Anything More Self-Conscious than Watching Yourself?
12 August 04 09:16 AM | Scott Mitchell

My latest “book” is out, but this time it's not a book - it's a DVD. About two and a half months ago I started talking with DVPress, a company that makes technical training DVDs, and decided to participate in creating a DVD targetted toward those interested in learning the fundamentals of .NET Web Services. I flew out to Houston at the end of May, and spent two days filming the seven or so hours of training that's on the two-disc DVD. Yesterday I received the 20 author's copies and, naturally, sat down to watch myself. The verdict? I don't like the way my voice sounds (although I already knew that).

Anywho, if you are interested in learning about .NET Web services, or know someone who is, or just want to own a DVD where yours truly is sitting there droning on for seven hours, you can pick up a copy of the DVD at Amazon.com: Beginner's .NET XML Web Services ($29.95, qualified for free shipping). The training covers the basics of Web services, looks at creating and consuming Web services with Visual Studio .NET, explores the SOAP and WSDL standards, and dives into the Web Service Enhancements, showing demos on both UsernameToken authentication and sending / receiving attachments with DIME and WS-Attachments.

Funny side story from the days of filming: the studio is in an office building, and during my filming DVPress was expanding their office space into the neighboring suite. In the other suite were a team of handy-men painting, cleaning, etc. At one point, I'm in the middle of a chapter - the lights are off, save a set of bright lights on me, there's a camera and a cameraman filming, but despite this, a handyman quietly opens the door and walks into the room. He walks behind the camera, over to the side and parallel with me, about six feet away from me (still off-camera, though). The whole time I'm still looking in the camera, delivering the lesson... well, he starts painting a window sill, and he does so half turned so that while he's painting, he's watching me with this quizical look on his face. Very surreal.

RoundedCorners Web Control Update
09 August 04 02:49 PM | Scott Mitchell

A couple weeks ago I created a custom ASP.NET server control for displaying some text within a box with rounded corners. This control, which I called RoundedCorner, was discussed in detail in the article Introducing the RoundedCorners Web Control. Ideally, such rounded corner boxes are created by having a graphics designer create the necessary rounded corner images using Photoshop or some other graphics editing program. The HTML designer, then, can create the necessary markup (HTML and/or CSS) to display a box using these rounded corner images. While this is indeed the "best practices" approach for creating a box with rounded corners, it is not always feasible for those of us who are developer teams of one, and whose artistic skills match those of a brain-damaged poodle. The RoundedCorners Web control aids those of us, like me, who fall in this boat by dynamically creating the corner images using GDI+.

Since the publication of the original RoundedCorners article, I have received a lot of great feedback on suggestions for improvements. The main two suggestions were:

  1. Add the ability to put anything inside a box with rounded corners, not just some text message. That is, I should be able to have a DataGrid, some HTML markup, and a TextBox Web control all within a RoundedCorners Web control instance.
  2. Use anti-aliasing when generating the images, to help smooth out the rounded corners.

I have implemented these two enhancements, and recently wrote an article on 4Guys with information about my experiences. You can read the article at Improving the RoundedCorners Web Control, which contains the complete source code. Also be sure to check out the updated live demos.

Filed under:
Here's One Way to Win the Browser War
09 August 04 12:31 PM | Scott Mitchell

While Internet Explorer clearly still holds a sizeable lead in browser usage, alternatives such as Mozilla and Opera are faring better as of late due to security concerns and an improved browsing experience. Personally, I use Mozilla FireFox as my browser of choice. Now, there is a “good” way for Microsoft to win the browser war, and a “bad” way. The good way is to improve IE, to add nifty features, make it less vulnerable to malware, and so on, and so on. That way, everybody benefits. The “bad” way is by making alternate browser unusable, and this is what Microsoft is doing (likely unintentionally) right this very minute.

If you use FireFox, mosey on over to MSDN content, such as this piece on Composition vs. Rendering. Notice how the source code sample is all squished together. That is, you see something like:

[C#] using System; using System.Web; using System.Web.UI; using System.Collections.Specialized; namespace CustomControls { public class Rendered : Control, IPostBackDataHandler, IPostBackEventHandler { private String text1; private String text2; private String text = "Press the button to see if you won."; private int number = 100;

This essentially renders FireFox unusable when I need to lookup MSDN information online. What's particularly frustrating, is that this problem used to not exist on MSDN, although it did on the ASP.NET Dev Center. Back in March of this year, I took the time to find the problem and provide a fix. It took a month or so for this fix to finally make its way into the ASP.NET Dev Center, but by mid-May, it was definitely working. But now, both MSDN and the ASP.NET Dev Center don't play nicely with Mozilla FireFox. And here's the kicker: it's not working for the exact same reason as I wrote about before. Bummer.

So, I implore you, Mr. MSDN - please fix MSDN so I can browse with FireFox!

Filed under:
How Do You Tell if a Number is Prime?
06 August 04 11:31 PM | Scott Mitchell

I just finished reading a blog entry on the new System.Collections.Generics.Dictionary class in Whidbey where Krzysztof Cwalina talked about the difference in conflict resolution between the Hashtable and the Dictionary classes. (The Hashtable uses probing, the Dictionary chaining.) When either data structure reaches its maximum size it must be expanded. (This maximum size is defined as a percentage of full buckets for the Hashtable, as defined by its loadFactor; for the Dictionary, all of its buckets must be filled before being resized.) When being resized, the algorithm goes as follows:

  1. Double the size of the number of buckets
  2. Find the next largest prime number; this prime number is the new number of buckets for the data structure.

For the Hashtable, which uses probing, it is of great importance that the hash and the number of buckets be relatively prime, in order to ensure that probing does not lead to conflicts itself. This is ensured by having the number of buckets be prime, meaning it will be relatively prime with any number, save itself and 1. But why does Dictionary need a prime number of buckets? There may be some reason I'm missing, but I don't believe it's a requirement.

Anywho, a commentor on Krzysztof's blog asked why the number of buckets is expanded so. That is, why double (and then some) the number of buckets, why not increase is by 10%, or 50%, or something user-defined? From my understanding, this could be user-defined, but doubling the size of a buffer is a good heuristic. It's what the ArrayList and List data structures do when you exceed their capacities.

But enough rambling, let me address the title line of this blog. When expanding a Hashtable, it is important to end up with a prime number of buckets. But how does one find a prime number? Since a prime number is a number with only 1 and itself as factors, a naive approach would be to loop from 2 to the number - 1, and see if any numbers divided the number being tested. If so, the number is not prime; if not, the number is prime.

While this will definitely work, it's a bit of overkill. You can actually loop to just the square root of the number you want to test. Why? Well, say you want to know if x is prime. If it is, then a number less than or equal to sqrt(x) must divide x. To prove this, use a proof by contradiction. Assume that x is composite and that it is not divisible by a number less than sqrt(x). Then there exists some set of numbers, call them y and z, such that y * z = x, and y, z > sqrt(x). If this is the case, then y * z must be greater than x, since sqrt(x) * sqrt(x) = x. Since we have reached an absurd conclusion, the premise must be wrong, and therefore a composite number must have a factor less than or equal to its square root. So you can just loop from 2 to sqrt(x) when checking for divisibility.

Even this approach is overkill, really. I believe it was Euclid who showed that all integers can be written as a product of primes. So rather than looping from 2 to sqrt(x), you really only need to check for divisibility against the prime numbers between 2 and sqrt(x).

Enough mathematics - how does .NET find the next largest prime number? Well, the Hashtable maintains an array of 70 prime numbers that are roughly twice in size. That is, it starts with 11, then 17, then 23, then 29, then 37, and so on, up to 7,199,369. Obviously it skips over a lot of primes, since the 1,000 prime number is 7,919. Given a number, we can find the prime larger than this number by consulting this pre-defined array. But what if the number we have to find a prime larger than is, itself, larger than 7,199,369? If this is the case, the .NET Framework falls back on the ol' tried and true measure - looping from 2 to sqrt(x) and checking for divisibility.

To learn more about Hashtables in the .NET Framework 1.x, check out: An Extensive Examination of Data Structures, Part 2.

Filed under:
Latest Article of Mine in this Month's asp.net PRO
04 August 04 09:08 PM | Scott Mitchell

In the July 2004 issue of asp.net PRO magazine there was an article of mine titled Displaying Syndicated Content (link works only for asp.net PRO subscribers), which examined how to read in a remote RSS feed and display it in an ASP.NET Web page, including how to accomplish this using RssFeed, an open-source custom server control I created for displaying syndicated content. In this months issue, I have a related article called Syndicate Your Site (again, URL for subscribers only), which looks at the inverse of displaying syndicated content - creating it. The article shows how to turn database data into an RSS feed.

Since the July 2004 issue, I've gotten a number of positive correspondences regarding RssFeed, including some great suggestions for enhancements. If you've not seen RssFeed before, check out the live demos. Essentially you can display an aesthetically-pleasing RSS items in an ASP.NET Web page with two lines of code.

For more free server controls, check out my Code Projects page.

Filed under: ,
Anyone Familiar with Enhancing the ReadWriteControlDesigner?
02 August 04 09:13 PM | Scott Mitchell

My last two blog entries have focused on the RoundedCorners Web control I created, which displays text within a box with rounded corners. (See a live demo or read more about this control.) One of the most requested feature additions has been the ability for the control to contain nested content, and to display this nested content within the box with rounded corners. That is, a page developer could use the following markup:

<skm:RoundedCorners runat=”server” ...>
<asp:DataGrid ...>
...
</asp:DataGrid>
</skm:RoundedCorners>

And the result would be a DataGrid within a box with rounded corners. Well, adding this functionality wasn't too challenging, but the task that's facing me now is creating a rich design-time experience, which is proving to be harder than expected. Ideally, the design-time experience would be similar to that of the Panel Web control, where a page developer could simply drag and drop Web controls from the Toolbox into the RoundedCorners control. From my research (primarily Developing Microsoft ASP.NET Server Controls and Components and picking through Reflector), I found that you need to create a Designer class that derives from the ReadWriteControlDesigner class. This, along with setting the ParseChildren and PersistChildren class-level attributes correctly, will automatically will allow a page developer to drag and drop controls within the custom server control. However, the ReadWriteControlDesigner class does not call the GetDesignTimeHtml() method, which is typically used in a custom Designer class to tailor the HTML used to render the control in the VS.NET Design tab.

Instead, the ReadWriteControlDesigner class creates what appears to be a DHTML-aware canvas that you can use to tailor the look of the control in the Design tab. I was unable to find what, exactly, the rendered HTML is for this canvas, but it appears to be a <span> or <div>. You can programmatically specify CSS properties or HTML attributes for this canvas, such as backgroundcolor, width, height, font, border, etc. But I don't see that there's any possible way to customize the actual HTML that comprises this canvas. See, I don't want a simple <span> or <div>, I want a 3x3 <table> in there, which would show a potential title for the box, and the places where the rounded corners would appear. But with a custom Designer derived from ReadWriteControlDesigner class, I can't find out how to control this, if it's at all possible.

Has anyone had any luck creating a custom Designer for a server control that extends the ReadWriteControlDesigner class and allows for a finer degree of customization of the HTML in the VS.NET Designer, or is this just not possible? Finally, any opinions on having a substandard design-time experience? Would it be worth it to have a control with more features (namely control nesting)?

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.