mostlylucid

November 2003 Entries

Back in a few days...

Taking a break away from computers for a few days...back in a week's time...

Dino Esposito, one of the greatest .NET authors around has started a weblog!

Find his weblog here, for those who don't know, Dino is the author of the MSDN Magazine Cutting Edge column as well as a whole bunch of the best books around on ASP.NET (do a search at Amazon...then buy his books!). He's already made a couple of very informative posts (the control state stuff is really interesting). So, go check him out!

RSS Feeds...

Rob Howard asked how other people were doing RSS feeds, well this has been an issue for me recently, where I had to generate RSS feeds for existing objects. I used a little collection of classes to do this which I've uploaded here, here's a quick example of how I'm currenlty using these (names removed to protect the innocent) - note, these are not EXACT Rss, I added one field, xsdDate, 'cos I needed this for a transform (doesn't break readers having this extra bit though!), I'll update this later with a bit more info on these...essentially it passes through the items in an object (badly) named ItemFeedStruct and creates an entry for each one...doing a ToString() then gives me the complete RSS feed for this. Note, I did not write the RSS Classes originally, but I can't find the link to the person that did - if ot was you, leave a comment! UPDATE:  Apparently it's Adam Kinney's from the GotDotNet Workspace

        private void BindRssControls(ItemFeedStruct theFeed)
        {
            
            string thisUrl = "http://" + Request.Url.Host + Application["AppPath"];
            RSSFeed rFeed = new RSSFeed("Latest  " + cts.ContentTypeName,thisUrl,"Feed for  Communities");
    
            for(int i=0; i < theFeed.items.Length; i++)
            {
                RSSItem rItem;
                if(_contentType != ctl.ForumThreads)
                {
                    rItem = new RSSItem(Server.HtmlEncode(theFeed.items[i].ItemTitle),Server.HtmlEncode(theFeed.items[i].ShortDescription));    
                }
                else
                {
                    string longDesc= theFeed.items[i].LongDescription;
                    if(longDesc.IndexOf(' ') > -1)
                    {
                        longDesc= longDesc.Substring(0,longDesc.LastIndexOf(' '));
                    }
                    rItem = new RSSItem(Server.HtmlEncode(theFeed.items[i].ItemTitle),Server.HtmlEncode(longDesc));    
                }
                rItem.PubDate = theFeed.items[i].ItemValidFrom.ToUniversalTime().ToString("r");
                rItem.XsdDate = theFeed.items[i].ItemValidFrom.ToString("s");
                rItem.Guid = theFeed.items[i].itemId.ToString();
                rItem.Link = Server.HtmlEncode(theFeed.items[i].ViewUrl);
                rItem.Author = Server.HtmlEncode(theFeed.items[i].AuthorName);
                RSSCategoryCollection rCat = new RSSCategoryCollection();
                rCat.Add(new RSSCategory(Server.HtmlEncode(theFeed.items[i].Category)));
                rItem.Categories = rCat;
                rFeed.Items.Add(rItem);
            }
            Response.ContentType = "text/xml";
            Page.EnableViewState = false;
            RssLiteral.Text = rFeed.ToString();
        }

Fantastic Web 'Widgets' from Matt Hawley

Found through a comment on Jon Galloway's blog (no relation), this site has a whole bunch of nice little client side controls including a particularly nice calendar control . Anyway, thought I'd post the link for future reference :-) - oh and here's Matt Hawley's blog (he wrote them)

Yukon presentation - it rules!

Just been catching up on the PDC presentations, came across this one on Yukon, also, for an interesting perspective on why you should use SPs in Sql Server, watch the first 10 minutes! Man, I am so looking foward to Yukon reaching RTM; the architectures which this thing enables will be so elegant.

UPDATE: As Jon Galloway pointed out, these are pretty buggy; the UI takes a bit of getting used to (or sucks to an incredible degree would be more accurate) - hint, don't click on the images for each track, click on the text. Worth persevering though!

Nested Data Bound List Controls in ASP.NET

