Saturday, March 27, 2010

Writing Your Own HttpHandler in F# - Starting the Solution

So my friend, Ryan Riley, was talking to me the other day about building an HttpHandler using F#, but he had come across a problem... how to debug the handler using Visual Studio. Knowing how much it would irritate me not to be able to debug my F# web-related work, I set out to figure out how to get this kind of project started. I'm going to make this whole thing as simple as humanly possible. And when I say simple... I mean absurdly simple...

1. Create a new MVC web application.
2. Delete everything out of the project other than the web.config.
3. Remove all the references (all of them... I told you this would be absurdly simple...)
4. Now, add an F# class library project to the solution. Call it "FunctionalWeb.Framework".
5. Delete the .fsx file. (or if you feel strongly about it, don't.)
6. Add a reference in the F# class library to System.Web.
7. Rename Module1.fs to HttpHandler.fs.
8. Paste the following code within HttpHandler.fs file, and replace anything that's already there:


namespace FunctionalWeb.Framework

open System.Web;

type HttpHandler() =
interface IHttpHandler with
member this.ProcessRequest(context:HttpContext) =
context.Response.Write("Hello from a simple F# Http Handler!")
context.Response.End()
member this.IsReusable with get() = true


9. Add a reference to FunctionalWeb.Framework in your web project.
10. Replace the content of the web.config file with the following:


<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0">
</compilation>
<httpHandlers>
<add verb="*" path="*" validate="false" type="FunctionalWeb.Framework.HttpHandler, FunctionalWeb.Framework"/>
</httpHandlers>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true"/>
<handlers>
<remove name="FunctionalHandler"/>
<add name="FunctionalHandler" preCondition="integratedMode" verb="*" path="*" type="FunctionalWeb.Framework.HttpHandler, FunctionalWeb.Framework"/>
</handlers>
</system.webServer>
</configuration>


Your solution should look something like this (You may or may not have the nested files below the web.config):



11. Press F5. If all goes well, you should see something like this:



As long as you allowed Visual Studio to modify the web.config in order to allow debugging, you should be able to put a breakpoint in your F# HttpHandler file, and have Visual Studio hit the breakpoint.

Congrats! You've just gotten started building your own HttpHandler with F#.

Thursday, March 18, 2010

ASP.NET MVC isn't SOLID (or How to Rely on Abstractions in Views and Controllers)

MVC is a great framework for building web applications, however, there's at least one SOLID principle I feel could be implemented more thoroughly: Dependency Inversion Principle. Dependency Inversion Principle states that "code should depend on abstractions, not concretions." This can be seen in the views, where the generic type parameter of strongly-typed views is typically based on a concrete model:

<%@ Page Title="" Language="C#" MasterPageFile="../Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MyNamespace.Widget>" %>

It can also be seen in the controller, where POST actions may have parameters that are concrete:

[HttpPost]
public void Details([Bind] Widget widget)
{
// do something with the widget.
}

Ideally, it'd be nice to rely on an interface for both of these situations, however, it's a little harder than simply replacing Widget with IWidget in the controller and the view. Somehow MVC has to figure out which implementation to use with IWidget. This is where a little creativity and dependency injection can come in handy.

Internally, MVC uses a class called the DefaultModelBinder to reconstitute the strongly-typed view model from the posted form data sent via the POST. This class's "BindModel" method is called from the controller, and the type expected by the controller's action is passed as a property of the ModelBindingContext parameter expected by BindModel. There's a whole slew of things BindModel goes through to bind the form data onto the model, but the only thing we're interested in at the moment is how it creates an instance of an object based on a specific type. Turns out this is accomplished via the "CreateModel" method.

Now, the CreateModel method is very simple. Ultimately, unless the type expected is an IDictionary<T> or an IEnumerable<T>, it's going to simply make a call to Activator.CreateInstance, pass in the type requested, and return the result. Luckily for us, CreateModel is virtual, so we can override it with something like this:

public class DependencyInjectionModelBinder: DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
object result;

// Attempt to get the value from ObjectFactory. If this fails
// use the default method of constructing the model.
if ((result = ObjectFactory.TryGetInstance(modelType)) == null)
result = base.CreateModel(controllerContext, bindingContext, modelType);

return result;
}
}

Next, we need to ensure this new model binder is the default model binder. To do this, we need to simply add this line in our global.asax.cs file, somewhere where it will be called from Application_Start():

ModelBinders.Binders.DefaultBinder = new DependencyInjectionModelBinder();

So, now we have a DependencyInjectionModelBinder registered as our default model binder for our application. Now, supposing that Widget implements IWidget, and you want your view and controller to rely on IWidget instead of Widget, you need to ensure you've registered Widget as the default concrete class of IWidget. Add this line so it will be called from the Application_Start method in the global.asax.cs file:

ObjectFactory.Configure(x => x.For<IWidget>().Use<Widget>());

Lastly, we need to change our view and our controller to use the interface instead of the concrete class:

View:

<%@ Page Title="" Language="C#" MasterPageFile="../Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MyNamespace.IWidget>" %>

Controller:

[HttpPost]
public void Details([Bind] IWidget widget)
{
// do something with the widget.
}

That's it! You've now made MVC more SOLID by adhering to dependency inversion principle in your controller and your view. Nowhere in your application, other than when registering Widget as the default implementation of IWidget, should you need to directly reference Widget as a concrete class.

Sunday, March 14, 2010

"Value types do not support variance".... but why?

I was reading over the details regarding the new way the IEnumerable<out T> interface is implemented in C# 4.0, specifically as it relates to covariance and contravariance. In my reading, I came across this interesting statement:
"Value types do not support variance."
What does that mean?

Certainly, the following code compiles just fine:
IEnumerable<object> strings = new List<string>();
But the following does not:
IEnumerable<object> ints = new List<int>();
Nothing more is stated in the documentation, other than that variance is not supported on value types. So I got to thinking... why is this?

Here's my theory (and I'd love to have someone from Microsoft verify this for me). When you're converting the List<string> to an IEnumerable<object>, you're not actually changing the real essence of what your original List<string> is. Internally, the List<string> class is going to still hold on to an array of references to objects on the heap, but instead of specifying that those objects on the heap are strings, we simply say they're objects instead. An array of value types, however, is different. The array of integers is a block in memory that holds the actual values, whereas the array of strings is a block of memory that holds references to the actual values, which are residing somewhere else on the heap. So what would have to happen in order for the covariance to work? Basically, an entirely new list would have to be created, and each value that resides in the internal array supporting List<int> would have to be boxed and the boxed reference placed in a new array, thus creating an entirely new List<object> to support this kind of thing.

This would be more than simply a performance hit. This would require every implementor of IEnumerable<out T> to define an "escape route" so to speak for when the type of T is a value type. So, instead of jumping through hoops to support this scenario, it's simply disallowed.