Monday, April 21, 2008

I've been horrible with blogging lately.  But, I would be remiss if I  neglected to mention Peter's birthday today.  Happy Birthday, Peter.

Hopefully the thing that's been clogging my blogging pipes will be gone soon.

posted on Monday, April 21, 2008 3:28:22 PM (Pacific Standard Time, UTC-08:00)  #    Comments [1]
 Monday, February 25, 2008

Some of my posts are really reactions to search queries that have previously landed on my blog.  If they did a search that got to my blog, but I know they didn't find what they were looking for, chances are they (or someone else) will do the same again.  And, if I HAVE the information they are looking for, it makes sense to just add the information, even if it's what I would consider well-known or common sense information. (common sense for software developers, that is)

One general search query I see again and again is something like "What is Action<T> for?" or "What is Func<T>?"

These are framework-provided, generic delegate types.  If you'll recall, delegates can be thought of as type-safe function pointers.  A delegate type really just captures a signature as "callable" object.  Leveraging generics to define delegate types that can capture common signatures is goodness, since they are very flexible and can be used by anyone.  This also aids in interop between different components, since a general signature is far more interopable than custom delegate types.

In v2.0, several functional-looking APIs were added that took delegates as arguments (think List<T>), so instead of adding a special delegate type for each API, several "generic" delegates were added to capture the "essence" of a signature such as Action<T> which takes T and does some action (returning void), Predicate<T> which takes T and returns bool (presumably doing some test against T), Comparer<T> which compares 2 T's, etc.

In v3.5, even more generalized functional patterns were introduced (used heavily in Linq).  And we added a bunch more Action<> "overloads" for functions returning void, and added Func<> "overloads" for functions with a return value.  (I use overload loosely since these are classes and not methods) These patterns dropped the semantic "meaning" of the delegate, and just went straight to the idea of capturing a signature.

These framework-provided delegates are useful for using in your own code rather than creating your own.  Whether you leverage the Linq-centric, super-generic Action/Func pattern, or opt to consume the more meaningful v2.0 Predicate, Comparer, etc. is up to you.

posted on Monday, February 25, 2008 11:12:15 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Sunday, February 24, 2008

We were hanging out after church today, and I saw a large flash of black and white zoom by the sliding glass door that looks out over the deck into the backyard.  I immediately jumped up and grabbed for the camera and in my panicked state, took several of the worst pictures ever of a majestic bald eagle as it sat in a tree less than 20 feet away from the house.

It was obscured by several other trees, so the focus isn't great.  And my shutter speed was too slow to eliminate the excited shake in my hands.  I tried to step out onto the deck to get a better shot, but it flew away.  It was enormous.

posted on Sunday, February 24, 2008 2:01:53 PM (Pacific Standard Time, UTC-08:00)  #    Comments [2]
 Tuesday, February 12, 2008

This is one of those entries that attempts to fill a void in online search for a particular topic.  I ramble on for a while to give enough context so that a search engine can match it up in a relevant manner.

I was debugging something the other day, and thought I had come across a heinous bug in the CLR.  Turns out, everything was working fine and the bug was in the app.

A program was crashing and it was a managed exception, so I attached to it with VS2008 and dug in.  The first thing I noted was that this was a retail build, so my stack was collapsed in a number of places... expected, keep moving.  Then, I noted an interesting frame on my stack (this is a contrived example, not the actual thing I saw):

>    CanonTest.exe!CanonTest.GenericType<System.__Canon,int>.SomeOperation() + 0x55 bytes   

That's weird, what is System.__Canon and what's it doing here? Surely this must be a horrible CLR bug where my method tables are being corrupted!  Internet searches seem to be confirming my thoughts.  A few others with random __Canon's showing up on the stack do look like bugs.  After a bit more reasoning, I come to the conclusion that System.__Canon must be special in some way since it follows the pattern for such things...  marked internal, pre-pended with double-underscore.

A few emails later, I had my answer.  System.__Canon is the special type that is used to identify "canonical" generic type instantiations. It typically only shows up in release builds, so you don't normally see it on the stack while debugging.  So, it's easy to assume something's wrong when you do see it.

If you'll recall, one of the really cool things about the Generics implementation is that it allows for code sharing.  Jitted methods can be shared between compatible type instantiations.  For instance, the code for SomeGenericType<string> can likely be shared with SomeGenericType<Foo> (where Foo is another reference type. We don't currently share code between value types, so you'll continue to see those on the stack such as in the example).  That shared code needs to live somewhere, so we have the concept of a "canonical" generic type instantiation that is identified by __Canon as the type parameter.

Also, in alot of debugger stack representations you'll get the GenericType`2 form rather than expanded form.  In that case, you never see __Canon.

For some more info on Generics and code sharing, see Joel Pobar's excellent blog entry on the subject.

posted on Tuesday, February 12, 2008 11:56:35 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]
 Wednesday, January 09, 2008

A twist on Bill Cosby's humerous show,  the other day I said the following to my daughter:

I'm sorry, donkeys don't stick to the refrigerator.

