<January 2009>
SuMoTuWeThFrSa
28293031123
45678910
11121314151617
18192021222324
25262728293031
1234567

Post Categories

Navigation

Subscriptions

RssFeed Version 1.9 Available

A new version of RssFeed - everybody's favorite ASP.NET server control for displaying RSS feeds - has been released.  The new version 1.9 adds two notable improvements:

  1. The RSS feed “slurping“ code/logic has been decoupled from the server control-related code, and
  2. Support for the <enclosure> element has been added.  In RSS version 2.0 this element is used to associate some external document with the item, and is commonly used in podcast syndication.

Item #1 is the one I'm most excited about.  Previous to this version, the code for sucking down the RSS content was embedded deep within the server control.  But why?  This prevented developers from using my control if they wanted complete control over how the data was displayed... or maybe if they didn't want the data displayed at all.  For example, imagine that you wanted to periodically grab a feed, see if any of its items' descriptions contain a particular substring, and then save those results to a database (or email someone, or whatever).  Previously this was not possible with RssFeed - now it's a snap.

Want to grab an RSS feed from a remote server?  Just do:

RssEngine engine = new RssEngine();
RssDocument doc = engine.GetDataSource(url);

Want to enumerate the items in the returned RSS feed looking for descriptions that contain the term “ASP.NET“?  Simple:

foreach(RssItem item in doc.Items)
  if (item.Description.IndexOf(”ASP.NET”) >= 0) ...

In fact, you could use this logic to strip out those entries that don't have the term ASP.NET in them and then bind that modified RssDocument instance to the RssFeed control by assigning it to the control's DataSource property and calling the DataBind() method.  Check out a demo of the RssEngine class.

The enclosure support now makes it easy to display a podcast using RssFeed, including a “Download” column that links to the items enclosure.  You can see a list of the KPBS News podcast for San Diego at this live demo.  Note how those items that have an associated media file specified via an <enclosure> tag have the Download link in the right column.  Click it and start listening to the podcast!

To top it all off, there's even a 4Guys article detailing this new version: Displaying RSS Feeds - A Look at Version 1.9.  You can download RssFeed and check out the online (or offline) documentation at the official RssFeed homepage; there are also a slew of live demos available.

posted Tuesday, September 27, 2005 4:58 PM by admin with 0 Comments

Google Video, Personalized Search, and MSAdSense - Oh My!

One of my favorite attributes of the web is the abbreviated length of the software cycle.  With desktop software there's this whole mess of burning bits to a CD and shipping them to some physical location, which requires that users actually take the time out to go to said store.  Even for desktop software distributed via the Internet, there's still platform limitations and bulky downloads.  All of these factors that impede deployment and adoption of desktop applications are removed with web-based apps.  It seems like almost once a week that there's some news coming out of Yahoo!, MSN, or (more often than not) Google.

Case in point, a slew of “search site” news came rolling out over the past few days.  One of the coolest is Google Video's commercial-free airing of Everybody Hates Chris, a new comedy series on UPN about Chris Rock's childhood.  Furthermore, Google Video, which used to use a program one needed to download and therefore limited it to playing only on Windows boxes, now operates as a Flash movie in the browser.  That means cross-browser and cross-platform support, as well as the removed nuissance of having to download a program.  Also, the Flash movie automatically resizes to your browser's resolution, automatically buffers the video and (on my DSL connection) starts playing nearly instantly.  You can also seamlessly jump around the stream with little to no delay.  Nice!

If that's not enough, Google also recently improved their Personalized Search feature. When logged in and searching, each search result has a “Remove this Result” link that you can click to optionally filter out search results for your particular search phrase, for all search phrases, or, heck, you can remove the entire domain.  A useful tool for removing splogs and other spammy sites that clutter up the results page with useless information.  This information is not only helpful in cleaning up your own results, but the information will likely be aggregated and used by Google to help improve their search engine's heuristics.

Finally, word is out that Microsoft will be releasing their own AdSense-like program.  This program, called adCenter, has been in beta since March of this year, although only available in France and Singapore.  However, the beta will, I expect, be opening up in the US sooner than later, seeing as there are a slew of adCenterp-related articles on all the tech news sites.  It'll be interesting to see how Microsoft fares in this market, which is already cornered by the likes of Google and Yahoo.  More competition is always better, of course, and hopefully Microsoft can introduce some innovative tools and metrics that force Google and Yahoo to increase their functionality and featureset.  Viva la capitalism!  :-)\

For a computer nerd who likes trying out new programs, it really is an exciting time we live in.  As one who doesn't have cable and will, hopefully, never need/get it, I'm looking forward to a day when the computer can more effectively replace the television.  Seeing Google Video's advances and capabilities in airing a sitcom makes me think we're that much closer.

posted Monday, September 26, 2005 11:32 PM by admin with 0 Comments

Latest MSDN Online Article - Building a ContentRotator ASP.NET Server Control

My latest MSDN Online article is now available from the ASP.NET DevCenter: Building a ContentRotator ASP.NET Server Control.  This article is on ASP.NET 1.x (gasp!) and looks at building a custom, compiled server control that can be used to randomly display various content.  The content displayed can be vanilla HTML markup or dynamic content through the means of User Controls. 

The impetus for this article was, in part, to resurrect the memory of classic ASP's AdRotator control.  (Actually the AdRotator control is included in ASP.NET but gets no press.... curse the bursting of the dot com bubble!)

Enjoy!

posted Wednesday, September 21, 2005 12:07 PM by admin with 0 Comments

Fixing "The Following Add-Ins Failed to Load" Error in Visual Studio .NET