This article (which pretty much constantly seems to be down for me at the moment) presents an interesting was to nest Repeaters etc... in ASP.NET, now I have never used this approach - and I have no idea what method is best (and I suck at writing so, I'll probably update this a LOT). What I generally do is use the OnItemDataBound event to bind child tables on to the nested repeater to do this you simple create an ASPX page with a repeater into which you nest a second repeater. 
In the first repeater, you use the OnItemDataBound event (ItemDataBound from the code-behind) to pull out a DataTable using a DataRelation and bind it on to the 'child' repeater...see the project for a complete implementation using Northwind.
I've made the complete project  avaialble here.
UPDATE: Sorry, I've had to pull the source for now, having major problems with the .TEXT editor...hmm...anyway, feel free to download the project and have a dig around, happy to answer any queries!

Compile ASCX controls - so you no longer have to distribute the ASCX file!

I replied to someone's post saying that this was possible, well I finally got around to digging out the link, this article on CodeProject provides a little tool which will generate the C# source file representing your ASCX, pretty cool really!

Internet Explorer Client Side behaviours - the magic of HTC

Reading this post from Stephen Sharrock reminded me about something I often overlook, the phenomenally powerful DHTML behaviours which IE supports using HTC files. The WebService behaviour for instance lets you pull information into your client from aribtrary web services, even without using HTCs, tools like xLoadTree provide the ability to load data straight into the client without forcing a postback.
Before anyone comments, I know these are IE only - to be honest I don't care, when only 3% of users use anything other than IE, it seems a shame to ignore the functional improvements these kind of tools provide.
Now, Mozilla does support it's own version using XBL and XUL - hopefully some genius will work out a way for mozilla to support full HTC as well...

OK, enough moaning - I will now go one whole week without complaining!

Things like this kind of put my complaints about silly programming stuff into a bit of perspective!

Now this really bugs me...

Noticed a link in my referrer log from this post which comments on a comment I made in the whole Dyanmic SQL debate, this comment:

Right. Because evaluating arguments based on their validity is too much work, so it's much easier to pick the "winner" by picking the side with the least vested interest. It apparently has nothing to do with the fact that Frans is, well, correct?

Based on my comment taken out of context from this post:

"To be honest I'm always a bit reticent to pay much credence to an argument on an approach to Data Access from someone who has a vested interest."

Sorry, but I did not 'pick a winner' I said in the same post that I took no absolute position in this debate, for the most part I disagreed with Frans's position because I did not agree with many of his arguments, the vested interest comment was based on this by Frans-

"A good O/R mapper helps you with this. Microsoft also believes stored procedures are over: Microsoft's next generation business framework MBF is based on Objectspaces, which generates SQL on the fly. ".

So his position seemed to be boiling down to the belief that you should use an O/R mapper (such as of course, LLBLGen Pro), it was also positing the belief that Microsoft had the belief that this was also true (Objectspaces is ONE approach, Yukon actually increases the utility of Stored procedures by allowing the use of cLR code within them) , in addition I made several comments; and replied to a comment from Frans here on my own site which did challenge the validity or his argument - is it too much work to read ALL the comments?
My initial comment boiled down to the fact that if you have a strong vested interest in any position on any topic, it is likely that your arguments will be slanted to one position over the other, I love pizza so if someone asks what 'the best' food is, I'm going to argue for Pizza. If you also read further into the comments - and Rob Howard's folow up comments - the validity of Frans's argument is challenged alot! What these comments on my post seem to come down to is that this guy agrees with Frans's position, didn't bother checking the 'facts' presented and therefore chose to take task with my position because he didn't agree with it...fine!

Problems with most blogs...

A comment from Rob Howard (I'll dig out a link later) go me thinking about problems with most blogs. Now, in my every day job I develop community applications, forums and all sorts of similar 'social software systems' one of the big keys to helping discussions to take place it giving a simple path to reach the discussion.
Blogging systems are very different, giving exclusive prominence to the posts, with 'comments discussions' becoming secondary - which frankly is a bit of a shame! So here's the idea, the comments in blogs are essentially single threaded forums (with the initialising message being the original post), what I though I would develop (well once I get my dev machine working properly again...stuipid computers!) is a simple control which can sit in a side-bar displaying the most active discussions. Also some form of notification system, where a user posting comments can optionally choose to have all future replies to the discussion (or simple notification that a reply has been made with a link to the discussion). Problem comes with RSS - would there be any point in providing an 'active discussions' feed, would this even function with RSS readers?

UPDATE: Been having a play with this (the comments tracking stuff) - .TEXT does not make this overly simple (well, not really .TEXT, blogs in general) - the problem boils down to the fact that you're requesting a notificaiton without membership.
Now, there are a couple of ways to do this; since a 'remember me' checkbox exists this could be used as the basis for a rudimentary membership system with the cookie being used as the only authentication mechanism; also, with each notification sent, a URL could be included which would allow the user to 'unsubscribe' from the notification.
I prefer the second option since cookies are just too flaky to be used as an opt-out mechanism (getting deleted, privacy settings etc...). Oddly this is where things like .NET Passport and .NET Alerts come into their own -- and represent a pretty perfect vector for the delivery of such unimportant, transient notifications...so, anyone want to give me a free license for passport and alerts (rough value $20000 :-)), I wish Passport and Alerts were MUCH cheaper, the only sites I've used these systems on are Microsoft's own brand sites and for charities - really a shame, it could be a brilliant system if more developers got interested.
Anyway, I'll look at doing the URL system in the next day or two (just got my dev machine running again so I'm busy installing software right now)

