CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Brendan Tompkins [MVP]

Blog First. Ask Questions Later.

July 2005 - Posts

  • WebHost4... about 24 more hours - We're moving.

    Well, it appears that CodeBetter.Com has outgrown our WebHost4Life account.  You know how I knew that?  Cause they shut us down!  That’s right, just turned off our server.  They did the same thing to our friend DonXml:

    The wonderful folks at WebHosting4Life shut down my site for a while today. Seems as though this site was eating 100% of the CPU (I’ve got multiple sites hosted on the same account, but this one was the one hogging resources). Instead of emailing me and letting me know that this site was too much of a strain on the old, small server it was hosted on, and scheduling something with me, they just shut down my site and then sent me an email letting me know that they did it, the site was using 100% of the resources and to contact them via their support site.

    Granted, we are growing pretty fast, and have a good amount of traffic, but I would have liked a bit more notice.  Anyhow, we’re moving to a better, faster server.  In the next couple of days, you may see some DNS weirdness, but hang in there, we’ll be back better than ever soon!

    -Brendan

     

  • An ASP.NET Custom Control for Dynamically Filtering Data - DataSetFilter

    A common need for web-based reporting is to create a UI to allow the user to apply filter criteria to a set of data.  Usually, this involves coding a fairly complicated UI, and associated code to apply the filtering logic to a DataView.  This UI usually is fairly static, possibly containing a drop down list to allow the user to choose which column to filter by, UI elements to allow them to select the filter criteria, and a mechanism to transform this data into a RowFilter to apply to a data view.  This can become tedious to code and maintain over time.  I’ve created a custom control that can do all this for you, which I’ve been able to use to allow numerous web-based reporting applications to be rapidly developed here at the port. 

    What is it?

    This WebControl, DataSetFilter, builds this complicated UI on the fly, given a particular DataSet and DataTable.  It does the following:

    • Grabs the DataTable’s columns and each column’s type, and generates a drop down list that the user can use to choose the column to filter.
    • Adds the appropriate operator for the column’s type.  For example LIKE is only appropriate for string types, greater than only for numeric and DateTime types.
    • Adds the appropriate value entering control.  For example, for DateTime types, it adds a calendar control, for other types it adds a textbox.
    • If multiple filters are added, it adds a boolean drop down list, to allow the next filter to be properly added.
    • Finally, it raises an event when the filter has changed, so that you can handle this event, normally applying it to your DataView, and re-binding your DataGrid.

    So, for example, here’s what it looks like when applied to Sahil’s Animal DataSet.

    And to see all animals that weight greater than 15 pounds and less than 5 pounds, we’d add two filters.  Notice the Boolean drop down list.

    For DateTime values, it presents a Calendar picker.

    Combine this with a standard ASP.NET DataGrid, and you’ve got a quick, but powerful reporting tool.

    What do you need to code to get it to work?

    There’s really not much that you need to do, just plop an instance of the DataSetFilter on to a form, DataBind it, and handle the FilterChanged event.  Here’s all the code that you need to bind the DataSetFilter.

        public override void DataBind()

        {

          DataSet ds = GetData();

          this.DataSetFilterControl1.DataSource = ds;

          this.DataSetFilterControl1.DataMember = ds.Tables[0].TableName;

     

          DataView dv = new DataView(ds.Tables[0]);

          dv.RowFilter = DataSetFilterControl1.RowFilter;

          lblFilter.Text = DataSetFilterControl1.RowFilter;

     

          this.DataGrid1.DataSource = dv;

          base.DataBind ();

        }

    And all that’s left to do is handle the FilterChanged event, and re-bind your DataGrid.  Easy!

        private void DataSetFilterControl1_FilterChanged(object sender, EventArgs e)

        {

          this.DataBind();

        }

    Okay. I want it!

    You can download the example web project here.

    The source code for the DataSetFilter control is here.

    There’s some other stuff in my Tompkins.Web namespace to enable this control, such as my CalendarPlus control, but everything you need is there.  There’s also support for adding parameters, which can prompt the end user for values to be entered, in the case of a stored filter.  I’ll try to blog about how all that works next time.

    -Brendan

  • CodeBetter.Com Google Adsense...

    Like Roy, we’ve decided to experiment with Google Adsense ads on our homepage.  There are a lot of things we could do around here with a little cash, such as upgrade our hosting account, so we thought, why not?

    Actually, we do everything around here by a voting process on our member forums.  It’s pretty cool - if we have a decision to make, we just put up a poll, and go with a 2/3 majority vote.  We put up the question “should we do a trial of adsense ads” and guess what?  86.7%  of us thought it would be a good idea.

    So we’ve got ads on our home page, and our aggregate blog page.  Any revenue from these ads will go into a fund to support improvements here at CodeBetter.Com.  We figure that most people view our syndicated RSS anyhow, with no ads, so this won’t even been seen by our loyal readers, right?  

    We’re not putting these ads on individual’s blogs, but you may see ads on our member’s blogs as well.  These ads you see on an individual’s blogs are not funding improvements at CodeBetter.Com – any revenue made from these ads belongs to the blogger.

    As always, let us know what you think, and how we’re doing in general around here! 

    -Brendan

  • Surf the web on your Vacation - Use your Sprint cellphone as a FAST USB modem

    I just had to post about this… It’s vacation time, and if you’re like me, every year you have the problem of how to connect from the beach, in the woods, on your road trip, or wherever your travel plans may take you.  Last year, I had to drive 50 miles to a library to do some emergency server work. This year, fingers crossed, I’ll be able to relax on the dock and connect to the web.  If you have a Sprint phone, here’s a great solution.

    BTW: I checked into the Wireless Broadband data cards, and Sprint’s current cost of $80/month +2 year contract for the service, it wasn’t really something I thought was worth the cost.

    Then I found this article from Engadget –

    HOW-TO: Use your CDMA cellphone as a USB modem - Engadget - www.engadget.com

    Travel plans about to take you beyond the land of broadband? Venturing far afield from the great kingdom of WiFi? You may have been born with 802.11b in your mouth, but you’re going to want to get prepared for that next trip to the sticks. This How-To will show you how to get a decent Internet connection for no cost other than the phone minutes you use while connected.

    I purchased my USB cable for $9.99 somewhere online, then somewhat skeptically followed the directions from the article.  It works like a charm! And it was fast, like the article says – speeds typically somewhere between a 56K modem and DSL/cable.  

    So for a total cost of $9.99, I actually got a 500 + K (will verify the actual speed later - but it's fast!) connection through my laptop!

    -Brendan

  • Debugging Tricky Issues with Red-Gate's ANTS Profiler

    I ran into a head-scratcher of a problem recently with WSMQ's new DbProvider, using the June Enterprise Library Data Access Application Block.

    I noticed that when running WSMQ under a low trust account, the application is initially very slow to respond.  Eventually, things seem to return to normal, but whenever the aspnet worker process is restarted, the application is again sluggish for a time period.  I couldn’t figure out what was causing this slowness.  It wasn’t my SQL server connection, it wasn’t simple assembly caching. Something was timing out, then getting cached, but what?

    Enter Red-Gate’s ANTS Profiler

    Like all their tools, I highly, highly recommend ANTS Profiler. Raymond has a great review of ANTS here.  Their SQL and ANTS tools  should be an essential component of any .NET developers suite of tools. Oh, and there’s a period at the end of that sentence.

    ANTS Profiler™ is the simple .NET profiler that pinpoints slow lines of code in .NET applications and helps you understand how your application is using memory.

    Anyhow, when I fired up ANTS, I  noticed that when I run WSMQ under a low-trust account, a call to the WMI’s IWebmLocator.ConnectServer is being made, and it's taking up 45 seconds during a simple profiling session!

    So, I started looking into code and found that even though I only had the Data Access Application Block configured, it was in fact, making WMI instrumentation calls.  This will require running under a high-trust account, something that I couldn’t require with an app that is designed to be deployed anywhere, even on a trusty WebHost4Life account.

    I found this post that showed me how to turn this stuff off, EntLib Required Post-Installation Step.

    I don't recommend it, but if you really want to you can also disable all of the WMI and performance counter instrumentation in Enterprise Library. This requires a recompile of Enterprise Library, and you will lose valuable performance monitoring data.

    Well, I do really want to do it, so here was my solution: Open the the EnterpriseLibrary.sln and modify the Configuration Properties\Build\Conditional Constants of the EnterpriseLibrary.Common project.  I had to remove the conditional build constants that were mentioned in @baz’ post.

    The point of this post?  I would have never even known where to look without ANTS!   This is really a great tool.  Thanks Red-Gate!

    -Brendan

  • "Developers Developers Developers" - what did Ballmer really mean?

    Jeff’s having a good discussion over at A BizTalk Enthusiast : Transition from MSDN Universal to Visual Studio Team Edition about the new Team System Pricing.

    I know, it’s a dead horse, along with DataSets versus BEs, VB.NET vs C#, and all the other *blog post topics that tend to crop up every month or two .  Remember, I’m an open source hippie, and pretty liberal to boot. I was raised that way, so it’s not really my fault, but it’s how I tend to think. So, here’s my take on MS charging lots and lots (enterprise prices) for Team System:

    Ballmer said "Developers, Developers, Developers" right? 

    Now,  if you’re like me, you heard this and thought of armies of developers, writing good code, saving the world – one unit test at a time.  Some of us  may have linked this sentiment to our own drive to create quality software systems that work, in some kind of “greater good” of software development way.  But we were really just kidding ourselves.  The real meaning of this statement was “… they’re they key to our success…” ie “…they’re the key to shareholder profit…”  We all really understood (even us hippies) that this statement really meant:

    “Developers, Developers, Developers : this is how Microsoft will stay uber-profitable and continue to crush our enemies.”

    Which is fine. No problem here with companies making money… Hey, even hippies have to retire and own boats.

    But here’s where I’m a little confused.

    If Ballmer really sees us developers as the key to MS making money,  why would they price Team System out of reach - and even un-license us MSDN subscribers from using parts of it?  Especially since we’re writing .NET code with the stuff.  It’s not like Java shops are going to be buying Team System and using it to manage the process of writing Linux code, are they?  Wasn’t he saying that MS needs to enable developers?  Isn’t this what you were saying Steve? 

    Perhaps what Ballmer really meant is “Developers, Developers, Developers – We're not charging you guys enough!" 

    Every day, I'm more and more interested in open source. 

    I often wonder if I could do what I need to do without any MS software installed on my home computers.  Don’t get me wrong – I love Microsoft. I’ve lost friendshps over my love for them.   I just don’t love giving them too much of my money.  Hey, I’m already devoting my career to their technology, what more do they need from me? Revenue from the four computers I have sitting in my house?

    Finally, a shameless self-serving announcement

    I really like Telligent's open source model.  Information Week has a cover story on Open Source this week.  They’ve called it a “Boomlet.” I think they’re right.  I’ve decided to release WSMQ as an open source application, with a licensing structure similar to Telligent’s.  I’ll be posting more about that in the next few weeks.

    -Brendan

    * This BTW could be the fatal flaw with blogs and is a topic for another post “Cyclic Redundancy Patterns in Blog Post Topics” (the other fatal flaw is that people like me can comment on issues like this, and get a Google ranking companies would kill for .. is this really a good thing?).

  • Refactoring WSMQ - Provider Patterns, DAAB and CodeSmith

    Now that CodeBetter.Com is humming along fairly nicely, I’ve been turning my extra time (much to my wife’s chagrin) to my pet project, WSMQ.

    If you’re not familiar with WSMQ, it’s a simple queueing application that supports multiple backend data storage mechanisms  (currently SQL Server, and file-based XML) that can be accessed over different endpoints.  The beta currently supports WSE 2.0 Web Services access over HTTP, but the next version will include support for REST, soap.tcp and direct dll project integration.

    I received some really good feedback after the first beta, specifically, around the back-end data storage scheme.  The original version was built to support XML, and the SQL Version was quickly put together knowing that refactoring would be the next step.

    The first beta version had the following drawbacks:

    • DataSets were used to shuttle data between the database and the business entities.  The extra overhead of datasets was un-necessary.  I’m with Scott Hanselman on this one.
    • The data layer was a concrete class, and there was dependent code in the Queue provider to this class.  This was a violation of the Dependency Inversion Principle, and resulted in a much too tightly coupled design.
    • The data model required deletes and inserts when messages were received. This was done since it most closely mirrored the way the XML version works, and could be put together quickly.  It was very slow.
    • The data layer used SqlTypes, which made switching data providers difficult.

    I started with a completely new database design, which is much much better and probably very close to the version that will ship when I actually release this thing.  I re factored the code and came up with, I feel, are good solutions to each of these issues:

    No more DataSets!  Whahoo!

    DataSets have their place, but not in an application designed for performance.  If performance is what you’re after, it’s DataReaders all the way. I was definitely mis-using them in my original design.  I was getting the data from SQL, filling datasets using a DataAdapter, and then moving the data into my business tier.  My new design uses the Data Access Application Block, returns DataReaders, and fills the business objects from the readers. This has resulted in an enormous perf increase.

    Added a Provider Pattern for the Data Layer

    The new version uses a provider model to access the Data Tier. 

    See this MSDN article here for more on the Provider Pattern from Rob Howard

    [The Provider Pattern is] a pattern that allows for a pluggable Business Logic Layer (BLL) and Data Access Layer (DAL) for published APIs. This pattern is being used throughout the new ASP.NET 2.0 infrastructure features; it allows you to unplug our default implementation of an API and plug-in your own—a very powerful capability.

    In fact, Rob created some CodeSmith templates, that will create your abstract and concrete Provider classes for you.

    Provider Model Templates (using MS DAAB) :: CodeSmith Peer Support Forum

    The attached template creates the Configuration, Abstract, and Concrete classes you will need to implement a SqlDataProvider for your projects. You can alter these templates to use any of the other DAABs out there (GotDotNet, etc) if you want to create an Oracle, Access, MySQL, etc provider.

    I’ve modified his templates to use the new DAAB from the June Enterprise Library, and to be database-agnostic using only the abstract db types.  You can download my templates from his thread on the CodeSmith support forum. The result is that the entire data layer can be swapped out, by simply implementing an interface, dropping a DLL and making a configuration change.  Can’t get much more pluggable than that.

    I’m also adding a Provider model for the queue provider itself, which will let you plug in a custom provider to handle the entire back-end queueing operation.  This will allow you to plug the WSMQ front-end service, web management tools, etc to any queueing application, such as MSMQ or WebSphere Queue.

    I’m very happy with the way this is all coming together.  I’m going to be releasing beta 2 in the next couple of weeks, and hopefully will be able to release version 1 around or just after PDC… Beta 2 will be an open beta (no registration) so look for that soon.

    -Brendan

  • PDC Countdown Image V2

    The other day, I created a PDC Countdown Image that you can add to your blog.

    It grabs the PDC logo from Microsoft, calculates the days until PDC, and renders a new image to the outgoing Response stream, as a JPEG image.

    I’ve put up another version, that looks a little nicer.  In fact it looks like this:

     CodeBetter.Com

    To add this one, here’s the HTML you’ll need:

    <a href="http://msdn.microsoft.com/events/pdc/"><img src="http://www.codebetter.com/pdccountdownimage2.ashx" border=”0”></a>

    If you haven’t entered the contest yet, you can use my handy dandy service to create your entry… Good luck!

    -Brendan

  • Refactoring My PDCEntry Service

    Earlier today I was inspired by Jeff Atwood’s blog post on Software Rot:

    Coding Horror: The Broken Window Theory

    Don't leave "broken windows" (bad designs, wrong decisions, or poor code) unrepaired. Fix each one as soon as it is discovered. If there is insufficient time to fix it properly, then board it up. Perhaps you can comment out the offending code, or display a "Not Implemented" message, or substitute dummy data instead. Take some action to prevent further damage and to show that you're on top of the situation.

    The article on “Urban Decay” he mentions is a must read, a fascinating topic, and very closely linked with something that should be called “Software Decay” but is also known as Software Rot.  I’m going to blog about something I’ve been thinking about “Root-Bound Software” and the associated process of “Software Weeding” soon, but Jeff’s post got me thinking about some potential broken windows in my my PDC Contest Entry Service.

    So as not to let this service (since I expect it to be wildly popular) rot, I’ve done a bit of refactoring. You can download the new version here. Here’s what I’ve done:

    • Refactored the code that does the work into a reusable service, now the service itself is very lean and mean.
    • Added a REST endpoint, via an ASHX handler. The service can now be access via GET parameters:

    http://www.wsmq.com/PDCService/PDCContestEntryRestEndpoint.ashx

    Parameters: firstName, lastName, interests, blogUrl

    • Fixed spelling errors, Fixed a queuing bug, and improved formatting.

    So, here’s my new entry.  BTW, two people managed to bang the service, before the REST interface was added.. Bil Simser and Leon Langleyben.. Way to go guys! 

    -Brendan

    I’m Blog’n my way to the PDC!

    If you haven’t heard, Channel9 has started a contest where you can win a ticket to the PDC, including an airline ticket and hotel!  This is one amazing contest, and all you have to do to enter is have a blog, and post why you should win the prize.  So here’s my official entry:

    blogging my way to pdc

    Here's some information to help you get to know me better:

    Why me?

    Why do I want to go to the PDC? Because I love to blog! And I'm prolific! Here's some of my more popular blog posts links according to Google :

  • Brendan Tompkins
  • Brendan Tompkins
  • Brendan Tompkins : Dreading writing your "Blog'n to PDC" entry ...
  • Brendan Tompkins : A Simple InfoPath Web Viewer Control
  • Brendan Tompkins
  • What are my interests?

     Well, here’s a list of books that I'll probably be reading on the plane to LAX :

    Map of Bones Financial Management : Theory and Practice with Thomson ONE (Harcourt College Publishers Series in Finance) Good to Great: Why Some Companies Make the Leap... and Others Don't

    Did I type up all this ugly HTML for this Blog post myself?

    Heck no!  I’m lazy!  But that’s exactly why I need to go to PDC!  The PDC is all about the future, and in the future, we’ll all be using cool technology to do things like typing tedious, boring contest entries.  I’m getting a head start on the salad days, so I figured out how to use ASMX web service that Brendan wrote! To prove it, you can see that I'm on this list of other, lazy coders who would rather sit back and use a distributed Web Service to do their work!  

  • Add my PDC Countdown Image to your Blog

    Thinking more about this PDC contest thing, I realized that it be cool to have an image on my blog that would countdown the days till the PDC.  This way, if I win, I’ll know when to start really getting juiced!  And, I’ve got some extra time lately, since the CS 1.1 roll out here at CodeBetter is pretty much done. So, I threw together an ASHX http handler which can add this image to your blog:

    It grabs the PDC logo from Microsoft, calculates the days until PDC, and renders a new image to the outgoing Response stream, as a JPEG image.  I've tossed this code up on CodeBetter, so if you want to add this image to your blog, you just need to add this HTML:

    <a href="http://msdn.microsoft.com/events/pdc/"><img src="/pdccountdownimage.ashx"></a>

    I also thought it was a neat way to demonstrate some cool things, like

    using System;

    using System.Drawing;

    using System.Drawing.Imaging;

    using System.Globalization;

    using System.IO;

    using System.Net;

    using System.Web;

    using System.Web.Caching;

     

    public class PdcCountdownImage : IHttpHandler

    {

      public bool IsReusable

      {

        get { return true; }

      }

     

      /// <summary>

      /// Processes the request.

      /// </summary>

      /// <param name="ctx">CTX.</param>

      public void ProcessRequest(HttpContext ctx)

      { 

     

        Byte[] imageBytes = null;

     

        // Check if the cache contains the image.

        Object cachedImageBytes = HttpRuntime.Cache.Get("PDCBYTES");

     

        // We have some cached bytes, use em!

        if (cachedImageBytes != null)

        {

          imageBytes = cachedImageBytes as byte [];

        }

        else

        {   

          // Gotta go get the PDC image, hope they don't change the location

          System.Net.WebClient webClient = new WebClient();

          byte [] pdcImageBytes = webClient.DownloadData("http://msdn.microsoft.com/events/pdc/images/home_pdc_masthead.gif");

          using(Image inputImage = Image.FromStream(new MemoryStream(pdcImageBytes)))

          using(Image outputImage = new Bitmap(inputImage))

          { 

            using(Graphics g = Graphics.FromImage(outputImage))

            {

     

              IFormatProvider culture = new CultureInfo("en-US", true);

              DateTime pdcStartDate =

                DateTime.Parse("9/13/2005",

                culture,

                DateTimeStyles.NoCurrentDateDefault);

     

              DateTime pdcEndDate =

                DateTime.Parse("9/16/2005",

                culture,

                DateTimeStyles.NoCurrentDateDefault);

     

     

              DateTime today = DateTime.Today;

     

              string message = String.Empty;

     

              if(today < pdcStartDate)

              {

                message = String.Format("It's in {0} days!", (pdcStartDate - today).Days);

              }

              else if(today >= pdcStartDate && today <= pdcEndDate)

              {

                message = " It's on baby!";         

              }

              else

              {

                message = "  It's over baby!";

              }

     

              using(Font font = new Font("Arial", 16))

              {

                g.DrawString(message, font, Brushes.Gray,1,1);

              }       

     

              using(MemoryStream stream = new MemoryStream())

              {

                outputImage.Save(stream, ImageFormat.Jpeg);

                imageBytes = stream.GetBuffer();

              }

     

              HttpRuntime.Cache.Add("PDCBYTES", imageBytes, null,

                today.AddDays(1), new TimeSpan(0, 0, 0),

                CacheItemPriority.Normal, null);

            }       

     

          }   

        }

     

        ctx.Response.Cache.SetExpires(DateTime.Today.AddDays(1));

        ctx.Response.Cache.SetCacheability(HttpCacheability.Public);

        ctx.Response.Cache.SetValidUntilExpires(true); 

        ctx.Response.ContentType = "image/jpg";

        ctx.Response.BufferOutput = false;

        ctx.Response.OutputStream.Write(imageBytes, 0, imageBytes.Length);

        ctx.Response.End(); 

      }

    }

    You can download the ASHX file here, if you want to tweak it, and host it yourself. 

    Have fun!  Hope to see you at the PDC!

    -Brendan 

More Posts

Our Sponsors