I am giving a talk on Web Services this week and one technology I discuss in virtually every Web Services talk is the Web Services Enhancement (WSE) Toolkit.  One of the nice things about the WSE Toolkit is that it integrates with Visual Studio .NET - right-click on the Web Service or client project and there's a WSE 2.0 Settings option in the context menu that brings up a GUI to edit the WSE-related settings.  However, in running through the talk/demo code today, I noticed that my copy of VS.NET on my laptop wasn't displaying the option in the GUI.

My first attempt at fixing this was to simply uninstall and reinstall the WSE Toolkit.  Upon restarting VS.NET after this process, I got a dialog box with the warning, “The Following Add-Ins Failed to Load - WSE 2.0.”  Urg.  I did a bit of searching and discovered that one way to fix this was to “repair” the VS.NET installation.  So, off I went to the Add/Remove New Programs screen and went to the VS.NET installation screen and clicked on the Repair/Reinstall option.  This prompted me for the VS.NET CDs and, about 20 minutes later, wrapped up doing whatever in the world it was doing.

Fortunately, this fixed the problem for me.  I have no idea what the problem was, exactly, but opting to repair VS.NET is what ended up working for me.  Hope this helps someone else in a similar situation.  For those more familiar with VS.NET Add-In specifics, any guesses/ideas as to what the problem was and, perhaps, a more direct, quicker workaround?

posted Monday, September 19, 2005 11:35 PM by admin with 0 Comments

Google Blog Search

Google's added yet another beta product to their lineup, this time it's the Google Blog Search.  This new search service competes directly with other blog search engines, such as IceRocket and Technorati.  I've been using IceRocket to search the “blogosphere” as of late, and they seem to have very few splog sites in their results.  Furthermore, IceRocket sorts the results chronologically (whereas Google sorts by relevancy by default) and has neat little tools like the Blog Trends Tool.  However, I do find that IceRocket's response time can be a bit slow at times; that is, doing a search or going to the next page of results might take a couple seconds, whereas with Google it's instantaneous.  Both IceRocket and Google Blog Search provide an RSS (or Atom) feed of the search results.

What's most disappointing with Google Blog Search (and IceRocket, to a lesser degree) is the predominance of splog entries.  If you do a search on anything remotely spammy - lasik, cialis, texas holdem, etc. - the majority of the results are going to be splog sites.  Mark Cuban points the finger at Blogger.com in his post A splog here, a splog there, pretty soon it ads up... and we all lose:

What makes the problem particularly frustrating is that it doesn’t cost anything to setup a blog on what is probably the most common blog host, blogger.com from Google. It’s fast, its easy, it’s free and it can be automated. [Note from Scott: you can make a new blog entry in Blogger.com by simply sending an email message to a specified address...]  So blogs are coming at us left and right. We are killing off thousands a day, but they keep on coming. Like Zombies. It’s straight from Night of the Living Dead. Brain dead splogs. Coming at us by the thousands.

Blogger is by far the worst offender. Google seems to be working hard to adjust their relevancy indexes to exclude splog from having influence on search rankings, but they don’t seem to be doing anything more than removing reported splogs. Kind of like going after the zombies one at a time with a shovel. Can we get some help on this Google?

Keep in mind that Mark is one of the owners/investors in IceRocket...  Speaking of Mark Cuban, he also has a great entry on Google's Blog Search as well, comparing it to IceRocket and listing the major concerns he finds with Google's latest offer: Welcome to the show Google BlogSearch.

Hopefully Google will figure out a good compromise, one that eliminates the vast, vast majority of splog sites but that doesn't nullify any (or many) legit sites.

There are also a number of features currently missing from Google's Blog Search that will, I'm certain, be added eventually.  Some of these include:

  • No integration with Google Search History
  • No “Blogs” tab atop the Google search results (akin to the Images, News, Groups headings)
  • No way to submit my blog's RSS/Atom feed.  According to Google Blog Search Help, “If your blog publishes a site feed in any format and automatically pings an updating service (such as Weblogs.com), we should be able to find and list it. Also, we will soon be providing a form that you can use to manually add your blog to our index, in case we haven't picked it up automatically. Stay tuned for more information on this.”
  • No means of categorization.  It would be nice to be able to drill into blogs by topic rather than just having to do a keyword search.
  • Lack of meta-statistics on the blogosphere.  A buzz index like IceRocket provides or other metadata that can be gleamed from Google's massive index would be most appreciated.

posted Friday, September 16, 2005 11:48 AM by admin with 0 Comments

FeedBurner Summary

