Archives

Archives / 2004 / July
  • Blackberries get no love on Guam...damn

    I got word from a friend of mine that's running one of Guam's wireless Internet access services that Blackberry devices aren't going to be supported anytime soon or in the near future.  I've been evaluating a couple of smartphones for GuamCell Communications for the past couple of weeks, and after putting them through the wringer, decided that perhaps the Blackberry was the best way to go for my company.

    Unfrotunately, they apparently require some network doohickeys and protocol thingamajigs that I won't pretend to understand.  I'm really not after a PDA or PIM device...just more of a mobile communications applicance that gets on the true World Wide Web, not WAP.

    I guess it's more cold showers for me...

    Read more...

  • Emulating PhotoShop Actions programmatically in ASP.NET with GDI+

    Being in the broadcast media business, among the most critical assets we have is the timely distribution of imagery.  And one of the "happy little accidents" I so often come across is when people e-mail images of varying size and resolution, both outside of as well as within the hallowed halls of my organization.  We constantly get tons of graphics submitted to us from viewers, from other affiliate stations, and from the networks, as well as passing things we shoot out in the field and that we find on the Web along to each other.

     

    Professional organizations send stuff in all sorts of quality levels, sometimes with monstrous file sizes.  And Joe Average typically doesn't have the equipment, know-how or technical congeniality to resize/rescale/resave the cool family photo he took on the digital camera his wife gave him.  He just wants to see it on the Web.  And there's nothing I hate more than having to painfully sit and wait while I download a 9MB e-mail message containing a 1600-x-1200 JPG.  Ouch.

     

    The relative chaos of dealing with non-standard images quickly gets messy and needlessly cumbersome.  You can set de facto rules on image dimensions and resolutions, but people just won't budge, resulting in large pictures that need to be scaled down, scaled up, shrunk and morphed every which way.  It's unreasonable to expect people to conform to a standard, so that's when the magic of technology comes in.  This normally requires a graphic artist or person in the know to (1) be present and available, (2) fire up a graphics application like Adobe PhotoShop to do the work and (3) manipulate the images to get them in the right format(s).  And the bigger the batch of images, the larger and more time-consuming the job.

     

    Obviously, such a solution is still dependent on a human being, which introduces ambiguity into the equation.  So to optimize processes further, I do everything in code with ASP.NET and GDI+ to programmatically emulate such tedious and often laborious tasks. 

     

    Most people (myself included) get this type of work done by using PhotoShop Actions.  For those of you not in the know, Actions are basically PhotoShop's moniker for macros, empowering a graphic artist with the ability to define a seemingly limitless number of operations, which will later be aggregated/executed with a single-click.  So you can define a series of instructions that set up templated formats for images for use on the public Web, within a LAN, on television, in print advertisements, and suitable within e-mail messages, each taking into consideration a particular medium's idiosyncratic display and distribution constraints.  In this example, we'll do this in code. 

     

    The syntax below preps an image submitted via an ASP.NET WebForm and preps it in a suitable Web format with certain constants:

    • Must be a .JPG
    • Must not be larger than 80K
    • The quality level of the JPG is set to 30
    • The resolution of the image is 72 dpi
    • The image uses high-quality interpolation
    • The image's width can be no larger than 350 pixels

     

    Rather than saving the submitted image directly to disk or posting it in a database, the code first emulates the operations we use in internally in a PhotoShop Action to prepare it to conform to our spec list.  Only after the image is prepped, it's saved as a byte array within a SQL Server database table field of type IMAGE.

     

    private void btnSubmitImage_Click(object sender,EventArgs e)

    {

        // get the stream of data for the image from a server-side Form with an <INPUT> control with an ID of inputUserSubmission

        int length = (int)inputUserSubmission.PostedFile.InputStream.Length;

        byte[] imageBits = new byte[length];

     

        // read the digital bits of the image into the byte array

        inputUserSubmission.PostedFile.InputStream.Read(imageBits,0,length);

     

        // save the byte array as a Bitmap object

        MemoryStream ms = new MemoryStream();

        ms.Write(imageBits,0,imageBits.Length);

        Bitmap unrenderedImage = new Bitmap(ms);

        ms.Close();

     

        // manipulate the image according to the specification and save it to the database

        WarpImageDimensions(unrenderedImage);

    }

     

    private void WarpImageDimensions(Bitmap imageToSave)

    {

        /* RE-SIZE THE IMAGE ACCORDING TO A FIXED WIDTH OF 350 PIXELS */

        Bitmap resizedImage = ResizeSubmittedImage(imageToSave);

     

        /* SET THE RESOLUTION OF THE IMAGE TO 72dpi */

        const float res = 72;

        resizedImage.SetResolution(res,res);

     

        /* SET THE INTERPOLATION MODE */

        Graphics g = Graphics.FromImage(resizedImage);

        g.InterpolationMode = InterpolationMode.HighQualityBicubic;

     

        /* RE-SET THE IMAGE'S COMPRESSION QUALITY TO "30" */

        EncoderParameters encoderParams = new EncoderParameters();

        long[] quality = new long[1];

        quality[0] = 30;

     

        EncoderParameter ep = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality,quality);

        encoderParams.Param[0] = ep;

     

        ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();

        ImageCodecInfo jpegICI = null;

     

        for(int x=0;x<arrayICI.Length;x++)

        {

            if(arrayICI[x].FormatDescription.Equals("JPEG"))

            {

                jpegICI = arrayICI[x];

                break;

            }

        }

     

        MemoryStream mem = new MemoryStream();

        resizedImage.Save(mem,jpegICI,encoderParams);

     

        /* SAVE THE IMAGE TO THE DATABASE AS A BINARY BYTE ARRAY */

        byte[] bits = mem.ToArray();

        // do database INSERT operations into DB field of type IMAGE here

     

        mem.Close();

        g.Dispose();

    }

     

    private Bitmap ResizeSubmittedImage(Bitmap bmpIn)

    {

        // re-size a submitted image while maintaining its aspect ratio

        Bitmap bmpOut = null;

        int newHeight = 0;

        int newWidth = 0;

        const int fixedWidth = 350;

        const int fixedHeight = 200;

        decimal ratio;

     

        // if the image is too small, then just use it as is

        if(bmpIn.Width < fixedWidth)

        {

            ratio = (decimal)fixedHeight/bmpIn.Height;

            newWidth = Convert.ToInt32(ratio*bmpIn.Width);

            newHeight = fixedHeight;

        }

        else

        {

            ratio = (decimal)fixedWidth/bmpIn.Width;

            newHeight = Convert.ToInt32(ratio*bmpIn.Height);

            newWidth = fixedWidth;

        }

     

        bmpOut = new Bitmap(newWidth,newHeight);

        Graphics g = Graphics.FromImage(bmpOut);

        g.FillRectangle(Brushes.White,0,0,newWidth,newHeight);

        g.DrawImage(bmpIn,0,0,newWidth,newHeight);

        bmpIn.Dispose();

     

        return bmpOut;

    }

     

    The advantage to this type of programming is visible when the distributed nature of the need for imagery kicks in.  The base logic can be implemented within an XML web service, so that savvy distant-end developers at business partners can build upload clients in whichever platform they're most comfortable with and get the image to you.  For those not-so technically inclined, you can still build a simple ASP.NET image upload client that takes advantage of the HttpPostedFile class for them.  In your internal apps, you can easily create a custom HttpHandler to display the image within a databound List control like a DataGrid or Repeater. 

     

    Using an HttpHandler is a little more work than just referencing an image stored on a server's filesystem, but the advantage is that you can store previously-viewed images in the .NET Cache API, reducing the total amount of actual database traffic and really improving the user experience when viewing large amounts of images.  (Shameless plug: read my article on MSDN about caching data across multiple platforms for more on this subject.)

     

    I've also been forced to come full circle in building tools to help people out.  I tried so hard to get people away from the mindset of having to use their Inboxes to send images, but I finally gave in - it's just the way people do things.  So I'll bend.  I've started extending part of the transmission feature using the Web Service Enhancements 2.0, allowing an XML web service based on similar code to be callable from non-HTTP clients, specifically through e-mail, facilitating SOAP communications through SMTP.  This is based loosely on the SOAPMail sample project. 

     

    I've also built smart clients that upload images raw and use code not unlike that mentioned here and perform such rendering on the client itself, performing adaptive rendering based on the calling platform/device. 

     

    It's really quite cool when you put this type of code into production.

     

    Acknowledgement: even though I assembled a bunch of ideas and concepts into a single service, the crux of the work with the graphics interface wouldn't have been possible without great contributions from Rick Strahl and Chris Garrett, whose wrote outstanding work on the resizing algorithm and programmatically setting the JPG compression levels, respectively.  Both have fantastic pieces on using GDI+ in ASP.NET applications.  So thanks guys for getting the ball rolling on this one. 

    Read more...

  • Dan Wahlin saves my sorry, ignorant butt once again

    I've lost count of how many times Dan Wahlin, either directly through e-mail or indirectly through his writing, has helped me out with XML-based problems in my projects.  I was able to tap Dan's wisdom yet again this morning as I sussed out a nagging problem with inferred schemas and XML's nature to assume all fields are strings in lieu of a more formal validation structure.

    I was able to figure out a curious problem I had with overriding the default inferred XML schema applied to a DataSet, which was ruining what was intended to be numeric sorting.  I took a look at Dan's timeless, seminal work "XML for ASP.NET Developers" and literally slapped myself up the head when I discovered found 2 key points:

    1. the XML Schema needs to be loaded first into a DataSet before the XML itself is read into the DataSet (not the other way around)
    2. you need to call DataSet.AcceptChanges() - D-UH!

    I was previously trying unsuccessfully to apply conditional XS:INT and XS:DOUBLE typing to certain fields using the following construct:

    DataSet ds = new DataSet();
    ds.ReadXml(Server.MapPath("results.xml"));
    ds.ReadXmlSchema(Server.MapPath("results.xsd"));
    ds.WriteXmlSchema(Server.MapPath("results-2.xsd");


    ...and here's the code that got it working:

    DataSet ds = new DataSet();
    ds.ReadXmlSchema(Server.MapPath("results.xsd"));
    ds.ReadXml(Server.MapPath("results.xml"));
    ds.AcceptChanges();

    Then, running a test with WriteXmlSchema() shows the data typing has taken effect, and the page in which the code executes clearly shows that the data is properly sorted numerically. 

    Thanks Dan!  I owe you some serious BBQ if you ever head out this way!

    Read more...

  • Mike Hall rules on SportsCenter

    Mike Hall, the 22-year-old winner of ESPN's Dream Job contest this past March, started in his first rotation with SportsCenter, the network's flagship program this week.  And he's totally been impressive.  Good suits, good jokes, not trying to be too over-the-top right out of the gate, he's held his own while being a good co-host.

    Heck, I've been anchoring news & sports for 5 years, and I picked some things up from the kid.

    Go on with your bad self, Mike...kick ass!

    Read more...

  • Do you talk to your code?

    Being a musician, I've learned that only after reaching the point of maturity in your own skill set in general and in particular with an instrument, do you develop a relationship that exponentially amplifies your ability to create.  Most expert players can all attest to the quasi-sexual experience one can have while playing a certain song with a certain instrument - it's been said that the great B.B. King openly cries each and every time he performs "The Thrill is Gone" on his prized Lucille.  There's a real emotional bond created between man and machine.

    As a software developer, I've bonded with the syntax to which I affix myself for countless hours.  Some programmers talk to their PCs....I talk to my code.  I see the machines on which I work as vessels for the real tool...the code itself, and I get right into conversations with my beloved scripts.  I've found it helps the productive process to engage in a running narrative that serves to aide as a self-imposed quality control mechanism, if you will.  And I don't assume I'm alone. 

    I find myself having a tendency to be quite vulgar when working on silly, mundane helper methods (like string manipulation routines), while I'm more loving and affectionate with ADO.NET and database communication code, and downright abusive and demeaning when it comes to XSLT.  In contrast, I'm totally submissive and "whipped" when it comes to anything JavaScript (largely because I suck at it). 

    How about you?

    Read more...

  • Good God, I'm a geek...

    I was walking through a local mall this evening after doing the 6PM news, and I in so doing, was carrying around no less than 3 mobile devices: my personal LG LX5450 cell phone, my work-assigned 2-way radio/cell phone and my new Audiovox Thera, which I'm test driving for some friends at a local telecomm company.

    The fact that I had 3 devices of varying size, weight and color dangling from my belt didn't shock me...the fact that I actually didn't think twice about carrying so much hardware on my person does.  Nowadays, it's not uncommon to see people sporting a pager, cell and/or radio, but I just damn looked odd.  And I became immediately aware of this as I passed a window with reflective tint.  I tried in vain to reconfigure the arrangement of my digital appendages, but I think by that point it was too late.

    Hell, I got a call and even I couldn't tell which device it came from!  Maybe it's time to invest in one of those man-purses. 

    Read more...

  • I gots me some smartphones to play with...

    One of Guam's premiere telecomm companies, GuamCell Communications, was nice enough to let me borrow two brand-freakin'-new smartphones, the first to be released for public sale on Guam.  I got my hands on the Audiovox Thera PocketPC with the latest version of Windows CE and the Treo 600  with the latest PalmOS. 

    I'm supposed to test/evaluate/criticize/compare/contrast the units and their relationship with Guam's new wireless data services for the TV segment on technology I host every Tuesday, “Tech Talk with Jason Salas.“  It's basically me being goofy and playing with different toys, and trying to explain complex concepts in plain English.

    I admittedly haven't played with the PalmOS since the grayscale days of my old Palm III, and since joining the Church of Gates, I've naturally been playing with and developing for Windows operating systems.

    I'm lucky to have friends in the know...my good friend Jamil Justice is my company's creative director, and as an artist, is (surprise, surprise) a Mac guy.  And as such, he's more inclined to the Palm stuff, so we're going to do a tag team report next week.

    In the meantime, it's hella fun playing with this stuff.  I'm already building some administrative services to run over the phones, since they can both tap the actual World Wide Web, not a WAP offshoot.  And I've been working with GuamCell on developing a business plan for hosted LAN services, wherein they provide a private gateway to a library of apps we write and host for our network ff of our web server. 

    If I can ever stop playing MP3s on the Audiovox unit, maybe I'll get around to working on the story...

    Read more...

  • If tuna is brain food, salmon's a lobotomy

    I read something years ago that touted tuna as being brain food.  Well, salmon must be the polar opposite, because after a spicy salmon salad from one of my favorite local health bars, Synergy Studios, I couldn't think of a damn thing.  And I was working on a pretty non-complex project.  The old grey matter upon which so much of my work is based just wasn't firing

    I gave up eating red meat for lunch a few months back, and it really has helped with keeping my energy levels high (for a challenge, try going out for a steak lunch in the middle of a busy day and then try to do ANYTHING productive for the rest of the day).  You'll drag-ass like never before.

    Anyway, a couple trips to the drink machine for some Mountain Dew and King Car Ice Tea and I was back firing neurons...sort of.  We don't get Mr. Pibb out here, and I don't drink coffee, so I get my caffeine where I can.

    Read more...

  • Great moments in Web history: the dude who "developed" alternating table row colors

    I'm completely lost when it comes to determining exactly who came across the notion of using alternating row colors in large lists of tabular data - something that's become a practice in such great use that one would assume that it would wear out its welcome, but most definelty not.  But we would all be wise to tip our collective hat to this person for their discovery.

    I recall the early days of ASP 3.0 when the only thing I'd ever use modulus logic for would be to assign BGCOLOR=“#CCCCCC“ to odd-numbered rows.  As alternating row formatting became more popular based on its relative ease of setting up and dynamic results, people started creating components and DreamWeaver plugins just to do it!

    My best guess would be to assume that someone in the Web community around 1999 started putting old Excel report formatting tricks to use within web documents.  Heck, the practice became so widespread, a big draw for people just getting into ASP.NET is the fact that the platform makes automates the formatting of such considerations in the List web server controls for those of us who latched onto the “every-other-row-looks-different” mentality.

    Jakob Nielsen would (should) be proud.

    Read more...

  • I keep wanting to develop WinForms apps...but then I don't...

    I'm a web developer, hard to the core.  Every few months, I get the “expand thine own skill set” bug and start to dabble in Windows Forms programming, but then almost as quickly dismiss it because it's so damn hard and frustrating. 

    Label me impatient and/or ignorant, but sometimes, I don't want to build every single menu, MDI element or be responsible for doing the simple-yet-complex computations required to get the precise positioning of controls on a Windows application.  It's then when I realize what a blessing we have with the browser being pre-built, and then re-commit myself ot my chosen craft. 

    At least for another few months.

    I'd venture to say that there are a significant amount of desktop/console devs that do web stuff that the converse, and this shouldn't come as a surprise to anyone.  And if you're a server-side developer on any platform (ASP, ASP.NET J2EE, PHP), there are more than enough topics to keep you from becoming bored with the redundancy of HTML and writing programs that generate it.  And heck, innovations in web technology are bridging the divide between what's truly “desktop only” capability and that which can be deployed, managed and accessed via the Web.

    Count your blessings, and praise the almighty URL.

    Read more...

  • So that's what RAM's used for...

    I've been jamming on an app for the last 2 months, a big voter update process that we're only going to use once to keep voting totals in synch across multiple platforms.  The one thing that's bewildered me has been the painfully slow-ass performance. 

    In tests on my staging server (a WinXP Pro box w/256MB of RAM), the process cycled through more than 100 candidates and updated a DataSet...and took about 19 seconds to do so.  Which totall had me stumped.  It was a somewhat large job, but nothing extraordinary, and not really that daunting for a processor.  It just ran slow.  I even rebuilt it using a SqlDataReader (I'm using a SqlDataAdapter now), and it still wouldn't fly fast enough/

    I finally said “forget it” (but I didn't really say “forget“) and deployed the app to my production server, which sports a couple of gigabytes of RAM and multiple monster processors and the same process ran, without any modifications in about 2 seconds!

    D-uh!

    Read more...

  • An homage to Jonathan Goodyear - creator of the *first* ASP.NET blogging app

    I know I'm likely going to get flamed for this for historical accuracy, but I'd like to take a moment to acknowledge the early work of ASP.NET pioneer Jonathan Goodyear, who many of you will know from his AngryCoder site and many more will know from his BackDraft column in ASP.NET Pro Magazine.  He's among the most prolific contributors of content - nice or nasty - in the ASP.NET community. 

    It just dawned on me now that Jon may have been the first person to develop what was at the time the first widely-used weblogging application. 

    With apologies to Scott Watermasysk, who has now joined forces with Rob Howard at the latter's startup company Telligent Systems (there's a solid group of core employees right there), whose own homegrown blogging app, .Text, revolutionaized the way the Microsoft development community communicates and is arguably THE single greatest personal achievement in ASP.NET over the last year, Jon's early work set the standard for publishing article-based content to the 'Net using ASP.NET technologies.

    Circa 2001, Jon built one of the first community-oriented sites using 100% ASP.NET.  In meeting Jon during the late stages of ASP.NET 1.0 Beta 2, he shared his code with me, which was brilliant and inspiring for my own projects in developing interactive, article-based systems.  The ability to empower content authors to connect directly with their readers and vice-verse really changed the way we in the media business have approached writing.

    Sure, the AngryCoder publishing system wasn't fully automatic, but the first-generation of any new ideas that can be considered as paradigm shifts usually are.  Jon's original article publishing framework required outside authors to format their submissions in HTML, asserting their own line breaks and referncing classes that conformed to CSS rules Jon defined.  It also had the limitation (or quality control caveat, depending on what side of the bed you rise) of requiring Jon's personal review/approval, but it did work beautifully and was pretty cool.  Especially for outside writers like me, just getting into the game.

    But one of the key features - giving people the ability to post comments on certain articles, and then e-mailing that article's author - is a mainstay of the modern blog on any platform.  It surely wasn't an overtly original idea, and was an evolution of the BBS'es and guestbooks in days of yore, but it was really cool to have that instantaneous interaction.  And it led to the development of much greater things.

    And as do most things, the traffic on and significance of AngryCoder.com has subsided, maybe getting one or two new articles posted every other month.  In its heyday, it got that many every other day.  And its to be expected...hell, we're in the tech field, so brand loyalty, as is true with possessions, is fleeting.  But it was a shining - albeit brief - moment in ASP.NET history we'll all be wise to reflect on.

    And just for those of you who've read this far without falling asleep - Jon also eventually revamped some of his site to include the AngryCoder Blog, to embrace some of the de facto standards of blogging.  Sweet.  :)

    Read more...

  • Do we now say "tab controls" to refer to List controls in ASP.NET? (aka, "Who writes this stuff anyway?")

    I came across a curious headline I was intersted in this morning in the e-mail newsletter for .NET Insight from Fawcette Technical Publications, for whom I've worked as a freelance writer before, doing technical case studies for the publication formerly know as .NET Magazine.

    Anyway, I found this teaser to be intriguing enough to check out:

    "Choose the Right Tab Control"
    ASP.NET's Repeater, DataList, and DataGrid controls display data in a tabular format with various features. Learn which control is the best fit for your app. [Read More
    • Building ASP.NET Web Applications
    • Bind XML Data in ASP.NET
    • Access Contacts Over the Web

    Maybe it was just me, but I've come to associate the moniker “tab control“ to refer more to the TabStrip control of variations of it.  Apparently, whomever wrote the headline thought the “tab” was an acceptable short-form way of saying “tabular control”, which more resembles ASP.NET's List controls (DataList, Repeater and DataGrid), which is what the article and related links provided about. 

    Being in the news business, I've more than made my share of gramamtical/contextual snafus when doing headlines, both in published content and on live television, so I'm not ripping on FTP for getting this one wrong.  And I'm familiar with the company's editorial process, so this might not necessarily be the original intent of the author.  I just thought this was odd.

    Or maybe it is just me...have we in the ASP.NET community started calling List controls “tab controls”?

    Read more...

  • Linking your site's data with a Calendar control for data-searchability

    I added new value to my site's intra-search capabilities by writing a small, single-page “app” this weekend that's already proven to have amped usability and traffic, by allowing people to do date-centric searches.  It basically links a Calendar control to my news database, returning the stories we've published for that day.  In the news business, this is a critical element to have that many site's either under-develop or completely ignore.

    Enjoy!  Hope it gives you some ideas for your own projects.

    Read more...

  • Making your site's content date-searchable with an ASP.NET Calendar control

    Last Friday before I got on the newsdesk to do my broadcast of the evening news, I had an epiphany.  Last month, I finally got around to doing something I've been meaning to do for months - add full-text search capabilities to the news database for my company's site.  While this has exponentially improved the user experience people have in interacting with us, and has significantly increased traffic - it still wasn't perfect.

    And right before I went on the air, the notion of connecting my site's news articles with a Calendar control hit me.  Simple, easy to use, and instantly effective.  I was able to hammer out the code and get a working search page going in a few hours, and deployed the new service shortly thereafter, to rave reviews from my users.

    We're the type of company that publishes anywhere from 16-25 new stories online daily, so this is the perfect case for daily searchability - we publish often and in enough volume to warrant such an application.  Here's the code that shows how I did it, and note the following features:

    • the Calendar control uses startDate and endDate variables of type DateTime that set a minimum and maximum range of dates wherein users can click (days without stories or days that have yet to pass shouldn't be accessible).  This is all handled in the Calendar's OnDayRender event.  If a user happens to click on a day that's within the acceptable range but for some reason doesn't have any content, in which case an IndexOutOfRangeException would be thrown, a friendly error message is presented, saying there's no data for that day.
    • the code builds multiple Repeater controls programmatically and adds them to a PlaceHolder control on the page, rather than setting Repeaters declaratively.  This is done by instantiating objects of a custom class that derives from the ITemplate interface.  I use this type of construct a lot in data-centric programming, and it's based off of the must-read example by Nikhil Kothari and Mike Pope on MSDN on the subject.
    • content is presented for both single days and for 7-day week ranges, depending on what link within the Calendar the user clicked (an individual date or a week range).  The data is accessed via a stored procedure that conditionally returns data for as many days was requested (1 or 7).  When the SPROC returns a week's worth of stories, it actually executes a batch T-SQL statement that returns 7 recordsets.  This collection is iterated over and bound to the Repeaters within the page.
    • each day's (or week's) content is cached via an entry in ASP.NET's Cache API.  This eliminates the inevitable task of repeated database calls for the same data.  Because this type of thing will inevitably add up, I set the Cache to expire the entry in 20 minutes, and set the CacheItemPriority enumeration to CacheItemPriority.Low to keep things moderate, in terms of memory usage.


    PAGE CODE
    -----------

    <%@ Page Language="C#" ClientTarget="ie5" ContentType="text/html" Trace="false" Debug="false" EnableSessionState="False" EnableViewState="true" %>
    <%@ import Namespace="System.Data" %>
    <%@ import Namespace="System.Data.SqlClient" %>
    <script runat="server">

        DateTime startDate = new DateTime(2004,2,1);  

        DateTime endDate = DateTime.Now;

       

        private void LimitVisibleDays(object sender, DayRenderEventArgs e)

        {

            if(e.Day.Date < startDate || e.Day.Date > endDate)

                e.Day.IsSelectable = false;

        }

       

        private void SelectedDate_Changed(object sender, EventArgs e)

        {

            DataSet ds = new DataSet();

       

            if(ViewState["CurrentMonth"] != null)

                Rundown.VisibleDate = (DateTime)ViewState["CurrentMonth"];

       

            // get a count of the number of days selected to determine if the user picked a single day or a week range

            if(Rundown.SelectedDates.Count > 1)

            {

                if(Cache["DataCalendar-"+Rundown.SelectedDate.ToShortDateString()+"-MULTIDAY"] == null)

                {

                    DataSet cachedData = GetStoryResultSet(true,Rundown.SelectedDate.ToShortDateString());   // the user selected a date range (an entire week)

                    Cache.Insert("DataCalendar-"+Rundown.SelectedDate.ToShortDateString()+"-MULTIDAY",cachedData,null,DateTime.Now.AddMinutes(20),Cache.NoSlidingExpiration,CacheItemPriority.Low,null);

                }

                ds = (DataSet)Cache["DataCalendar-"+Rundown.SelectedDate.ToShortDateString()+"-MULTIDAY"];

            }

            else

            {

                if(Cache["DataCalendar-"+Rundown.SelectedDate.ToShortDateString()+"-SINGLEDAY"] == null)

                {

                    DataSet cachedData = GetStoryResultSet(false,Rundown.SelectedDate.ToShortDateString());   // the user selected a single day

                    Cache.Insert("DataCalendar-"+Rundown.SelectedDate.ToShortDateString()+"-SINGLEDAY",cachedData,null,DateTime.Now.AddMinutes(20),Cache.NoSlidingExpiration,CacheItemPriority.Low,null);

                }

                ds = (DataSet)Cache["DataCalendar-"+Rundown.SelectedDate.ToShortDateString()+"-SINGLEDAY"];

            }

       

            try

            {

                pnlStoryArchive.Visible = true;

                lblNoRecords.Visible = false;

       

                for(int i=0;i<ds.Tables.Count;i++)

                {

                    Repeater r = new Repeater();

                    r.DataSource = ds.Tables[i].DefaultView;

                    r.HeaderTemplate = new DailyNewsStories(ListItemType.Header,Convert.ToDateTime(ds.Tables[i].Rows[0]["StoryDate"]));

                    r.ItemTemplate = new DailyNewsStories(ListItemType.Item);

                    r.AlternatingItemTemplate = new DailyNewsStories(ListItemType.AlternatingItem);

                    r.FooterTemplate = new DailyNewsStories(ListItemType.Footer);

                    r.DataBind();

                    placeDays.Controls.Add(r);

                }

            }

            catch(IndexOutOfRangeException ex)

            {

                pnlStoryArchive.Visible = false;

                lblNoRecords.Visible = true;

                lblNoRecords.Text = "There are no entries for " + Rundown.SelectedDate.ToLongDateString();

            }

        }

     

        private void Keep_Months_Visible(object sender,MonthChangedEventArgs e)

        {

            // retain the currently-selected date in the Calendar control so the user won't have to cycle there again after selecting a date

            ViewState["CurrentMonth"] = e.NewDate;

        }

     

        private DataSet GetStoryResultSet(bool IsMultipleDayQuery, string datePicked)

        {

            SqlConnection conn = new SqlConnection("server=localhost;database=<YOUR-DB>;uid=sa;pwd=pwd;enlist=false;");

            SqlDataAdapter da = new SqlDataAdapter("GetCalendarStories",conn);

     

            da.SelectCommand.CommandType = CommandType.StoredProcedure;

            da.SelectCommand.Parameters.Add(new SqlParameter("@QueryDate",SqlDbType.SmallDateTime)).Value = Convert.ToDateTime(datePicked);

            da.SelectCommand.Parameters.Add(new SqlParameter("@IsMultipleDayQuery",SqlDbType.Bit)).Value = IsMultipleDayQuery;

     

            DataSet ds = new DataSet();

     

            try

            {

                conn.Open();

                da.Fill(ds);

                conn.Close();

            }

            catch(Exception ex)

            {

                return null;

            }

            finally

            {

                if (conn != null || conn.State == ConnectionState.Open)

                    conn.Close();

            }

     

            return ds;

        }

     

        /* CLASS TO CREATE REPEATER CONTROL TEMPLATES PROGRAMMATICALLY */

        public class DailyNewsStories : ITemplate

        {

            // data members

            private ListItemType _item;

            private DateTime _dateHeader;

     

            // overloaded constructor

            public DailyNewsStories(ListItemType item,DateTime dateHeader)

            {

                this._item = _item;

                this._dateHeader = dateHeader;

            }

     

            public DailyNewsStories(ListItemType item)

            {

                this._item = item;

            }

     

            // implement the sole interface method

            public void InstantiateIn(Control container)

            {

                Literal lit = new Literal();

     

                switch(this._item)

                {

                    case ListItemType.Header:

                        lit.Text = "<table style=\"padding-bottom:35px;\" width=\"100%\" cellpadding=\"11\" cellspacing=\"3\" border=\"0\"><tr>\n\t\t<th align=\"left\"><hr style=\"padding-top:35px;\" size=\"1\" align=\"left\" width=\"85%\" color=\"#000080\"/>" + string.Format("{0:D}",this._dateHeader) + "\n\t\t</th>\n\t\t</tr>";

                        break;

                    case ListItemType.Item:

                        lit.Text = "\n\t\t<tr style=\"background-color:#f1f1f1;font-size:7pt;\">\n\t\t\t<td align=\"left\"><b><a href=\"http://www.yoursite.com/detail_page.aspx?id=";

                        lit.DataBinding += new EventHandler(lit_DataBinding);

                        break;

                    case ListItemType.AlternatingItem:

                        lit.Text = "\n\t\t<tr style=\"background-color:#ffffff;font-size:7pt;\">\n\t\t\t<td align=\"left\"><b><a href=\"http://www.yoursite.com/detail_page.aspx?id=";

                        lit.DataBinding += new EventHandler(lit_DataBinding);

                        break;

                    case ListItemType.Footer:

                        lit.Text = "\n\t\t</table>";

                        break;

                }

     

                // add the control to the Control tree

                container.Controls.Add(lit);

            }

     

            private void lit_DataBinding(object sender,EventArgs e)

            {

                Literal lit = (Literal)sender;

                RepeaterItem container = (RepeaterItem)lit.NamingContainer;

     

                lit.Text += DataBinder.Eval(container.DataItem,"StoryID") + "\">" + DataBinder.Eval(container.DataItem,"StoryTitle") + "</a></b><br/>" + DataBinder.Eval(container.DataItem,"StoryBody") + "</td>\n\t\t</tr>" : "</td>\n\t\t</tr>";

            }

        }

    </script>
    <html>
    <body>
        <form runat="server">
            <body style="font-family:Verdana;font-size:9pt;color:#000000;">
                <center><b><font size="5">Search our archive by date</font></b>
                    <br />
                    Select a date from the calendar below to see that day's stories
                    <hr size="1" color="#000080" width="85%" align="center" />
                </center>
                <br />
                <asp:calendar id="Rundown" selectionmode="DayWeek" selectweektext="Select entire week" onvisiblemonthchanged="Keep_Months_Visible" onselectionchanged="SelectedDate_Changed" ondayrender="LimitVisibleDays" showtitle="true" runat="server" firstdayofweek="Monday" borderwidth="2px" backcolor="white" width="300px" font-size="7pt" height="180px" font-names="Verdana" bordercolor="#999999" borderstyle="outset" daynameformat="FirstLetter" cellpadding="4">
                    <todaydaystyle backcolor="#cccccc" forecolor="white" />
                    <selectorstyle backcolor="#cccccc" />
                    <nextprevstyle verticalalign="Bottom" />
                    <dayheaderstyle font-size="7pt" font-bold="true" backcolor="#cccccc" />
                    <selecteddaystyle font-bold="true" forecolor="white" backcolor="#666666" />
                    <titlestyle font-bold="true" bordercolor="black" backcolor="#999999" />
                    <weekenddaystyle backcolor="#ffffcc" />
                    <othermonthdaystyle forecolor="#808080" />
                </asp:calendar>
                <br />
                <asp:label id="lblNoRecords" forecolor="red" runat="Server" />
                <asp:panel id="pnlStoryArchive" runat="Server" visible="false">
                    <asp:Placeholder id="placeDays" runat="server" />
                </asp:panel>
            </body>
        </form>
    </body>
    </html>

     

    STORED PROCEDURE

    CREATE PROCEDURE GetCalendarStories
    (
     @QueryDate  SMALLDATETIME,
     @IsMultipleDayQuery BIT = 0

    AS
    DECLARE @incrementor INT
    SET @incrementor = 1

    IF @IsMultipleDayQuery = 1
     BEGIN
      -- get the first story for the latest day in the week
      SELECT StoryID,StoryTitle,StoryBody FROM StoryTable WHERE StoryDate >= @QueryDate AND StoryDate < @QueryDate + 1;

      -- get the remaining stories for the week, counting forwards
     WHILE @incrementor <= 6
     BEGIN
      SET @QueryDate = @QueryDate + 1
      SELECT StoryID,StoryTitle,StoryBody FROM StoryTable WHERE StoryDate >= @QueryDate AND StoryDate < @QueryDate + 1;

      SET @incrementor = @incrementor + 1
     END
    END
    ELSE
     BEGIN
      SELECT StoryID,StoryTitle,StoryBody FROM StoryTable WHERE StoryDate >= @QueryDate AND StoryDate < @QueryDate + 1;

     END
    GO

    Read more...

  • My paradoxical Microsoft MVP existence

    The last 9 months have been pretty interesting for me.  Last December, Rob Howard let me know that I'd been nominated for Microsoft Most Valuable Professional (MVP) status for my work with ASP.NET, which admittedly was in ad hoc evangelism by way of book reviews, community interaction and I assume just being a nice, non-confrontational guy. 

    I got the nod in January, for which I'm still totally blown away by.  That I can, in any capacity, be mentioned in the same breath as Alex Lowe, Steve Smith, Marcie Robillard, Julia Lerman, Rob Chartier and countless others I've come to know and can call friends blows me away.

    The flip side of a very unexpected coin was that I'd not really proven myself with any technical merit, more I'm assuming on my tireless penchant to help people like me.  I'll be the first to admit that I'm not among the most astute of programmers.  I like to think I know a little about a lot, but there are hordes of devs way better than I am at crunching syntax.

    This was one of the high points of my career.  But the times have changed and priorities have shifted, as they're so prone to do, and with this being an year featuring the Olympics, local elections and projects up the wazoo for my company, I've had to sadly regress from my community involvement and get more involved with, well...programming.

    Aye, there's the rub.

    I've really been hammering out page after page, library after library, jamming out some truly fun projects.  I've learned a phenomenal amount in the last 8 months since starting what's become my most technical work to date.  I can honestly say I've worked both progressively and prolifically - something I haven't been able to do in years.  But the bad thing is that I've not been as involved with the ASP.NET community as I used to be, now showing up sparingly in the ASP.NET Forums or in the ASPAdvice mailing lists.

    I also haven't played with the free alpha bits I get as an MSDN member, nor have I been able to give feedback or make bug reports as I so often did in years past.  It's just been one of those years.  No regrets - my career, like science, marches on.  I'm 1000% times better at developing really cool, really valuable ASP.NET stuff, and that feels good.  I just feel like I haven't done the program justice after being so generously recognized after years of work and then unfortunately having to flake to hammer out work projects.  Life's funny...only after someone telling me that my efforts to stay active in the community are appreciated do I really take off in my core skill.  Huh.

    I'm not sure if I'll be selected as an MVP again, but it's been a really fun ride.

    Read more...

  • Remember the 80's: the boy in the window from "Three Men and A Baby"

    Do you scare easily?  Does randomness freak you out more than intentional fright?  Do you love the 80's?  Check this out...

    One of the oddest memories of the Decade of Decadence I've got is the boy in the window from the classic comedy “Three Men and A Baby”.  In one scene near the middle of the film, the camera follows actor Ted Danson, panning left-to-right across a living room.  Just seconds later, when panning right-to-left, there's an image of a young boy standing in the window, behind a drape - staring at the camera.  Nothing menacing, nothing intentionally scary - just right into the camera.

    Now, I used to work at Blockbuster and I'd take home 3-4 slasher flicks a night, so I don't scare easily.  But trust me when I tell you that that was THE most frightening thing I've ever seen on film, and I've only seen it twice since...and I won't watch it alone.  I'm typing this alone at work on a Sunday morning and I got chills just as I added the picture above.  Brrrrr......

    You'll likely miss this if watching the film at normal speed or if you're not looking out for it, but as many of my friends and I did one brave night about 14 years ago, we rented the VHS version, and played the pivotal scene in slow motion. 

    Theories abound about what this could have been:

    • some production assistant stuck in a cardboard cutout prop in the shot to be funny, thinking no one would notice
    • a kid on the set stumbled across a live filming and got caught without the editor's noticing in the final cut
    • the kid was actually a boy who died tragically in the apartment in which the film was shot, and the image was his spectre
    • the image was a cardboard cutout of Danson himself, which from afar seemed to look like a boy

    Googling the topic seems to indicate people know about this as an urban myth of film.  To this day, I'm not sure anyone's been able to definitively figure out what it was.

    This also reminds me how you can play the vinyl version of Madonna's “Justify My Love” in reverse, you hear an evil backwards message.  I gotta give credit to my fellow Sideout boy Reuben “The Boy Wonder” Pel for intoducing this factoid to my classmates and I while we rehearsed for our senior production in 1992.

    Read more...

  • Kick-ass cover songs by folks from the UK...and the circle of life

    I fortunately stumbled across an online radio station (whose name I tragically can't recall at the moment), which played a phenomenal 11-minute cover of Radiohead's “Creep” by U2.  It was amazing.  This proved to be prophetically significant, as on the drive home from work I tuned into a local rock radio station (my company's competitor, no less), and heard Radiohead covering “Wonderwall” by Oasis. 

    Which of course, is a name 'borrowed' from an old George Harrison album.   Who was of course, a member of The Beatles.  Who Oasis said they were superior in their mainstream heyday.  Which U2 rightfully chastized them for.

    I'm gonna go rent “The Lion King“ now, continuing this “circle of life“ theme.  :)

     

    Read more...

  • Bad T-SQL, bad: how a date-specific query kept me up half the night

    I learned something new today about doing date-specific queries in T-SQL.  Let me first preface this with the fact that I've never done a date-specific query for a single date, having only ever done so for ranges where a SELECT * FROM TableName WHERE DateField >= '7/15/2004' was ever used.

    Apparently, this doesn't hold true for getting the precise date (at least when working with date fields in SQL Server 2000 of type SMALLDATETIME).  I tried and tried to get the following to work, without any luck:

    SELECT * FROM TableName WHERE DateField = '7/15/2004'

    Here's what I found does work, both returning the same resultset:

    DECLARE @QueryDate SMALLDATETIME
    SET @QueryDate = '7/7/2004'

    SELECT * FROM TableName WHERE [Date] BETWEEN @QueryDate AND DATEADD(day,1,@QueryDate);

    SELECT * FROM TableName WHERE [Date] BETWEEN @QueryDate + ' 00:00:00' AND @QueryDate + ' 23:59:59';

    Weird.  I knew I should have been an encyclopedia salesman.

    Read more...

  • Remember the 80's/90's - The Civil War Chess Set

    One of my favorite memories from the late 80's/early 90's, long before Garry Kasparov began pitting strategic wits against IBM supercomputers, was the Civil War Chess Set.  Basically, the marketing geniuses at Time-Life Books convinced enough people to spend an exorbitant amount of money over an extended period of time in the name of nostalgia and a sense of history. 

     

    In case your memory banks need a quick jog down Amnesia Lane, the Civil War Chess Set arrived in installments (much like Time-Life's other wares), with a beautifully-crafted playing board/carrying case adorned in blue and gray - what else?  Every other month, subscribers would receive at least one hand-crafted, pewter playing piece, classically sculpted to resemble soldiers as pawns, General Custer as king and other notables from the classic chapter in American history.

     

    Comedian George Wallace had a hilarious bit in his act about just how ridiculous such a prospect was – that one would need to wait nearly two full years just to play a game of chess properly.  The mere notion that enough people bought the damn things still cracks me up after all these years. 

     

    I'm not sure if VH1's “I Love the 90's” is currently mentioning this unforgettable stroke of marketing wizardry, but it surely deserves the nod.

    Read more...

  • My next music project: 80's/90's songs featuring the word "love" in the title

    A few weeks ago I started what I considered to be an ambitious side project, collecting the greatest 80's power/monster ballads.  Apparently, many of you felt this was also a noble effort.  J

     

    Now, I'm going to try and take this a step further.  I'm going to try to get a CD together of each and every 70's/80's/90's song with "love" featured in the title.  I was going to include the 60's, but hey…I've got to go to back to work some time.  Now a little about me: I'm a lifelong rocker, but I like all genres of music, so there's some dance, some new wave, perhaps some country, and some Top 40 pop stuff.

     

    Here's what I came up with off the top of my head:

     

    q       Depeche Mode – "Strangelove"

    q       Def Leppard - "When Love & Hate Collide"

    q       Book of Love "I Touch Roses" (OK…this is the band's name, not the song title, but it's a great new wave dance song)

    q       Erasure – "Chains of Love"

    q       Nazareth – "Love Hurts"

    q       Scorpions – "Lovedrive"

    q       Scorpions - “Still Loving You“

    q       Def Leppard - “Love Bites“

    q       Kiss - “I Still Love You“

    q       Kiss – "Love Gun"

    q       Tesla - “Love Song“ (these guys started gigging on Guam in the 80's!  For realz!)

    q       Saigon Kick - “Love is on the Way"

    q       The Cardigans – "Lovefool"

    q       Pantera - "This Love"

    q       Motley Crue – "Too Young to Fall in Love"

    q       Kelly Clarkson – "The Trouble with Love Is" (Kelly and I have the same birthday - April 24!  And ironically, so does Barbara Streisand!)

    q       Dokken – "It's Not Love"

    q       Tonic – "The Way She Love Me"

    q       W.A.S.P. – "Love Machine"

    q       FireHouse – "Love of A Lifetime"

    q       Queensryche – "I Don't Believe in Love"

     

    What I need is your help…feel free to add your own songs…there are undoubtedly many I missed out on.  Have fun with this!

    Read more...

  • ASP.NET no-no: making changes to web.config live on the server (aka, "why I'm an idiot")

    I had what was thankfully a temporary moment of total hysteria this afternoon.  I was working on some configuration changes to a blogging app I wrote and added to my site to support my TV station's coverage of this year's local elections.  And in so doing, I opened a copy of the root directory web.config file in FrontPage, made a couple of changes and then saved the file back to the server.

    Catastrophic mistake.

    Well, the site crashed.  I was getting all sorts of non-descript errors, so I called ORCSWeb and had Pam (who I finally got to talk to after nearly 2 years of correspondence), and we couldn't get the site restored.  After about 30 minutes of trying different things, I took an old copy of web.config and re-uploaded it to the server, which gracefully held.  Long story short, I should know better than this.  You would think that ASP.NET and/or IIS and/or the .NET Framework and/or FrontPage would be a bit more fault-tolerant than this, but that's assumption for you.

    Bottom line: once it's deployed on a production server, stay the hell out of config files.

    Read more...

  • Of hyperparanoia and being a good developer

    Sometimes, ignorance is bliss. 

    I've honestly lost count of the number of times I've stressed out while writing code since 2001, afraid to try something in a production programming atmosphere because of all that I know about the ASP.NET environment and what could either conflict with an existing service, slow down an application in the aggregate or otherwise ruin a good design.  I remember the good old days of ASP 3.0 when I would just code blindly, with total disregard for running services or resource consumption.  Hell, back then, if something worked, it worked. 

    Nowadays, I'm way too critical of my own designs and of every nuance of performance.  And this is arguably just what Microsoft had intended...my near pulling-out-my-hair state every time I work on a big project, with the result being great code and great product.

    I will openly admit that this heigtened state of fear has made me a better developer - I program aggresively, but defensively, if that makes any sense.  Chalk it up as maturity, but in so doing, I've also shown another growth side effect - premature grey hair.  :)

    Read more...

  • URL rewriting and passing variables, sans the visible query string

    In a blog post I did last December, I mentioned how the new trend for advanced web development seems to be migrating away from visible query string name/value pairs, towards IDs and keys included within the URL itself.  This got a lot of great exposure, and correlated with the thoughts and code of ASP.NET community heavy-hitters like Steve Smith, Scott Mitchell and Rob Chartier, whose respective takes on performing progressive URL surgery can really make a site work better, as far as user psychographics are concerned.

    My basic premise was from a usability standpoint, its ugly as sin to have so many variables and appended values, ampersands and question marks.  Others have since chimed in with the security benefits/risks of embedding values within the URL directly.  Granted, no self-respecting ASP.NET dev would hard-code in username/password combinations directly into the URL, but it's certainly possible.

    For example, here's the canonical example of how employing the URL rewriting features baked right into the .NET Framework can help:

    User-Visible URL
    ------------------------
    http://bogusphonedirectory.com/8675309


    Actual URL loaded by browser
    -------------------------------------
    http://bogusphonedirectory.com/get_resident_phone_number?id=8675309

    This really caught on like wildfire throughout the ASP.NET community once articles and evangelism started about the topic.  I'd like to add a corollary now, in that one of the benefits of investing in the time and developmental practice to do URL rewriting properly through Context.RewritePath()/Context.RewriteUrl() is that so many more variables can now be passed to the calling page via the query string, being free (and arguably safe) from snooping eyes:

    Actual URL loaded by browser w/additional variables
    ----------------------------------------------------
    http://bogusphonedirectory.com/get_resident_phone_number?id=8675309&monthFilter=4&city=losangeles&attendant=tommytutone

    This may be a “like, D-UH!“ factor to experienced developers, but is something I've seen many people neglect in their application design.  This really opens up a new galley of possibilities for developers.

    Read more...

  • JasBlog, v.1.7: conditional string manipulation for dynamically-rewritten URLs

    I'm adding what will be (I hope!) the last of the features for what's now become v.1.7 of my first blogging app.  Strange, as the product to date has had no name.  This last cog in the machine does what .TEXT does, in dynamically rewriting the URLs provided for each blog entry so that each author has a URL that's a bit friendlier than their query string counterpart.  And I previously mentioned about how I loathe the latter

    I've been considering Steve Smith's article on using Regular Expressions to handle dynamic URL rewriting, and this seems to be the general direction in which I'll be heading.  I was initially trying to per-page URL rewriting, but I'm finding that such an approach makes no sense.  So, it's back into Global.asax that I dive.  However, a new problem has arisen, namely in the way I should handle the various URLs generated by the program's basic design.  It suppoers multiple authors, so I've got to account for scalability, yet at the same time, the types of URLs generate are somewhar finite and under my control.

    I have the following structure that I need to take certain behavior on:

    (these values need to be ignored completely)
    /blog
    /blog/
    /blog/index.aspx

    (these values need to redirect to AUTHOR_POSTS.ASPX)
    /blog/jsalas
    /blog/jsalas/
    /blog/jsalas/index.aspx


    (these values need to redirect to READ_BLOG.ASPX)
    /blog/jsalas/11.aspx
    /blog/jsalas/11.aspx#comment457
    /blog/jsalas/11.aspx?page=2#comment457


    What would be the best way to handle the manipulation of strings?  I’m unsure at this point if it would be better to do a massive if...then statement, or use a RegEx, or do an Array.Split thingy.

    This is becoming more obsession than work....  :)

    Read more...

  • The art of shredding

    After completing work on v.1.5 of my first blogging application, I decided to start some work on my other side project, compiling/covering/recording the Greatest 80's Monster Ballads.  Thus, after playing for 4 hours straight and soloing like a madman on everything from Randy Rhoads to Iron Maiden to Steelheart, the tips of my fingers look more like fruit salad than appendages.  Yikes.

     

    At least the cool thing now is that I can lay my fingers on a hot skillet and not feel anything for the first 3 seconds.  So I guess you can say I had a “callous” evening.  Sorry...that really sucked.  :(

    Read more...

  • 80's guitar tablature request: Winger's "Miles Away"

    One of the side projects I'm working on is getting together a really kick-ass list of 80's monster ballads.  Part of this is because I'm personally covering all the tunes for my own amusement.  However, one song that's eluded me for years is Winger's “Miles Away” (the acoustic version by Kip Winger is awesome).  I've always been terrible at transcribing music, so if anyone has the chord progression or a link to it, I'd be most appreciative.

    Read more...

  • Good artists copy, great artists steal

    A couple of days ago I was mentally patting myself on the back after completing Version 1.0 of my first blogging app.  After a good night's sleep (my first in about a week) I took a second look, found a couple of inequities, and went back in and added a few more features, and did some light code cleaning.  So I guess what may be considered v.1.5 is ready to go, having been written solely in ASP.NET Web Matrix in C# for SQL Server 2000 for ASP.NET v.1.1.

    I basically played with the .TEXT blog app a little and emulated most of the features available, such as author editorial control and account signup.  So while none of the ideas and enhancements in the feature set are overly original designs of my own, they're low-budget variations on an existing theme that work rather nicely for their current purpose.  Pretty interesting stuff, and a nice way to spend and otherwise boring 4th of July weekend.  Needless to say, I got a lot done and we're waaaay ahead of our release date, which is supposed to be this coming Friday.

    Gosh, I need a life.  :)

    Read more...

  • I just wrapped production on my first blogging app

    I've been wrestling with a problem for a couple months - how to incorporate weblog functionality on my site's coverage of this year's local elections.  Essentially, we're going to integrate blogging a la VH1 with that network's “Best Week Ever“ blog, incorporating our producers and giving you a sneak peek at what's coming up with our TV shows, plus give you some behind the scenes stuff that either didn't make it to air or that we couldn't show on TV.

    I was initially going to rent out space with TypePad, but then a couple of days ago after reading an article on creating your own blog on MSDN Magazine by my friend Marco Bellinaso I just fired up Word and started spec'ing out what I wanted to do. 

    So, the build-in-your-damn-self concept came into play.  Which worked beautifully, because when I thought about it, we're not after high-volume, and some of the more advanced features (i.e., stats, trackback links, publising pictures via MMS on camera phones, et al.) are a tad outside of what we're going after.  So rather than pay out, I took 18 hours and built it myself.

    Long story short, I'm proud to say I wrote my first, low-budget, low-volume blogging app, which I'll totally give you the code and SPROCs for, if you like.  It's by no means .TEXT, FlexWiki or something of that caliber, but it does the trick for us.  The blog itself allows for multiple authors and there are no compiled assemblies to play around with, so it's pretty flexible.  Rip it apart, put it back together, and send me your enhancements.  v.1.0. is written for ASP.NET v.1.1 in C#, and uses SQL Server 2000 at the back-end (sorry...I'm lazy and won't do the conversions to either  VB.NET or OLEDB). 

    Just send me a note at jason@kuam.com if you'd like the code and it's yours!  :)

    Read more...

  • I'm smart enough to know that I know I'm not smart enough

    Welcome to the summer of my discontent.

     

    One thing that constantly irks me is when management constantly throws diverse, multiple, disparate projects at a person because it's "within their scope of work".  According to whom?  Please don't challenge me with working on something for which I'm neither prepared nor trained, much less interested in.  Throughout history, catastrophes have begun that way.

     

    Because I'm a web software developer, does that mean I can configure and fix a network or create and manage e-mail accounts?  Or write a desktop app?  Or do graphic design?  Or pre-program everyone's cell phones?  Because I have a marketing degree, does that necessarily mean I'm good at marketing?  Or even know how to do it?  And why all of a sudden am I responsible for keeping the books, drafting contracts and maintaining client relations?  That's a rather bold and naive assumption.

     

    Oh, silly me…I forgot.  According to you, a computer is a computer is a computer.  And because I know a little about how to use one it makes me good at everything under the sun having to do with the machines.  My bad.  Don't get me wrong…I'm flattered by people thinking so highly of my skills, but show a little initiative, people.  Damn.

     

    One thing that I pride myself on is maintaining an inane sense of pessimistic pragmatism.  And this helps, because rather than openly flaunt my talents, I outwardly promote my limitations.  People often ask me completely random questions, like, "What's the best web site to find movie listings on?" or "Where on the Web can I find information about zoos?", or even, "Hey, where can I find good tourism information on Guam?"  I'll look them straight in the face and say, "I honestly don't know…why don't you look it up?" 

     

    Oops, silly me again…it must have slipped my mind.  Apparently, you're under some delusion that I've got the whole of Google's search index stored mentally.  Because I'm "a computer guy".  And evidently, it's beyond your capacity to search for it yourself.  

     

    I guess my disdain for sloth-like intellectualism stems in the fact that I'm completely self-taught (a blessing and a curse), and that I got better at doing whatever it was I did by taking it upon myself to try.  And fail.  And then get back up and try again.  And eventually, figure out what works and how to get something done.  And most importantly, remember how I got there and hopefully avoid the pitfalls and mistakes I experienced along the way. 

     

    I'm by no means bragging, just trying to reintroduce the concept to society that human beings are capable of great things if they really apply themselves.  And I'm constantly trying to expand and extend my own skill set, and while I do enjoy working with and helping folks, it's rather disheartening to have to regress and do stuff that they could very easily do for themselves.  Break the mold & challenge the status quo!  Apathy, conformity, and open embrace of mediocrity aren't very becoming traits.

     

    Carpe freakin' diem!

    Read more...

  • My lil' side project: compiling the greatest 80's monster ballads

    To keep my waning sanity from completely leaving me, I'm doing something I haven't done in years...made a mix CD (OK...way back when it was tapes, but I've since caught up with the times).  Actually, there's a dual meaning...I'm also gathering all this stuff so I can make a CD of me covering all them, with me playing all the musical parts.  So, I'm still compiling, but of a different nature.  Ha! 

    The theme is 80's monster/power/rock ballads, and I've got a decent collection going...I'd like your help on what else should be in this, the ultimate in cheese and emotion:

    • Steelheart - “She's Gone“
    • Winger - “Miles Away“
    • Europe - “Carrie“
    • Warrant - “I Saw Red (live)“
    • Stryper - “Honestly“
    • Scorpions - “Still Loving You“
    • Scorpions - “Send Me An Angel“
    • Scorpions - “Always Somewhere“ (what can you say?  These guys are the kings!)
    • Def Leppard - “Bringin' on the Heartbreak“
    • Def Leppard - “Love Bites“
    • Def Leppard - “When Love and Hate Collide“
    • Kix - “Don't Close Your Eyes“
    • Cinderella - “Nobody's Fool“
    • Great White - “Rock Me“
    • Kiss - “Beth“
    • Kiss - “I Still Love You“
    • Bon Jovi - “I'll Be There For You“
    • Dokken - “Alone Again” (live from One Live Night...the best track ever!)
    • Tesla - “Love Song“ (these guys started gigging on Guam in the 80's!  For realz!)
    • Saigon Kick - “Love is on the Way“
    • Giant - “I'll See You in My Dreams“
    • Krokus - “Screaming in the Night“
    • McCauley Schenker Group - “Anytime“
    • Vixen - “Cryin'“
    • Queensryche - “Silent Lucidity“
    • Simple Plan - “Perfect“ (I'm letting this one slide...it just came out this year (2004), but it's too good of a song)

    These also are excellent songs to write code to.  I've been using them as the impetus for a blogging app I'm doing and it's coming along nicely.  So tack on your favorite tracks...thrash, glam, etc....it's all welcome.

    Thanks for your input!

    Read more...