Saturday, March 15, 2008

Debugging Routes

Previously Scott Hanselman pointed out that in CodeCampServer we are using a tiny wrapper around MvcRouteHandler in order to catch all exceptions and provide the route information along with the error message.  I called this (for lack of a better name) BetterMvcRouteHandler.  That’s right, Better!

Scott took this a mile further and created a nice route debugging table that you can use while debugging.  You can download this route debugger on Phil’s blog (with source).

To enable the route table debugger, you have to add this line to your global.asax:

RouteDebug.RouteDebugger.DebugRoutes(RouteTable.Routes);

I think it would be better to be able to add ?routedebug to the end of ANY url and have this happen automatically.  To accomplish this I created an HttpModule.  It looks at each request for the ?routedebug querystring key and, if found, calls the line above.  I ran into a hiccup, though… once you set the route handler to the debug one, all future requests use it as well (even without the url parameter). 

Good ‘ol Phil released the source for this route debugger, so I added a method to revert the routes back to their original values if the query parameter doesn’t exist.

Here is the RouteDebugModule:

Route_debug_module

(remember:  this code would NOT be appropriate for production use, both for the awkward setting of route handlers on every request and the fact that you don’t want your users to be able to see your route information.)

And the RevertRouteHandlers method (in Phil’s RouteDebugger.cs):

Revert_routes

The _oldRouteHandlers is just a static dictionary that hangs on to the route before swapping with the debug one.

I added the HttpModule to my web.config, and now I can do this:

Route-debug-in-action

…and also flip back to the regular request without recompiling.

I’m thinking they should call this BettererRouteHandler instead of RouteDebugHandler, who’s with me?

Monday, March 10, 2008

ASP.NET MVC - Preview 2 Thoughts

I said previously that I was excited for this release.  Ultimately I didn’t see much worth blogging about.  Some features are a step in the right direction, some (I think) were a step back.

I’m currently upgrade Code Camp Server to Preview 2 and hit about 80 errors which I had to go in and resolve.  My initial thoughts:

  • I think the HttpContextBase is a bad idea.  Yes I understand the desire to not introduce breaking changes.  But I think that the people that will be using ASP.NET MVC will be congnizant of this and code appropriately.  Interfaces are much easier to depend work with while testing, and I’d rather just use those.  Hey, couldn’t they give us both, and framework providers could choose?
  • what’s up with the OnActionExecuting, OnActionExecuted events?  These used to be OnPreAction, OnPostAction, which was much more readable (in my opinion) — seriously, put these back!  The new naming is not nearly as obvious to the glance.
  • Testing is still too cumbersome.  I think some good mocking-fu can mitigate this, but it’s a tough sell to people new to unit testing (and to mocking).  TempData should be implemented as an IDictionary on the controller, only to have a real TempData that depends on session state at runtime.  This would allow me to test that TempData works without having to mock session (which is not intuitive at all).
  • The Action filters are going to be where the goo lives.  This is how we will see some really productive & handy filters for performing actions such as requiring SSL, protecting an action from unauthenticated access, loading common data, etc.  Think of them as HttpModules for individual actions.

More to come, I’m sure…

 

 

Wednesday, March 05, 2008

ASP.NET MVC Preview 2 Now Available

I normally don't do this sort of announcement, but this one excites me.

Download the ASP.NET MVC Preview 2 here:
http://www.microsoft.com/downloads/details.aspx?familyid=38cc4cf1-773a-47e1-8125-ba3369bf54a3&displaylang=en&tm

Feedback to come...

Friday, February 29, 2008

Case Insensitive String Comparison is Teh Suck

Why is it so verbose to compare two strings in C# and see if they are equal, while ignoring case?

What I mean is this:  ("Apples" == "apples")  => false

Take the following examples, each of which does what I want it to, however there is so much noise code here that it really takes away from the readability of the code:

Assert.That(matches[0].Email.Equals(email, StringComparison.InvariantCultureIgnoreCase));

Assert.That(matches[0].Email.ToLower().Equals(email.ToLower()));
Assert.That(string.Compare(matches[0].Email, email) == 0);
Assert.That(Regex.Match(matches[0].Email, email, RegexOptions.IgnoreCase).Success);

Each one of these works, but I really wish this was a language feature.  Wouldn't it be nice to have a new operator syntax?
Assert.That(matches[0].Email ==? email);
//or
Assert.That(matches[0].Email ==~ email);
It turns out that we're not alone.  Ruby and Python have the same problem, however their regular expressions option is much more elegant looking (due to the languages having regex as a core feature).  This seems like such a common need that I'm surprised that this type of thing isn't built into the core of most languages.