In August I moved over my RSS feed from the default .Text RSS feed source (Rss.aspx) to using FeedBurner's free service.  Part of the challenge in this process was having existing subscribers automatically switch from using Rss.aspx to using FeedBurner's generated feed (http://feeds.feedburner.com/ScottOnWriting).  I ended up getting everything to work by retooling Rss.aspx to send an HTTP 301 status code to aggregators, which instructed them to update their information using the new feed URL.  For more on the reasons why I switched to FeedBurner along with how I made the needed changes in .Text to send an HTTP 301, refer to FeedBurner and Changing a Blog's Feed URL.

I've now been using the FeedBurner service for coming on three weeks, and wanted to share a quick review of the service.  In my previous blog entry I mentioned the three motivating factors that prompted me to switch to FeedBurner were:

  1. Subscription statistics - FeedBurner provides a number of free statistics, including number of subscribers, number of requests, and aggregator breakdown.
  2. Someone else handles the bandwidth - currently requests to the RSS feed on ScottOnWriting.NET consume roughly 1.5 GB of traffic per week, or 6 GB of traffic per month (in total, ScottOnWriting does about 11 GB of traffic per month).  That's a lot of 1s and 0s that would be nice to offload to another party.  (I don't believe the pre-0.94 version of .Text I was using supported conditional HTTP GETs (although if I'm not mistaken the "official" 0.94 release does; had I been using a version that supported conditional GETs this bandwidth requirement would be an order of magnitude lower, I'd wager, perhaps just a GB for the month.)  (To clarify, while FeedBurner does make requests to the blog's RSS URL, it caches the results for a period of time, thereby reducing the bandwidth demands for my server.)
  3. FeedBurner has a couple of neat “publicizing“ tools - FeedBurner includes a number of tools to easily make links to add your blog to My Yahoo!, MyMSN, newgator Online, and so on.  Additionally, there are nifty little tools you can use to “show off“ how many folks subscribe to your blog, a la:

The free FeedBurner service provides three traffic metrics:

  • Feed Circulation, which shows how many folks subscribe to your blog, how many requests there were to your RSS feed, and how many click throughs there were.  The circulation data can be broken down by day or by hour, and shown in terms of the current week, the current date, the current month, and so on.  Here's a bar graph that shows the circulation for ScottOnWriting.NET since I started using FeedBurner in late August:


  • Readership - the readership stats allow me to see what aggregators are being used to subscribe to my site's content, along with a breakdown of bots and browser aggregators.  As the following graphic shows, the most popular aggregator that's reporting itself (or that FeedDemon knows of) is Bloglines, followed by RssBandit (my aggregator of choice).


  • Item Stats - this shows the click throughs on an item-by-item basis over a specified date range.  For example, the most popular blog entry of mine since late August (at least in terms of subscribers “clicking through“) is How Big is Too Big a ViewState? with 171 click throughs.

The second motive of mine for using FeedBurner was to have someone else (namely FeedBurner) bear the bandwidth costs.  (Thanks, guys!)  Anywho, in the three weeks prior to using FeedBurner the daily bandwidth for ScottOnWriting.NET was 388 MB.  Since moving to FeedBurner my daily bandwidth average has dropped to 211 MB.  FeedBurner alone is saving me 177 MB per day, which is more than 5 GB per month.  Sweet!

One of my initial concerns with FeedBurner was that once you were using FeedBurner you were “locked in.“  That is, I worried that if, down the road, I wanted to switch back to hosting the RSS feed on my site (or use some FeedBurner competitor, or if FeedBurner went out of business), I'd be SOL, since how would I get my subscribers who subscribe to my FeedBurner feed to switch to a different feed?  I'd need to HTTP 301 my FeedBurner feed and since that's hosted with FeedBurner, they have the ultimate say as to whether or not that would be possible.

This fear was assuaged by a blog post by FeedBurner cofounder and CTO, Eric Lunt.  In the post Eric mentions that it is possible to have your FeedBurner feed use an HTTP 301 and spells out their business rules for implementing this (namely, different actions are taken by the feed as time progresses... the HTTP 301 isn't used indefinately, it eventually unwinds to use, basically, a 404).  From Eric's entry:

... when you start directing subscribers to FeedBurner, you may, in the future (way way way in the future) change your mind and want those subscribers pointing back to your original feed. You would probably also like this to happen automatically, and you would probably like some fallbacks for subscribers who don't get redirected for some reason. To date, there has been no simple way to do this. Steve Gillmor first raised this point with us during an interview late last year, and it has also been discussed more recently. We think we have the best feed management service, we think that providing publishers with the ability to do whatever they want is always the right answer, and most importantly, we think your subscribers are your subscribers, not ours or anybody else's.

So, beginning today [June 10, 2005], we're providing a detailed service for publishers who choose to leave FeedBurner. When you delete your FeedBurner feed, we have added an option to redirect your feed. If you select this, we begin a one month process of transitioning your subscribers back to your source feed.

That's reassuring to know.  If you couldn't guess, I highly recommend FeedBurner.  The stats and bandwidth savings make this free service an invaluable one, and the ability to leave FeedBurner clealy and crisply takes away any potential downside in switching over your feed.

For more entries on customizing .Text be sure to check out the Blog Enhancements category.

posted Thursday, September 15, 2005 2:33 PM by admin with 0 Comments

How Big is Too Big a ViewState?

When creating ASP.NET pages one thing that usually doesn't get looked at too intensely by developers is the page's ViewState weight (I've been guilty of this myself).  While there are various mechanisms to reduce the ViewState bloat in a page, the ultimate (uneloquently worded) question is, “How big is too big a ViewState?”  Dino Esposito chimes in with some metrics in his blog entry ViewState Numbers [emphasis Dino's]:

You should endeavour to keep a page size around 30 KB, to the extent that is possible of course. For example, the Google’s home page is less than 4 KB. The home page of ASP.NET counts about 50 KB. The Google’s site is not written with ASP.NET so nothing can be said about the viewstate; but what about the viewstate size of the home of the ASP.NET site? Interestingly enough, that page has only 1 KB of viewstate. On the other hand, this page on the same site (ASP.NET) is longer than 500 KB of which 120 KB is viewstate.

The ideal size for a viewstate is around 7 KB; it is optimal if you can keep it down to 3 KB or so. In any case, the viewstate, no matter its absolute size, should never exceed 30% of the page size.

I think these are good metrics to live by when building apps targetted for the Internet.  ViewState enacts a “double hit” regarding page load time.  First, the user must download the ViewState bytes.  Then, when posting back, that same ViewState must be reuploaded to the web server (sent back in the POST headers).  And then, when receiving back the resulting markup from the postback, the ViewState (possibly modified) is sent back down again.  So during a postback there's a seemingly double hit.  That is, if it takes x seconds to download the ViewState of the page, when the user posts back it will take at least 2x - x to upload the ViewState and another x to download it back again.  Cripes!  (This is part of the reason AJAX is so appealing in Internet situations, although AJAX carries with it it's own slew of issues.)

When you're building intranet apps, where you know your user's will be connecting over a LAN, the page sizes and ViewState sizes are not as important as they impact the user experience much less.  Most of my “real-world” projects have been created for the intranet setting, so I've not had to fret over ViewState size as much as others may have. 

For those projects where a trim ViewState size is paramount, one common question is how to quickly determine the ViewState size (and, perhaps, what junk is actually being stored in there).  For the ViewState size, I usually just do a View/Source and then highlight the ViewState content.  (In UltraEdit - my text editor of choice - the number of bytes selected is shown in the toolbar.)  To determine the contents of ViewState there are tools like Fritz Onion's ViewState decoder (for ASP.NET 1.x and 2.0) and Nikhil Kothari's Web Development Helper (for 2.0).  I also provide code for a web-based ViewState decoder (for ASP.NET 1.x) in my article, Understanding ASP.NET ViewState.

posted Wednesday, September 07, 2005 11:14 AM by admin with 0 Comments

FeedBurner and Changing a Blog's Feed URL

This weekend I moved over my RSS feed - previously http://ScottOnWriting.NET/sowBlog/Rss.aspx - to a feed managed by FeedBurner (http://feeds.feedburner.com/ScottOnWriting).  FeedBurner serves as a sort of feed URL proxy.  Basically you give FeedBurner a link to your RSS feed and it creates a feed based on that feed.  You then point your subscribers to the FeedBurner feed and FeedBurner serves up your site's content, maintains statistics on who's subscribing to your blog, and so on.

I decided to move to FeedBurner to realize three benefits (keep in mind that ScottOnWriting.NET (still) runs off of an old version of Scott Watermasysk's .Text blogging engine, as I've yet to upgrade to Community Server; previous to today, I was actually using a pre-0.94 version, but today "upgraded" to the official 0.94 release downloadable from the .Text GotDotNet Workspace):

  1. Subscription statistics - FeedBurner provides a number of free statistics, including number of subscribers, number of requests, and aggregator breakdown.
  2. Someone else handles the bandwidth - currently requests to the RSS feed on ScottOnWriting.NET consume roughly 1.5 GB of traffic per week, or 6 GB of traffic per month (in total, ScottOnWriting does about 11 GB of traffic per month).  That's a lot of 1s and 0s that would be nice to offload to another party.  (I don't believe the pre-0.94 version of .Text I was using supported conditional HTTP GETs (although if I'm not mistaken the "official" 0.94 release does; had I been using a version that supported conditional GETs this bandwidth requirement would be an order of magnitude lower, I'd wager, perhaps just a GB for the month.)  (To clarify, while FeedBurner does make requests to the blog's RSS URL, it caches the results for a period of time, thereby reducing the bandwidth demands for my server.)
  3. FeedBurner has a couple of neat “publicizing“ tools - FeedBurner includes a number of tools to easily make links to add your blog to My Yahoo!, MyMSN, newgator Online, and so on.  Additionally, there are nifty little tools you can use to “show off“ how many folks subscribe to your blog, a la:

When changing over your RSS feed URL the main challenge is making sure that your existing subscriber base starts to use the new feed URL.  There are, to my knowledge, to ways this can be done, with the first of the two ways being the ideal way:

  1. Have your old feed URL emit an HTTP 301 status code - The HTTP 301 status code is a message from the server to the client saying, “Hey, this resource has been permanently moved to URL xyz.“  The client, then, can make a new request to the specified URL; too, if there's some database being used to track the URL, this message informs the client that it's time to update the database and use the new location.  If I'm not mistaken, virtually all modern aggregators support HTTP 301 status codes and will automatically update a site's feed URL to use the newly specified location.
  2. Tell people of your new feed URL - if you do not have control over your blog website you may not be able to take the steps needed to replace the current feed URL with an HTTP 301 status code.  In this case, the only approach I know of to inform users of the new feed URL is simply through word of mouth.  That is, you'll just have to post on your blog an entry telling users to update their aggregators.  As Kent Sharkey has noted, though, the results may be somewhat disappointing.

Since I run ScottOnWriting.NET myself (well, through a web hosting company), I have control over these matters.  The only challenge, then, was getting .Text to play nice.  In .Text version 0.94 the site's RSS feed comes from a file named Rss.aspx.  This file, though, does not actually exist; rather, in the Web.config file all requests are handed off to a .Text HTTP Handler.  When a request comes in for Rss.aspx, .Text generates the appropriate output.

To get Rss.aspx replaced with an HTTP 301 status code, the first step is to create an Rss.aspx file in your blog's root directory.  The code needed for this page is alarmingly simple - all you want to do is return an HTTP 301 specifying the new feed URL, like so:

<script runat="server" language="C#">
void Page_Load(object sender, EventArgs e)
{
    Response.Status = "301 Moved Permanently";
    Response.AddHeader("Location", "
http://feeds.feedburner.com/ScottOnWriting");
}
</script>

(Of course replace the http://feeds.feedburner.com/ScottOnWriting Location header value with the URL of your new RSS feed...)

Creating this file is not enough.  In fact, even after creating this file if you visit Rss.aspx through your browser you'll still see the complete RSS feed rather than being auto-redirected to the specified URL.  This is because the ASP.NET engine is handing off the request to the .Text HTTP Handler rather than handling the request itself.  If you look at the <httpHandlers> section in the Web.config file you'll find an entry like:

<add verb="*" path="*.aspx" type="Dottext.Framework.UrlManager.UrlReWriteHandlerFactory,Dottext.Framework" />

This entry says, “Any request for an ASP.NET page should be handled by the class Dottext.Framework.UrlManager.UrlReWriteHandlerFactory,Dottext.Framework,” and HTTP Handler. This includes requests for Rss.aspx.  Hence we need to add the following line to the <httpHandlers> section:

<add verb="*" path="Rss.aspx" type="System.Web.UI.PageHandlerFactory" />

That tells the ASP.NET engine to take care of requests to Rss.aspx.  At first I naively thought that I was done, but I had just unwittingly setup an infinite loop!  When a request comes into Rss.aspx, it sends back a 301 status code to the client, saying, “No, no, no, you want to go to this FeedBurner URL.“  This is what we want to tell people coming through a browser or aggregator, but remember that FeedBurner also needs to know the URL of the site's feed, which, at this point, I had set simply as Rss.aspx!  So when FeedBurner periodically checked to see if a new version of my feed was available it requested Rss.aspx, which told it to check itself, which says to check Rss.aspx, which says to check itself, which... you get the point.

Instead, what I needed to do was rename .Text's Rss.aspx to something else, like RssFromText.aspx and instruct FeedBurner to use this alternate, “secretive” feed URL.  With this setup, a user who already subscribes to ScottOnWriting.NET through Rss.aspx will automatically be switched over to FeedBurner.  FeedBurner's RSS content will be populated from RssFromText.aspx, which will be generated from .Text, reflecting the most recent blog entries.  No more infinite loops!

To accomplish this I had to edit blog.config to tell .Text that it should use RssFromText.aspx as its RSS feed URL as opposed to Rss.aspx.  This involved updating the appropriate <HttpHandler> line like so:

<HttpHandler Pattern = "(?:\/RssFromText.aspx)$" Type = "Dottext.Framework.Syndication.RssHandler, Dottext.Framework" HandlerType = "Direct" />

With this addition, requests now to Rss.aspx are sent back an HTTP 301 status code, but FeedBurner can still slurp down the site's content through RssFromText.aspx.

Next, you'll probably want to update the link to the site's feed in the My Links section (since this will point the users to Rss.aspx, but you want them to go directly to the FeedBurner link).  (In actuality, this step is probably optional since even if you do leave it as Rss.aspx, when the attempt to view that page through a browser or slurp it through an aggregator, they'll get the 301 status code and auto-redirect to the FeedBurner URL... but still, for completeness let's change this link.)  To accomplish this, simply edit the MyLinks.ascx file in the ~/Skins/skin_name/Controls/ directory.  With version 0.94 you'll find two HyperLink controls that .Text automatically looks for and sets their NavigateUrl properties to Rss.aspx - these controls have IDs Syndication and XMLLink.  Even if you explicitly set the NavigateUrl properties to your FeedBurner URL, .Text will overwrite it and the link will be rendered as Rss.aspx.  If you try to simply remove these HyperLink controls you'll find that (at least with 0.94) .Text will barf.  What I did was simply set their Visible property to False.  I then added two HyperLink Web controls of my own that referenced the new feed URL.

There's one more facet that should be changed, although I've not made the change since (to my understanding) you'd need to actually hack the .Text source code, recompile, and re-deploy.  In the portion of the web pages in your blog you'll find a tag that's used for RSS feed auto-discovery:

<link rel="alternate" href="http://scottonwriting.net/sowblog/rss.aspx" type="application/rss+xml" title="RSS" >

Ideally the href attribute would contain the URL of your new feed... but I didn't feel like going through the headache of pecking through the source, making a change, testing, and so forth.  So I just left it as-is, figuring in the worst case someone will “discover” my feed to be Rss.aspx, which will automatically be updated to the FeedBurner syndication URL as soon as their aggregator makes its first request to Rss.aspx.

The FeedBurner service looks pretty cool upon first glance.  Once this new feed URL gets some use and I get some metrics in FeedBurner's database, I plan on sharing some of the stats... it'll be interesting to see what the most popular aggregator out there is for those who are ASP.NET developers (the primary audience of this blog, I imagine), among other data points.

posted Sunday, August 28, 2005 7:23 PM by admin with 0 Comments

Enhancements to skmLinkButton

In a previous blog entry I talked about skmLinkButton, a simple, open-source enhancement to the built-in ASP.NET LinkButton Web control.  skmLinkButton includes properties to display text in the browser's status bar when mousing over the link as well properties to easily add a client-side confirm messagebox when clicking the link.

I recently received an email inquiry in my Inbox from loyal 4Guys reader David P., who asked:

I'm writing to you because I think you may be able to help me. I enjoyed your article about overriding Linkbutton very much, but I have a further need that you may have a solution to. A LinkButton is rendered like <a href="javascript:__doPostBack(.....)" onClick="alert('pressed')">Click me</a>.

My problem is that if I SHIFT+CLICK the LinkButton [or right-click on it and opt to open in a new window], a new window opens [with the JavaScript, javascript:__doPostBack(.....), in the Address bar, resulting in a client-script error and a confused user.] ... I want to avoid that. I've found a solution:

<a href='#' onClick="__doPostBack(....);">Click me</a>

My problem is that I don't know which attribute to modify so that the Href value is moved to the onClick event... It must be done in an inherited control or codebehind.

(To see an example of David's problem, click here. The hyperlink's markup is simply <a href="javascript:var x = 4;" target="_blank">click here</a>. Note that clicking the link opens a new window that displays the JavaScript in the address bar and returns an error. This mimics the behavior of an ASP.NET LinkButton that is clicked to have opened in a new window.)

I tinkered with skmLinkButton to do what David requested.  The end result can be read about in this week's 4GuysFromRolla.com article, Stopping JavaScript Errors When Opening a LinkButton in a New Window.  There are live demos to tinker around with over at http://scottonwriting.net/demos/skmLinkButtonDemo.aspx.  You can download the complete source code, along with an example ASP.NET page and a prec-compiled assembly, at http://aspnet.4guysfromrolla.com/code/skmLinkButton.zip.

posted Wednesday, August 24, 2005 2:45 AM by admin with 0 Comments

Requiring HTTPS for Certain ASP.NET Pages

I'm currently working on a project that has SSL capabilities. Users reach the site through a partner site, with the user's session using SSL only if the partner site also used secure communications. There's also an administrative section that, regardless of whether or not the user entered using SSL, must be accessed via SSL. How, then, do you ensure that when a user visits a particular page or subset of pages that they do so via a secure channel?

There are a couple of techniques that I'm aware of. Probably the most sound way is to make the setting through IIS. If you go to the IIS metabase you can right-click on the folder or website you want to require be accessed only through SSL and go to Properties. Next, tab over to the Directory or File Security tab (depending on if you're configuring a directory or file) and, in the Secure Communications section, click the Edit button. This will bring up the Secure Communications dialog box; from there you can click the "Require secure channel" checkbox and, voila, the directory or file can now only be visited through HTTPS.

Once you have made this setting if a client attempts to visit such a configured resource through HTTP (rather than HTTPS) an HTTP Error 403.4 - Forbidden: SSL is required to view this resource.

You can also require SSL programmatically through your ASP.NET pages' code-behind classes, which can be useful if you don't have direct access to the web server's metabase to make the settings as described above). (Realize that setting the "Require secure channel" option through IIS has the advantage that it requires a secure channel for all types of resources - ASP.NET pages, HTML pages, images, and so on. By making this setting through ASP.NET - either in a code-behind class or in an HTTP Module - will only require SSL in resources requests that IIS hands off the the ASP.NET worker process.)

With the ASP.NET code-behind technique you basically add a bit of code to your code-behind class (or, better yet, a base class or HTTP Module) that checks to see if the request is through a secure channel; if not, it redirects the user to the same URL but through HTTPS. An example can be seen in this blog entry: 443 <--> 80 - Seamlessly moving requests in and out of SSL.

In my project I ended up using both techniques, actually. For the ASP.NET pages in the administrative interface I used a technique very similar to the one described in the blog entry. My main difference, though, was that I added a check to see if the incoming request was coming through localhost. If it was, then I didn't sweat the HTTP --> HTTPS translation. I just stayed with HTTP. (I did this because locally I do not have an SSL cert; sure, I could easily create and setup one, but why bother?) I went with the programmatic approach because the user might already 'legally' be on the site through HTTP and then click on a link to go to the admin page. I guess I could have went back and ensured that all admin links were fully qualified with URLs starting with https://, but instead I opted to let the person hit the admin page through HTTP only to be auto-redirected to the same page, but through HTTPS. I used the IIS approach in a couple of places where I had .htm files that needed to be protected. Also, I am using ELMAH on the site and wanted to ensure that its error log viewing page (elmah/default.aspx) could only be viewed through SSL, so potentially sensitive information couldn't 'accidentally' be sent over an insecure channel.

In closing, here are some additional resources I found on this topic that are worth reading:

posted Wednesday, August 17, 2005 2:38 AM by admin with 0 Comments

Third-Party, Commercial ASP.NET Components I've Used

Over a number of ASP.NET projects I've done for companies I've used a variety of third-party, commercial ASP.NET components to accomplish a bevy of common tasks. Oftentimes it makes sense for a client to plunker down the money for a pre-built app that I can plug into his application rather than paying me to create the needed functionality from scratch. I thought I'd share the list of third-party components I've used in the past, along with a (very) short review of each. I'd also be interested to hear what third-party ASP.NET components you've used in the past, and what you thought of them. (Of course, for a more lengthy list of third-party ASP.NET components - some commercial, some free - check out the ASP.NET Control Gallery.)

  • r.a.d. menu - despite having created my own free, open-source ASP.NET menu component (skmMenu), I have used r.a.d. menu in a number of applications. (The reasons for using this over skmMenu have varied. In some cases the client had already purchased r.a.d. menu; r.a.d. menu also offers better cross-browser support than skmMenu and can be customized more easily to provide a more professional look. There have been projects, though, in which I have used skmMenu, so don't let my use of 'competitor' menu components deter you from checking out skmMenu!) I like r.a.d. menu, as it's always been easy to setup and get working with. I've used it in situations both invovling rather static, boring menus, and ones where the entire menu structure was dynamically generated based on various parameters (the logged in user, the current data being worked on, the state of the system, and so on).
  • r.a.d. spell - while I've really liked r.a.d. menu, unfortunately I've not been nearly as impressed with r.a.d. spell. r.a.d. spell provides a client-side spell checker, and while it's realtively easy to setup and looks slick, I've had many random problems reported from various users on sites that I've used r.a.d. spell on. Complaints ranging from dictionary suggestions that seem 'off' to cryptic, client-side error messages when attempting to spell check.
  • Peter's Date Package and Professional Validation and More (VAM) - I'm a big fan of both of these products from Peter Blum. In one project I use the DateTextBox, CurrencyTextBox, DecimalTextBox, and IntegerTextBox like nobody's business. The end users love them, as they use client-side JavaScript to restrict the data being entered and have various bells and whistles (such as the nice-looking drop-down calendar in the DateTextBox, little up and down arrows to increment/decrement the value in the IntegerTextBox, DecimalTextBox, and CurrencyTextBox, and so on. I've yet to explore the true depth of the extra validation controls and capabilities, but expect those features to become more useful as this project evolves. But, seriously, the 'masked' TextBoxes alone made the entire purchase totally worthwhile. (In fact, in an earlier blog entry I carried on about my affection for Peter Blum's controls.)
  • aspNet Email - I had a client who needed to blast out customized emails to thousands of registered users on his site, and he contacted me for advice. I recommended Dave Wanta's aspNet Email component, which is not only easy to setup and blindingly fast in shooting emails out the door, but has a MailMerge() method that made writing the entire application about a thirty minute endeavor.
  • Tall PDF - I've not worked with this component in great enough detail to give it much of a review. I was able to accomplish what I needed to with it - building up a rather simple, two-page report in a PDF document - and didn't have too hard of a time doing it. The major disappointment was that the resolution of the PDF file seemed a bit low - that is, I could not import an image (specifically a graph that needed to appear in the report) unless it was like less than 460 pixels wide and like 620 pixels high. Kind of a bummer because I had to shrink down the dynamically generated graph in order to get it to fit, thereby losing some of the detail. But other than that annoyance, no complaints.
  • Dundas Chart for .NET - I haven't used Dundas in a client's application, but I was given a free copy from the kind folks at Dundas about half a year ago and have used the component in a couple of my own, non-public web applications. I was impressed by the look and feel and the ease with which I could chart data. One such 'private' application I've used this component in is one that I use to track my weight and caloric intake. Here's a graph showing my weight over the last six months or so. Creating this chart basically involved just a half dozen lines of code, and it's appearance can be easily configured through the Visual Studio .NET Designer. Personally I think it's a pretty snazzy looking chart considering my artistic skills!

I'm sure there are a handful of controls I'm forgetting, but the above list gives a smattering of the commercial ASP.NET components I'm currently using and have used in the past.

Care to add a comment about one of the commercial controls listed above? Want to add mini-review on a 3rd-party ASP.NET component you've used? If so, simply add a comment.

posted Thursday, August 04, 2005 1:49 PM by admin with 0 Comments

How Do You Keep Track of TODO Items?

I was working with a client a couple weeks ago, giving a demo through a remote desktop session, when he wanted to jot down a few notes.  His “TODO” list is saved on Outlook, sort of.  What he did to record his thoughts was pen them in a new email message, which, when completed, he simply saved and closed.  Later I saw his Drafts folder in Outlook, which had several thousand drafts, all various TODO notes.  (Interestingly, this client wasn't using any desktop search, so to find a TODO he apparently poked through the draft subject lines or used Outlook's molasses-slow search... I recommended using Google Desktop Search, so hopefully he's now a snappier TODO list searcher.)

Anyway, this got me thinking - how do you manage your TODO list?  I have the annoying habit of - gasp! - writing things down on little pieces of paper.  This habit is annoying for several reasons, the most significant one being the end result of a cluttered desk with bits of paper everywhere with reminders, ideas, and tasks.  Add to the fact that if I'm away from my desk I cannot access my TODO list, and you can see why this is a no-win situation.

Due to my haphazard approach to maintaining a TODO list, I decided to change things up.  I wanted to be able to quickly record a TODO item, be able to search a list of TODO items quickly, and have the TODO list be accessible from any computer, be it my desktop where I do 99% of my work, my laptop, or a public terminal.  Clearly I needed to use some Web-based solution here, but rather than reinventing the wheel I decided to simply use GMail.

One of the nice things about GMail is that you can send an email to yourself and add on a “qualifier” after the email name.  That is, if your email address is me@gmail.com, you can send yourself email like me+todo@gmail.com.  The +todo is what I call the “qualifier” and, despite its addition, your email will get delivered as normal.  The benefit of this is that you can create a filter that looks for incoming messages addresses to me+todo@gmail.com and have them automatically labeled and archived, thereby bypassing your Inbox.  With GMail the TODO list is readily accessible from any online machine and can be quickly searched.  And when I finish the TODO task, I simply delete the email from GMail.

To facilitate quick additions to the list I added an Outlook contact that goes to me+todo@gmail.com, along with a Contact in my GMail address book to the same address.  Therefore, either from my desktop through Outlook, or from a remote computer through GMail, I can add to my TODO list by whipping out a quick email to the appropriate contact, adding my TODO item in the subject with any details needed in the message's body.

Is this how you manage your TODO items?  Got a better idea/approach/suggestion?  If so, share away by making a comment!

posted Thursday, July 21, 2005 5:12 PM by admin with 0 Comments

Watch Your Cookies!

RCF 2109 - HTTP State Management Mechanism - provides the standard for how browsers should handle cookies.  Near the end of the RFC, the following recommendation is made:

Practical user agent implementations have limits on the number and size of cookies that they can store.  In general, user agents' cookie support should have no fixed limits.  They should strive to store as many frequently-used cookies as possible.  Furthermore, general-use user agents should provide each of the following minimum capabilities individually, although not necessarily simultaneously:

  • at least 300 cookies
  • at least 4096 bytes per cookie (as measured by the size of the characters that comprise the cookie non-terminal in the syntax description of the Set-Cookie header)
  • at least 20 cookies per unique host or domain name

On KB article 306070, Number and Size Limits of a Cookie in Internet Explorer, Microsoft states that they “comply” with the RFC by providing the bare minimum cookie requirements.  Urm, hello, Microsoft... these are the minimum capabilities.  Perhaps the goal here was not to have to have different cookie-handling code for IE based on the device (for example, a hand held device or cell phone might need to place such size/length restrictions on cookies), but it seems a bit annoying that such limitations should be placed on IE 6 when being used on my desktop, which has dozens of gigabytes just waiting to hold cookie data.  (There is a workaround for the 20 cookie limit - namely, use a cookie dictionary.  See the KB article for more info.)

Anyway, this 20 cookie limit came to bite me in the behind.  The scenario: a website using forms-based authentication and a Web page using Telerik's r.a.d. spell control.  Each r.a.d. spell control on a site emits a session-based cookie for the purpose of 'securing the dialog.'  I'm not 100% clear what that means or what, exactly, is being secured.  Initially I assumed that it had something to do with the client-side spell checking dialog, ensuring that some cross-site script or some other attack couldn't be used to read or modify the contents while being spelled checked.  That was my guess, at least, until I found that there's a UseSession property that will store whatever is needed to ensure the 'security' in a session variable.  Hrm, so it's a server-side check... I'm confused, but I digress.

Anywho, the UseSession property is False by default, so by default each time a user visits a page that has a spell checker control, or visits a page with many spell checker controls, new cookies get added to the browser.  You can probably see where I'm heading with this - one particular page had over 40 spell checking control instances on it which proceeded to write 40+ cookies to the client.  Since IE can only remember 20, it conveniently decided to nix my forms-based authentication ticket cookie.  The end result?  Whenever I visited this page, after posting back I'd immediately be kicked back to the logon page because the authentication ticket was getting overwritten by the slew of r.a.d. spell cookies.  Meh.

The workaround, in my case, was to simply set the UseSession property to True, thereby avoiding the plethora of r.a.d. spell cookies and thereby preserving my forms-based authentication ticket.

It took a bit of researching to figure this particular one out, and it wouldn't have been possible without Fiddler, a great tool for inspecting the incoming & outgoing HTTP streams.  (I mentioned Fiddler a few weeks back in my Scott Hanselman's Recommended Tools blog entry.) Thanks to Fiddler I was able to see the mess of cookies being added by r.a.d. spell and the corresponding loss of my forms-based authentication ticket cookie.  In addition, I set a breakpoint on the Global.asax's AuthenticateRequest event handler and added to the Watch window Request.IsAuthenticated.  On postback, then, I would hit the breakpoint and see that I had 'lost' my authenticated status.

In any event, if you find yourself being 'automagically' logged out of your site, perhaps it may be due to using IE as your browser and having too many cookies from your domain.  Hope this helps someone save the time that I invested.

Happy Programming!

posted Monday, July 18, 2005 7:14 PM by admin with 0 Comments

Database Projects in Visual Studio .NET

Until about two years ago, I was completely ignorant about Visual Studio .NET's Database projects.  That is, until my wife let me in on the secret.  Actually it was kind of funny, she came home from work one day excited after she had learned about the Database project type in VS.NET and wanted to show me how to create/setup/use such a project.  We were about to head out of the house, so I said, Later, and over the next few weeks she mentioned it occassionally, but there never was a good time.

Finally, we both had some free time and I asked her to show me the Database project.  Since then I've been using them in every single data-driven ASP.NET Web application project I've created, and have immensely enjoyed the benefits.  Many thanks, my dear.

I recently wrote an article on 4Guys about the advantages of Database projects and how to get started using them.  I invite you to read this new article, Database Projects in Visual Studio .NET.  Additionally, be sure to check out the Visual Studio .NET Database Projects sample chapter from Database Access with Visual Basic .NET.

To summarize the advantages of Database projects, I quote from my article on 4Guys:

  • Source control on database objects - if you are using source control (and you most definitely should be), the scripts managed through the Database project can be added to your source control provider. This means that any changes to your database objects will be recorded by your source control provider, thereby providing the myriad of advantages that source control affords (rolling back to older versions, a complete history of changes, etc.).
  • A centralized development experience - rather than having to poke through SQL Enterprise Manager you can manage your database-related objects through the same IDE that you are using to manage the pages and components in your ASP.NET application.
  • An improved text-editor - Visual Studio .NET's text-editor is head and shoulder's above SQL Enterprise Manager's built-in text-editing experience. Additionally, with SQL Enterprise Manager many of the dialog boxes that are used to create/edit database objects are modal, thereby making it impossible to examine other facets of the database when creating/editing a database object. Not so when doing it through Visual Studio .NET.
  • Ease of deployment - if you need to quickly replicate your database's structure having a Database project makes it as easy as right-clicking on the Database project's objects and selecting the 'Run' context-menu option.

posted Wednesday, July 13, 2005 2:07 AM by admin with 0 Comments

Free Tools for Managing Small, Hobby Websites

I run a number of websites that account for just a few thousand page views per day in total. Many of these websites are simple hobby sites I created for myself, friends, or family over the years, such as NBAWebLog.com and ReadyToBurst.com. Many of these sites are hosted with different web hosting providers. I am interested to learn what tools you use to manage small, hobby sites. (By 'manage' I mean to track site usage, monitor the site's health, and so on.) I've been using the following two free tools that I'd recommend to others:

  • StatCounter.com, for tracking/viewing reports on site traffic across the various websites, and
  • SiteUpTime.com, for keeping dibs on the site/web hosts's overall uptime/health.

Both services are free only in limited ways: StatCounter.com is free for sites that get less than 9,500 page views per day; SiteUpTime.com is free for monitoring one site.

StatCounter.com is pretty easy to setup, you simply create a new 'project' and provide the URL of your site. They then give you a cookie to place on each page in your site. Once you've added this cookie to your site and some visitors have stopped by, you can go back to StatCounter.com and view reports on your site's traffic. The reports are nothing fancy, and from what I see you cannot view reports for multiple projects at once (i.e., compare traffic patterns for site X vs. taffic patterns for site Y), but for the price I'm very pleased with the service.

I'm interested in learning about more 'must-have' resources for managing/running small, non-mission-critical websites. If you have any tools you find invaluable for this means, be sure to share them by posting a comment.

posted Monday, July 04, 2005 4:53 PM by admin with 0 Comments

Powered by Community Server, by Telligent Systems