Taken out of context, Becky thought it was pretty funny. Here's the context: I was playing with Jenna in the kitchen the other day, and she was playing with 2 plastic donkeys as well as some refrigerator magnets.  After seeing how the magnets stuck to the refrigerator, she tried to do the same with the plastic donkeys, which didn't work of course.

posted on Wednesday, January 09, 2008 10:40:08 AM (Pacific Standard Time, UTC-08:00)  #    Comments [2]
 Thursday, January 03, 2008

The CTP for the MVC framework includes support for master-page, page, and user-control based views.  I thought it might be interesting to enable .ashx-based views for things like RSS generation via System.Xml.Linq, or other more "raw" view output.

As it turns out, this is fairly trivial.  The place we need to extend is the IViewFactory returned by Controller.ViewFactory.  This is the component that is responsible for creating the view when a call to RenderView is made.

The default view factory is the WebFormViewFactory, which knows how to generate views based on .master, .aspx, and .ascx views.  Since we want to add support for .ashx, we'll use WebFormViewFactory as a starting place.  We'll inherit from WebFormViewFactory and override CreateView to supply our extra .ashx lookup.

using System;
using System.Globalization;
using System.IO;
using System.Web;
using System.Web.Compilation;
using System.Web.Mvc;

public class SpecialViewFactory : WebFormViewFactory {

    static readonly string[] ViewLocationFormats = new string[] { "~/Views/{1}/{0}.ashx", "~/Views/Shared/{0}.ashx" };

    ControllerContext _ControllerContext;

    #region IViewFactory Members

    protected override IView CreateView(ControllerContext controllerContext, string viewName, string masterName, object viewData) {
        _ControllerContext = controllerContext;
        //check to see if there is an ashx that matches here.
        object value = null;
        controllerContext.RouteData.Values.TryGetValue("controller", out value);
        string controllerName = value as string;
        if (controllerName == null) {
            throw new InvalidOperationException("No route data value available for controller.");
        }

        Type viewType = null;
        foreach (var loc in ViewLocationFormats) {
            var path = string.Format(CultureInfo.InvariantCulture, loc, viewName, controllerName);
            viewType = GetCompiledType(path);
            if (viewType != null) break;
        }
        if (viewType == null) {
            return base.CreateView(controllerContext, viewName, masterName, viewData);
        }

        if (!typeof(IView).IsAssignableFrom(viewType)) {
            //TODO: better exception
            throw new InvalidOperationException("Type not a view");
        }
        var view = (IView)Activator.CreateInstance(viewType);
        var viewHandler = view as ViewHandler;
        if (viewHandler != null) viewHandler.ViewData = viewData;

        _ControllerContext = null;
        return view;
    }

    private Type GetCompiledType(string path) {
        Type compiledType = null;
        try {
            if (File.Exists(_ControllerContext.HttpContext.Request.MapPath(path))) {
                compiledType = BuildManager.GetCompiledType(path);
            }
        }
        catch (HttpCompileException) {
            throw;
        }
        catch (HttpParseException) {
            throw;
        }
        catch (HttpException) {
        }
        return compiledType;
    }

    #endregion
}

GetCompiledType had to be replicated as it isn't exposed in the base class.  Note, I added a File.Exists check before I attempt to get the compiled type from the BuildManager. This was really to avoid having to deal with a bunch of first chance exceptions in the debug, although it seems likely that avoiding the exception is a good thing.  It wouldn't catch handlers that are mapped in the app dynamically or via web.config.

As you can see, I also added a ViewHandler class that my handlers can inherit from that gives them the same goodies that the other views get, but I'll leave that as an exercise for the reader to implement.

So, now the only thing remaining is to inject our special view factory into the pipeline instead of the default.  A simple way to do this is to set the ViewFactory property in the constructor of any controller that needs .ashx support. Now, you can create .ashx files and use them as views!

Next time, I'll show you how to add support for routing controller actions based on data not in the URL.

posted on Thursday, January 03, 2008 3:46:58 PM (Pacific Standard Time, UTC-08:00)  #    Comments [1]
 Tuesday, December 11, 2007

markandjasonWell, my old-school buddy Jason turns 32 today.  Jason and I have been friends since pre-school.  We pretty much attended every year of school together, all the way through our undergraduate years.  Here's a picture of me and him (Jason on the left... I don't know what the heck I'm doing) at one of my brother's birthday parties.  He was the friend I got to invite.

Happy birthday, man.  Go play some slaughterball today for me.

posted on Tuesday, December 11, 2007 4:22:30 PM (Pacific Standard Time, UTC-08:00)  #    Comments [4]
 Monday, December 10, 2007

I've been loving playing around with the CTP of the MVC framework for ASP.net.  On several occasions in the past, I've rolled my own hybrid MVC implementations on top of ASP.net, so the prospect of a high-quality, "official" implementation is pretty exciting.