Granted, there are concerns about how each one of these would behave, for example, how do you compare strings from two different cultures?  In my case I'm always dealing with English characters, but I fully understand the need to support internationalization.

What do you think?  Would you welcome a new operator to save your self some typing and improve readability?

The Culprit - System Restore Points

Thanks to Aaron Lerch and Scott Allen for nailing my problem exactly!  They suggested deleting system restore points and volume shadow copies.

Disk-cleanup

After doing this, I checked my free space via Explorer:

Explorer-drive-space2

42GB free now!  My santiy has returned.  Thanks guys!  My system will definitely stop thrashing with virtual memory now.

 

Thursday, February 28, 2008

Windows Not Recognizing Free Space

I’ve been having problems lately with my primary hard drive filling up.  Every once in a while Windows will tell me that I am running out of space on drive C: with only 500mb!  After I cough up my tongue I run CCleaner and do a quick WinDirStat report to see my big offenders.  Nothing glaring ever shows up in the report and I end up just deleting a bunch of old programs and other piddly files that probably only total to 1gb.  But Windows shuts up and I move on.

The last time this happened I took my World of Warcraft directory and manually (and painfully) moved it over to another drive.  This should have freed up 8gb.  It didn’t.

Today I started digging.  Windows correctly sees my drive size as 69.2GB, and reports that I only have 3.15GB free.  That must mean that ~65GB are in use.  However, JDiskReport (and WinDirStat) is showing that only 24gb are in use.

Explorer-drive-space

Jdisk-report

I ran chkdsk to get a raw view of the drive (and to see if there are any errors) and everything came out clean.  It reports that I have 15gb free!

Chkdsk-drive-space

Defrag is scheduled to run weekly and windows tells me that it doesn’t need a defrag.  At this point I’m wondering whether the drive is faulty or do I just need to reformat this drive… (I’d rather not do this, of course)

Any ideas?  I’m out of rope at this point.

 

Wednesday, February 27, 2008

Shame On Me

Someone decided to publicly criticize my example code in my previous post by saying that it was “bad.”  While I don’t agree with the nature of the criticism (my blog *does* have comments, you know) I totally agree with the message.  It was bad code.  I would never place that in a production application.

The intent of the post was to demonstrate some ajax techniques, not to talk about how to write testable, decoupled controllers.  I suppose that example code should come with a bit of a disclaimer that says “hey, we are doing this here for simplicity’s sake, but obviously you’d abstract this out.”  Ideally I would have commented out the entire flickr section, because it’s totally not important in the context of the example.

In light of this topic, here is how a perfectly testable PhotosController might be written:

public class PhotosController : Controller
{        
    private readonly IPhotoRepository _photoRepository;

    public PhotosController(IPhotoRepository photoRepository)
    {
        _photoRepository = photoRepository;
    }

    [ControllerAction]
    public void Search()
    {            
        RenderView("Search", new Photo[] { });
    }        

    [ControllerAction]
    public void Find(string query, bool? ajax)
    { 
        
        var photos = _photoRepository.SearchPhotos(query);
          
        ViewData["query"] = query;
        ViewData["photos"] = photos;
        
        if(ajax == true)
        {
            RenderView("_images", photos);
        }
        else
        {
            RenderView("results");    
        }            
    }
}

Here you can clearly see our dependency on IPhotoRepository.  This guy can be anything we want, from a Flickr implementation, google images implementation, a file system directory, or even (gasp) a TEST implementation for writing unit tests!

Here is the IPhotoRepository, that we are using in the example:

public interface IPhotoRepository
{
    Photo[] SearchPhotos(string query);

asdf

}

This returns a Photo object (that I defined), which means whatever implementation you choose, you need to map to this object. This is a good thing because it removed my dependency on "FlickrPhoto" in the view itself.

Our FlickrPhotoRepository now looks like this:

public class FlickrPhotoRepository : IPhotoRepository
{
    private readonly IConfigSource _ConfigSource;

    public FlickrPhotoRepository(IConfigSource configSource)
    {
        _ConfigSource = configSource;
    }

    public Photo[] SearchPhotos(string query)
    {
        var flickr = new Flickr(_ConfigSource.GetSetting("flickr.api.key"));
        var results = flickr.PhotosSearch(query, TagMode.AnyTag, query, 40, 1);

        var photos = new List<Photo>();
        foreach (var item in results.PhotoCollection)
        {
            photos.Add(new Photo(item.SquareThumbnailUrl, item.Title, item.PhotoId));
        }

        return photos.ToArray();
    }
}