Dumb piece of code...generate ordinals for numbers (th,rd etc...)

UPDATE:  My code below of course has an error (I wrote it to test the perceptive skills of the community ;-)) anyway, Philip Reick commented with a more credible version:

Hmm.. my bet is you came across it again after forgetting it because you threw it away. It would return the wrong result for inputs like "42", "123", "101", etc. I've done that a lot - I save code for some reason even when it's incorrect (like, its the vendor supplied code, or it has some trick in it), then a year later I find it and have to test it all over again because I didn't record WHY I saved it. Useless way to save things, but I have a few bad habits.

Here's one I use often (well, sorta - it's off the top of the head, no compiler here)

private static string GetOrdinal(int number)
{
int place = number % 10;
if( place > 3) return "th";

//special case for teens
int teen = number % 100;
if(teen < 20 && teen > 10)
{
return "th";
}
if( place == 1) return "st";
if( place == 2) return "nd";
if( place == 3) return "rd";
return "th";

 

OK, not the most complex piece of code on the planet, came across it when reinstalling my broken machine.It strikes me as something the Framework may have built in, but I couldn't locate it...Anyway, given an integer, this snippet will return a string with the correct ordinal.

THIS CODE IS INCORRECT! Retained for amusement purposes only :0(
public class OrdinalNumber
    {
        public static string  GetOrdinal(int Number) 
        {
        
            try
            {
                string numStr = Number.ToString();
                // Accepts an integer, returns the ordinal suffix
                //  special case three digit numbers ending
                // with 11, 12 or 13 - ie, 111th, 112th, 113th, 211th, et al
                if (numStr.Length > 2 ) 
                {
                    int intEndNum = Convert.ToInt32(numStr.Substring(numStr.Length - 2, 2));
                    if ( intEndNum >= 11 && intEndNum <= 13 ) return "th";
                        
                }
                if ( Number >= 21 && Number <=23) 
                {
                    //  21st, 22nd, 23rd, et al
                    switch (Convert.ToInt32(numStr.Substring(numStr.Length - 1, 1))) 
                    {
                        case 1: return "st";
                        case 2: return "nd";
                        case 3:    return "rd";
                        default: return "th";
                    }
                } 
                else if(Number >=1 && Number <=3)
                {
                    //  1st to 20th
                    switch (Number) 
                    {
                        case 1: return "st";
                        case 2:    return "nd";
                        case 3:    return "rd";
                        default: return "th";
                    }
                }
                else
                {
                    return "th";
                }
            }
            catch(Exception)
            {
                return string.Empty;
            }
        }
    }

What exactly is the point of ASPInsiders?

A discussion over on Paschal's site on the merits of the ASPInsiders cabal. I honestly don't see the point of this sort of group - what exactly does being a member mean to the community at large (apart from a pretty icon on www.asp.net forums)? Does membership imply that advice from these individuals carries an extra air of authority? I just don't get it...

SQLJunkies...fine, fine blogging site

The SqlJunkies weblog site is really starting to fill out, it's fantastic to have so many SQL experts posting in one place! Oh, and I'm not just saying that because I agree with Donny Mack's views on SPs; well, partially, reporting is still a pain but I had discovered a good link to a version using the SP to generate the Dynamic SQL which seemed like a sound approach.

Delegate.BeginInvoke() and memory leaks...

I'm getting increasingly involved in the world of Asynchrony and have been doing a bit of digging about into some of the pitfalls of multi-threading.
I came across an interesting one today involving the use of BeginInvoke without a corresponding EndInvoke when using delegates...many books (including the one I'm using most right now, the excellent Programming .NET Components by Juval Lowy) mention that a good way to fire events asynchronously (i.e., not blocking) is to simple call BeginInvoke on the delegate - cool seems easy enough!
Well, reading around a bit, I discovered this by Mike Woodring which contains this statement: "Starting with the 1.1 release of the .NET Framework, the SDK docs now carry a caution that mandates calling EndInvoke on delegates you've called BeginInvoke on in order to avoid potential leaks. This means you cannot simply "fire-and-forget" a call to BeginInvoke without the risk of running the risk of causing problems. "
Now, I can't find the bit in the docs which says that, but another article  at O'Reilly mentions the same thing... Well, based on this evidence, it would seem to be a good idea to avoid this potential leak, luckily Mike's stuff has a handily little helper class which supports the 'Fire and Forget idiom' - dead easy, now I can have lovely fire and forget calls without worrying about unintended leaks :-)

UPDATE: Found the doc reference, if you have MSDN it's here, if not the on-line version is here

Search gone for the time being...

Just updating the user control...back in a couple of days..
UPDATE: Well, soonish...stupid dev machine is playing up...

Feeling inadequate...

Everyone is posting pictures of their workspaces...I'm starting to feel more than a little inadequate...at work I use two monitors, at home just the one; would be two but I don't have the space...so just one and a KVM for accessing my other machines - now I know there was an article about how multiple monitors increase productivity - but frankly a bit more space would help more :-)

Great post on the homeless Children of Miami and their belief system...

This article is just an amazing read, the creation of a mythic landscape helping children to cope a little better with being on the streets - nabbed from Kuro5hin

Just noticed a flaw in the comments submission...stupid client side validation!

Fix it tonight...sorry for any inconvenience! If you want to submit a comment, enter any old thing in the search box for the moment...sorry!

Stored Procedures versus Dynamic SQL - the old debate...Frans Bouma's take...

Frans Bouma really doesn't see the point of using Stored Procedures over using Dynamic SQL - so Frans, what's your take on such things as Indexed Views and User Defined Functions - which are essentially SPs but there's no equivalent for Dynamic SQL, so you're suggesting I should not use these any more?
To be honest I'm always a bit reticent to pay much credence to an argument on an approach to Data Access from someone who has a vested interest (I know LLBLGen Pro supports SPs but it does have a strong bias towards Dynamically Generated T-SQL), kinda like MS on the Linux debate...slight vested interest (or former Halliburton CEO on Iraq - but that's a different matter :-))
I do use SPs almost exclusively for Data access, I have no vested interest in one approach or the other, I used to use Dynamic SQL in the bad old days of ASP/VBScript but switched to SPs when I needed more oomph in my data access code. I have a strong preference for manipulating data using Set based logic, yes, for more complex operations I'll bring the data into code but in general, I use the DB for manipulating and then return the smallest amount of data back to code. The reason I do this isn't stubbornness, simply I find it easier to filter and composite my data closest to it's source.
I also find some of Frans's arguments a bit lacking, there is an argument for using Dynamic SQL where you have to react to user input for filtering data; reports are a classic example where you might want to find  matching data items based on a variable number of inputs - by all means use Dynamic SQL for that, but in 90% of cases I just want to pull data from a DB as quickly and painlessly as possible this is where I'd use SPs. I often use Table variables for compositing and filtering data, treating SPs as set providers and modifying the eventual output resultset to contain only the data I actually need - this would usually require multiple trips to and from the DB (we're talking in the dozens here for each instance) and would be pretty slow, as well as causing heavy network traffic which I can usually ill afford in  highly scalable sites.
In short what I'm saying is that for my purposes, the 90% Stored Procedures, 10% Dynamic SQL works best - making absolute statements about such things is like commenting on religion, politics or Open Source  or Java - I don't believe there is a completely binary argument to be made in any of these areas, there's too many entrenched views - horses for courses is my opinion :-)

Memory Leak - solved - or 'When STAThread Goes Bad'

I posted a little while ago about an odd 'Memory Leak' I was having...well, after several days of trawling (and annoying Data Wanta who's excellent email component I was mistakenly blaming - sorry!), I finally found the answer! Turns out that the little [STAThread] attribute above the main class of the Comand Line app isn't so inoccuous after all - Dave pointed out this thread - apparently there's some sort of bug in .NET  which can lead to what is effectively a leak when using multi-threading in a STAThreaded application!

.NET and Locked Files...

OK, can anyone explain why I can't check explicitly if I can lock a file before reading from it (i.e., check that no-one else is locking the file before trying to read from it). I'm using the marvellous FileSystemWatcher to wait for files being created in a directory before triggering a job - fine but there doesn't seem to be any easy way to check is a file is 'readable' before starting to read... Right now my way of doing this task is to attempt to read - and place a Read lock - on the file using the FileStream  and catch the error it throws when the file is locked by another process...like so...but this really doesn't feel right. I balk at the idea of using exceptions (which are also REALLY slow) for this kind of task...why doesn't FileStream.CanRead check for locks BEFORE opening the file???

        private static int m_ReadAttempts = 0;
        private string  ReadFileFromDisk(string filePath)
        {
            try
            {
                if(!File.Exists(filePath))
                {
                    MessageBox.Show("Sorry, but the file specified " + Environment.NewLine + filePath + Environment.NewLine + "Cannot be found");
                    return string.Empty;
                }
            using(FileStream fs = new FileStream(filePath,FileMode.Open,FileAccess.Read,FileShare.Read))
                {
                        using(StreamReader sr = new StreamReader(fs)) 
                        {
                            string tmpStr = sr.ReadToEnd();
                            sr.Close();
                            m_ReadAttempts =0;
                            return tmpStr;
                        }
                
                }        
            }
            catch(IOException ex)
            {
                    if(m_ReadAttempts < 10)
                {
                    Thread.Sleep(500);
                    m_ReadAttempts++;
                    return ReadFileFromDisk(filePath);
                }
                else
                {
                    throw ex;
                }
            }
        }

Longhorn install on VMWare 4.0

Well, went very smoothly - just got the DL off of MSDN subs downloads, mounted the iso as a disk for VMWare, fired it up in "2003 Server" config - installed perfectly! Seems to be better connecting using Terminal Services (RDP) - installing Whidbey now - gotta say, VMWare just kills VirtualPC right now...the current VPC doesn't event pretend to be able to run Longhorn, VMWare is pretty seamless, can't wait to try 2004 now that MS will be 'enhancing' it...I realise there's too many of this type of post around at the moment, sorry for adding to the swarf!

UPDATE:  Umm...may have spoken too soon, left for work with Whidbey just about installed, came back and my machine has 'Press a key to reboot' showing....over and over again...hmm...bit worrying! Oh, and the MSDN discs arrived today as well - no Yukon annoyingly!

UPDATE UPDATE: May not have been Longhorn's fault - looks like my main hard disk is on the point of failing (thanks to the SMART prompt when I rebooted) - seems like my bulk mail test (where I wrote 3 million files to disk and deleted them again) may have been a bit too much for the poor thing... 

Puzzled by memory usage...

I have this command line app, when running in a 'normal' command window, it uses a fair whack of memory (around 60mb), but the second I minimize to taskbar, the memory usage drops to around 10mb....anyone any ideas why???

UPDATE: Apparently this has to do with 'Working Set size", it's generally nothing to get concerned over...there's a pretty good discussion here on pretty much the same topic...

Occasional blogger....and a book suggestion...

I'm in one of my quieter periods when it comes to blogging right now...I have no particular excuse, I am just a bit phasal when it comes to such things. Anyway, I'll give a suggestion as to some reading material whilst you are deprived of my non-sensical mutterings - the His Dark Materials trilogy by Philip Pullman, mid-way through the third book (the Amber Spyglass). This is a pretty amazing triology, I'd even say it approaches The Lord Of The Rings in it's scope - and, dare I say is even superior in many ways; not so much dumb signing or 'we're travelling' bits. It's essentially an exploration of some of the central themes of religion; as usual reviled by some 'christian' types - who seem to have entirely missed the point of the story...Anyway, fantastic read, great trilogy. Please don't believe some reviews which claim 'it's not for children', if ever there was a book that children should read it's these, they are deep, multi-layered books which explore some of the core fears which many children have about growing up...oh, and it's a great adventure story for adults too!

Name that lyric...

"Don't you think it's kind of funny, don't you think its kind of sad, the dreams in which i'm dying are the best I've ever had..."

What I've been up to...sending Bulk Email from ASP.NET / Command line / Schedule

Been a bit quiet of late, well basically I've been starting a new project at work - so I've been pretty much 24/7 in planning and building that app. It's a pretty cool little Bulk Email app (don't worry, for strictly opt-in mails :-)). A couple of the bits I've been using in this app are really useful in general, Mike Woodring's Custom ThreadPool, this is just a remarkably useful little class when you want to do Asynchronous operations from within ASP.NET (see this for more details on some of the places you may want to do this).
Esssntially within the application, I accept a large(ish) XML file which contains details for users (using “18000 in my test file), parse it; using XmlTextReader, the performance and memory usage of this class is just stunning, it can work through this 200000+ line file in less than a second (not too exact, don't have timing on there yet) and populate an object containing an arraylist of multiple DataTables. I have vastly underused DataTables in the past, but they are just incredibly useful for holding arbitrary data, and really easy to build dynamically. This object can then either be serialized to disk (allowing for scheduling for a later send) or fired to my mail controller immediately, this essentially spins up n threads to handle the mail sending operations (allocated from a static thread pool). The component I use for actually doing the mail merge is the excellent AspNetEmail form AdvancedIntellect , now I can't say enough about this product (I found what appears to be a very minor bug with the 'send status' but have yet to confirm this...). What I can do with this is, pass a DataTable (you can also pass a DataSet or SqlDataReader), fill in some fields and let it work through the table sending emails, with the class calling back into my code to give details on each send - very nice!
Anyway, I'm now working on reporting functionality for this app and 'tweaking' (currently hits “200 mails/second limited by the file-system, can do “1100 mails/sec if the file system is taken out of the equation) - have to say it's been a lot of fun, the multi-threading capabilities of .NET have really impressed me lately - my new favourite feature :-)

Also been to an MSDN roadshow today hmm...can't say it was the best use of my time, HEAVY on the marketing spiel, very low technical content, basically they were showing off .NET technology at a 'managers' level - very tedious...the Smart Client stuff using Office 2003 was pretty interesting though...got a new respect for InfoPath...

Updater block and Windows Update under threat?

As I've posted many times, I'm a relative novice when it comes to all things WinForms, this post on Slashdot got me thinking, isn't 'Updating an Application over the Internet' exactly what the Updater Application Block and Windows Update do, not to mention every antivirus vendor on the planet. The US really has to get all this nonsense with software patents sorted before it grinds the whole industry to a halt!