Note that I'm NOT on the ASP.net team.  I don't have any "inside" information about the framework, other than the privilege of getting to play with early bits.  But, since my previous jobs have involved alot of web development, I feel like I have some interesting insights.  I've been doing alot of app-building with the framework, and I found myself missing a few things that I'm sure are in the planning phases, but they are missing nonetheless.  Nikhil has some great AJAX support prototyped, so I was able to build on that, but I have some other samples I'll share that may be of some use.

First, users will no doubt be frustrated by trying to implement something simple like shared components.  Think of a blogroll, or list of categories on a blog.  These items don't really depend on input from the route (URL), they show the same data for every page.  Currently, each controller action has to put this data into the ViewData (which makes it more difficult to dynamically add shared components, especially if you're using strongly-typed ViewData).

You could solve this in your controllers by inheriting from a common controller type that prepared that data for you, but then you likely have a controller pulling data that is totally unrelated to it.

I think a better approach is to allow Views to render actions directly.  At first, this may seem like a violation of general MVC practices, but think of it this way...

  • A view can already generate a url to an action that would be rendered if the user clicked on it.
  • With proper AJAX support, you could make a callback and have the results of that action render into part of the page, either onclick or onload.
  • Allowing views to render actions using the same input that they would use to create a URL to that action simply eliminates the round-trip.

So, as Nikhil adds "RenderPartial" support to views, here's my RenderAction implementation:

First are some extension methods for the different view types.  These would go in an appropriate static class.

        /// <summary>

        /// Common logic for rendering actions as part of a view.

        /// </summary>

        static void RenderAction(string actionUrl, IHttpContext currentContext) {

            //create a fake IHttpContext that will fool the route collection

            //into creating RouteData for our action

            var fakeContext = new FakeContext(actionUrl, currentContext);

            var routeData = RouteTable.Routes.GetRouteData(fakeContext);

            //Make a new MvcHandler that will process our fake request

            var handler = new MvcHandler() {

                RequestContext = new RequestContext(fakeContext, routeData)

            };

            ((IHttpHandler)handler).ProcessRequest(HttpContext.Current);

        }

 

        /// <summary>

        /// Allows a page-based view to render actions

        /// </summary>

        public static void RenderAction(this ViewPage page, object values) {

            RenderAction(page.Url.Action(values), page.ViewContext.HttpContext);

        }

 

        /// <summary>

        /// Allows a master-based view to render actions

        /// </summary>

        public static void RenderAction(this ViewMasterPage page, object values) {

            RenderAction(page.Url.Action(values), page.ViewContext.HttpContext);

        }

 

        /// <summary>

        /// Allows a usercontrol-based view to render actions

        /// </summary>

        public static void RenderAction(this ViewUserControl control, object values) {

            RenderAction(control.Url.Action(values), control.ViewContext.HttpContext);

        }

You could imagine adding a similar extension to enable this for any kind of view.

Now, the "FakeContext" type is an implementation of IHttpContext that does the trickiness we need to get the routes to work, and the MvcHandler to execute the request.  Here's the relevant parts, the rest of the implementation just throws so that it is clear when something breaks that we haven't really thought through.

        class FakeContext : IHttpContext {

 

            //This is a similar fake object to help

            class FakeRequest : IHttpRequest {

                FakeContext _FakeContext;

 

                public FakeRequest(FakeContext context) {

                    _FakeContext = context;

                }

 

                public string AppRelativeCurrentExecutionFilePath {

                    get { return VirtualPathUtility.ToAppRelative(_FakeContext._ActionUrl); }

                }

 

                public string PathInfo {

                    get { return string.Empty; }

                }

 

                /// <summary>

                /// This is here to allow Nikhil's IsAjaxRequest method to continue to work

                /// </summary>

                public System.Collections.Specialized.NameValueCollection Headers {

                    get { return new System.Collections.Specialized.NameValueCollection(); }

                }

 

                //the rest of the implementation just throws.

                //that way, we know if something needs to be implemented later.

            }

 

            string _ActionUrl;

            IHttpContext _Context;

 

            public FakeContext(string actionUrl, IHttpContext context) {

                _ActionUrl = actionUrl;

                _Context = context;

            }

 

            public IHttpRequest Request {

                get { return new FakeRequest(this); }

            }

 

            public IHttpSessionState Session {

                get { return _Context.Session; }

            }

 

            //the rest of the implementation just throws.

            //that way, we know if something needs to be implemented later.

        }

This is a testament to the flexibility of the interface-based approach.  This would be MUCH more difficult if we had to deal with the concrete HttpContext type.

So, if we want to inject the results of an action in part of a view, you would just do something similar to the following in your view, and you can pass other data, just as if you were creating an Action.Link:

<% this.RenderAction(new { Controller = "Tags", Action = "Cloud" }); %>

Bingo, the system processes the request (almost) as if it were an isolated request.  There are obviously some limitations here, as well as some dependency on using Controller-based controllers and the MvcHandler, but that's certainly the common scenario.

Next time, I'll show you how to add support for ".ashx"-based views.

posted on Monday, December 10, 2007 12:44:29 PM (Pacific Standard Time, UTC-08:00)  #    Comments [3]