Wait a minute! This class now has it's own dependency on IConfigSource? Craziness! In our example code from before, I had accessed the Configuration singleton directly, which is punishable by hand-removal in Albonia. Thank goodness I don't live there. Now this class is decoupled from the actual configuration implementation and it could really be coming from a text file or database (whatever you want).

Wiring all this up is easy.  You could do it via XML, but I chose to do it directly in code:

private void InitializeWindsor()
{
    _container = new WindsorContainer();
    _container.AddComponent("config-source", typeof(IConfigSource), typeof(AppDomainConfigSource));        
    foreach(Type type in Assembly.GetExecutingAssembly().GetTypes())
    {             
        if(type.IsSubclassOf(typeof(Controller)))
        {
            _container.AddComponent(type.Name, type);
        }
    }
}

Also note that I'm using WindsorControllerFactory from MVCContrib, so now my controller can be created (and each of it's dependencies ( and their dependencies (and their Dependencies)))... I think you get the idea.

And there you have it.  A perfectly decoupled and testable modification for my previous example code.  As you were….

Sunday, February 24, 2008

UpdatePanel, Who?

I don’t know why people are so enamoured with ASP.NET AJAX.  Sure it works and is developed by Microsoft, but what’s wrong with the dozen other alternatives out there?  Many developers I talk to will say “yeah I used Ajax on this” (with a capital A) and what they are referring to is ASP.NET AJAX.  While I don’t think it is a horrible framework (I use it on occasion), I think it is too complicated and requires too much to get a simple example started.  When people say they have ASP.NET AJAX experience, it means to me that they have experience with declarative controls and <ScriptManager> tags.  It doesn’t necessarily mean they know how ajax works and it definitely doesn’t mean they know anything about javascript.  This worries me.

I often talk about how awesome prototype is (and lately I’ve been digging jquery) and inevitably someone tells me it’s just eaiser to wrap your sections in an UpdatePanel and be done with it.  It is sometimes hard to argue with that, even though it is the most inefficient way of doing ajax.  In addition, this can cause side-effects in WebForms because the entire lifecycle is being executed, even though only part of the page is rendered.  This method is actually called “partial html replacement” or “partial page rendering” and can be achieved easily without needing ASP.NET AJAX.

Now that ASP.NET MVC is out, which doesn’t work with ASP.NET AJAX (not the full stack) people are foaming at the mouth for their UpdatePanel equivalent.  (I think we’ll see an update for this in the coming weeks that will show ASP.NET AJAX working specifically in the MVC environment, but this point still stands.  You don’t have to use it.)

I’m going to use jquery in my sample, but the technique will apply to prototype, mochikit, and others.  In this sample we will take a functioning page and turn it into an ajax enabled page, while preserving the non-ajax scenario (if javascript is disabled).

For our example, I will borrow from an impressive rails tutorial [Quicktime] and implement the same thing in ASP.NET MVC.  The basic concept is this:  Search for flickr photos and display them on the page using ajax. 

We have our page:

Photo-search-form

if you search for “flowers”, you are taken to another action (physically) that shows you the results:

Photo-search-results

Now let’s assume that you want this to happen with ajax.  We’d like the results to be displayed directly on the same page as the query.

Here’s the form from that first action:

<h1>Photo Search</h1>
    <div class="box">
        <form id="search-form" method="get" action="/photos/find">   
            <label for="query">Query:</label>
            <input type="text" id="query" name="query" />
            <input type="submit" id="search" value="search" />
            <img id="indicator" style="display:none" src="../../content/load.gif" alt="loading...." />
        </form>
    </div>

And the action that the form submits to:

[ControllerAction]
public void Find(string query, string format)
{ 
     var flickr = new Flickr(ConfigurationManager.AppSettings["flickr.api.key"]);
     var photos = flickr.PhotosSearch(query, TagMode.AnyTag, query, 40, 1);

     ViewData["query"] = query;
     ViewData["photos"] = photos;

     RenderView("results");
}

(This uses the FlickrNet library available on CodePlex)

In order to translate this into an ajax-enabled page (while preserving no-javascript behavior) we have to do 2 things. 

  • Prevent the form from posting, so that the browser doesn’t take us off the page
  • Make the Find() action render only the partial html for the images (in the case of an ajax call

Let’s solve the first problem first.  Using jquery, we can capture the form submit by doing this:

function init()
{        
    $('#search-form').submit(        
        function() {
            $('#photos').hide();
            $('#indicator').show();  
            hijack(this, loadPhotos, "html"), 
            return false;
        });
}

$(document).ready(init);

When the document has been loaded, init() is called.  This finds our form and adds an onsubmit handler to it.  Next, we hide the photos div (in case there were pictures there already) and then we start the ajax indicator.  For the love of all that is good and holy, let the user know that you’re doing something!  Ok next up is this strange hijack() function.  This guy takes the form and submits it via ajax instead.  It accepts the form, the method to call when the result comes back (callback), and the data type of the return value.  Finally, to cancel the browser from actually submitting the form, we return false.

Here is that “photos” div I mentioned a second ago:  (I put this directly under our form)

<div id="photos" class="box" style="display: none">
</div>

It’s initially hidden because it will be empty when the page physically loads.

hijack() is a generic javascript function, and is defined as:

function hijack(form, callback, params, format)
{   
    try {                                            
        $.ajax({
            url:        form.action,
            type:       form.method,
            data:       $(form).serialize() + "&ajax=true",
            dataType:   format,
            success:    callback,
            failure:    function(e) { alert("error! " + e); }
        });
    } catch(e) { 
        alert(e);
    }
}

This is pretty basic ajax stuff in jquery.  The only thing different that I am doing here is notifying the controller that this is an ajax call, so that we may make it behave a little differently.  After all, we don’t want it to return a full html document… we only want the images!

That’s the essense of issue #2.  If we revisit our controller action, we can make the following change:

[ControllerAction]
public void Find(string query, bool? ajax)
{ 
    var flickr = new Flickr(ConfigurationManager.AppSettings["flickr.api.key"]);
    var photos = flickr.PhotosSearch(query, TagMode.AnyTag, query, 40, 1);

    ViewData["query"] = query;
    ViewData["photos"] = photos;
    
    
    if(ajax.HasValue && ajax.Value)
    {
        RenderView("_images", photos);
    }
    else
    {
        RenderView("results");    
    }       
}

We’ve added an optional parameter for the action to check for.  There are a number of other ways you might accomplish the same thing by embedding this into the controller itself.  You could make a convention that allows a base Controller class set an IsAjax boolean property to true if it detects this variable in form variables or querystring.  Whatever you find the cleanest.

And, Here is our new form!

Photo-search-ajax

You couldn’t see it in that still image, but there was an animated ajax indicator, and a nice slide down effect on the photo div.  If you turn off javascript, the whole thing still works.

This entire process is basically what you get with UpdatePanel.  The same techniques are used to accomplish partial page rendering.  Granted, UpdatePanel works slightly different (it’s parts of the same page that get updated) but you could easily return a full html document from the action and snip out the html you want to update.  Or you might have a specific ViewFactory that knows to only serialize HTML starting with an element root.

With some conventions and a tiny bit of javascript, you could easily achieve partial page rendering with out any fuss.  Plus you get to work with jquery, which is much mor enjoyable than ASP.NET AJAX.

UPDATE:  Download the code below.  You’ll need your own flickr api key (you can get one instantly from flickr.com).  Place it in the web.config.

PhotoSearch.zip (124 KB)

Saturday, February 23, 2008

ASP.NET MVC in Action - Early Access PDFs

book coverThe cat is out of the bag now!  I’m writing a book on ASP.NET MVC for Manning Press entitled ASP.NET MVC in Action.  I really thrilled to be part of this along with my co-authors Jeffrey Palermo and Dave Verwer.

So far 3 chapters are available on Manning’s Early Access Program.  We’d love to hear your feedback on the book so far.

Writing a book is much harder than I originally thought, but I think that blogging for four years has definitely helped.  With a book, everything has to be much more “polished,” so finishing up chapters tends to take a while.  This might explain my drop in posting frequency, but I hope to add tidbits of information that I’m working on to give you guys a peek at what the book will be like.

Our target release date will be October 2008.

Thursday, February 21, 2008

More Downtime - Local Activation Permissions on DCOM

What luck.  My server went down last night and didn't come back up until this morning.  I eventually had to request a power cycle from my host and then remote desktop in to see what went wrong.

The root cause of the error was this:

The application-specific permission settings do not grant Local Activation permission for the COM Server application with CLSID ...... to the user NT AUTHORITY\NETWORK SERVICE.

This caused a few other errors to occur in rapid succession and Windows decided to shut down my application pool.  You can clearly see the issue here:




I read up on the error and found a solution.  Apparently after Server 2003 SP1 came out, this issue started appearing on servers with a specific Group Policy (I'm not sure what).  They suggested to add NETWORK SERVICE to the DCOM Users group.

So far it is working fine.  We'll see!

I wonder how much google juice I lost during the 12 hour outage.  :(
Personal Loan - Loans - Phoenix Landscaping - Credit Card Consolidation