Category: ASP.NET MVC


Easy Compression with ASP.NET MVC

May 2nd, 2009 — 3:48pm

ASP.NET MVC already comes with great performance out of the box…due mostly to the lightweight nature of the framework. However, in the never-ending pursuit of faster load times I starting looking into what it would take to put together an Action Filter to compress the output of a controller action. Turns out, it’s pretty damn easy. Here’s what I came up with:

public class CompressAttribute : ActionFilterAttribute {
 
        public override void OnActionExecuting(ActionExecutingContext filterContext) {
 
            var encodingsAccepted = filterContext.HttpContext.Request.Headers["Accept-Encoding"];
            if (string.IsNullOrEmpty(encodingsAccepted)) return;
 
            encodingsAccepted = encodingsAccepted.ToLowerInvariant();
            var response = filterContext.HttpContext.Response;
 
            if (encodingsAccepted.Contains("deflate")) {
                response.AppendHeader("Content-encoding", "deflate");
                response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
            } else if (encodingsAccepted.Contains("gzip")) {
                response.AppendHeader("Content-encoding", "gzip");
                response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
            }
        }
    }

And you can use it like this:

[Compress]
public class ThingController : Controller { ... }

or on a controller action:

public class ThingController: Controller {
 
    [Compress]
    public ActionResult Index() { ... }
}

As you can see it really just sets a new filter for the response; GZipStream or DeflateStream depending on what the browser can handle and then sets the appropriate flag. After doing some lightweight testing it looks like the compressed output is on average 18% of the original size. My next task is to do some testing around how long the client takes to actually decompress the response. My guess is that it’s pretty negligible though.

10 comments » | ASP.NET MVC

ASP.NET MVC, StructureMap, and the 404

March 13th, 2009 — 4:28pm

ASP.NET has a great mechanism for handling 404′s in an elegant way. In a purely declarative manner you can add the following to your Web.config:

<error statusCode="404" redirect="/Session/Error" />

This works great when you are using ASP.NET, but when you’re using StructureMap (or any IoC container) to override the DefaultControllerFactory in ASP.NET MVC you have a bit of a problem in finding the non-existent controller type…namely…an Exception. For example, here’s what I’m doing with the controller factory and StructureMap:

public class InjectionControllerFactory : DefaultControllerFactory {
    protected override IController GetControllerInstance(Type controllerType) {
        return ObjectFactory.GetInstance(controllerType) as Controller;
    }
}

The problem is that when controllerType is null (i.e. there is no controller for the given URL) then an exception is thrown in the call to ObjectFactory.GetInstance. So our fancy error setup in the Web.config is moot because an exception is thrown before we even get there.

So, how do we fix this? Well…it’s simple really…let MVC do it’s thing. The DefaultControllerFactory method that we’re overriding here already handles this situation gracefully, so just call the base method if the ObjectFactory.GetInstance call can’t be completed.

public class InjectionControllerFactory : DefaultControllerFactory {
    protected override IController GetControllerInstance(Type controllerType) {
        if (controllerType != null) {
            return ObjectFactory.GetInstance(controllerType) as Controller;
        return base.GetControllerInstance(controllerType);
    }
}

Voila, now our “virtual” 404 is handled and our special 404 page is displayed.

1 comment » | ASP.NET MVC

ASP.NET MVC En Masse – Areas

March 12th, 2009 — 6:50pm

So I’m embarking on my first really large ASP.NET MVC project and I’m really excited about the prospects. But, with any new programming model comes change and little snags that you didn’t see coming. So I’m going to try and blog about these as the project progresses so others can see how we handled such obstacles and to help reinforce the solution in my own mind.

The first thing that you’ll run into in any large MVC application (and I suspect this would happen with Rails or Django as well) is that you end up with a lot of controllers…I mean…a lot of controllers. Inevitably these controllers revolve around similar functionality but you can’t quite bring yourself to combine them because doing so would create uber-controllers that break single responsibility and become unmanageable in their own right. The solution of course is to inject some conceptual node above the controller layer…in essence you want to group controllers.

So after doing some digging I found an excellent blog post by Phil Haack (the instigator of ASP.NET MVC at Microsoft). I think Phil is great, he’s stuck it to the “man” with an great project that beats WebForms hands down. Anyway, in his post he describes a mechanism for extending routing so that you can add essentially another layer to the application above controller, he calls them “areas” but I don’t think it really matters what you call them

If you download the source code for his prototype you’ll see that it’s basically a standard MVC project with just a few small modifications.

  • AreaRouteHelper.cs – This guy’s job is to add areas to route mapping.  It allows you to map routes inside areas and also map routes to the “root” or controllers that aren’t in an area.
  • AreaViewEngine.cs – this just adds patterns so that aspx/ascx views can be found one more level down in the file structure.
  • Changes to the global.asax to register the new area engine.
  • Changes to how the route table is set up (using AreaRoutHelper methods)

It’s super simple to set up and a really effective way to extend the MVC structure.

Comment » | ASP.NET MVC

Integrating Adobe Flex and .NET with ASP.NET MVC

January 2nd, 2009 — 3:30pm

There are a lot of tools out there to help you utilize .NET as a back-end for Flex applications.  All of these solutions come with a heavy customization and implementation cost.  I’ve used WebORB with quite a bit of success in the past but it always seemed a little heavy to me.  The truth is that WebORB and its compatriots are the right choice for large applications or apps with highly complex server side needs.  But for the lightweight web application that doesn’t require tons of server side business logic there is another choice.

With the advent of ASP.NET MVC we have a very simple way to construct web accessible .NET endpoints – controller actions.  In the past when you needed to get data out of .NET using HTTP you might spin up a web service or a WCF service.  These are still great options, but if the data you need to transfer is small and/or jagged you might find yourself writing a lot of extra code.  You’ll also pay the XML tax and nobody likes paying taxes.

So if not XML, what then?  Well, JSON of course.  JavaScript Object Notation is a perfect media for transmitting moderate amounts of data over the wire.  And there are excellent serialization options on both the .NET and Flex sides of the game.  So here’s a little example of this pattern in action.

Create an ASP.NET MVC Controller Action – Return JSON.

public ContentResult GetInventory() {
var repository = new InventoryRepostiory();
var items = repository.GetItems().ToList<InventoryItem>();
return Content(items.ToJSON(null));
}

I’m not going to go into the data access pattern here in this article, but I’m using a repository to return a set of inventory items.  You might also be wondering where this ToJSON() method comes from.  It’s an extension method…and here it is (c/o ScottGu):

public static string ToJSON(this object thing, int? recursionDepth) {
    var serializer = new JavaScriptSerializer();
    if (recursionDepth.HasValue)
        serializer.RecursionLimit = recursionDepth.Value;
    return serializer.Serialize(thing);
}

All it does is take an object, do a little reflection magic on it via the System.Web.Script.Serialization.JavaScriptSerializer class and spits out a JSON string.

Calling Your ASP.NET MVC Controller Action from Flex

The first thing you’ll need on the Flex side before you can consume your MVC action is a way to de-serialize the JSON string.  Fortunately, the Adobe guys have provided a handy library of utilities called AS3CoreLib which contains just such a service.  Once you have the SWC just pop it in the Libs folder of your Flex app.

So now let’s create a wrapper class in ActionScript to consume our ASP.NET MVC action.  I like to mimic the repository pattern on the Flex side as well so that I can keep up with a somewhat consistent API.  There’s nothing that technically holds you to this rule, but it’s helpful to keep things logically organized.  So, here’s the InventoryRepository in AS3:

package Data {
    import com.adobe.serialization.json.*;
    import flash.net.*;
    import flash.events.*;
    import mx.collections.ArrayCollection;
 
    public class InventoryRepository {
 
        private var completeCallback:Function;
 
        public function GetInventory(callback:Function) : void {
            completeCallback = callback;
            var loader:URLLoader = new URLLoader(new URLRequest("http://localhost/Home/GetInventory"));
            loader.addEventListener(Event.COMPLETE, getInventoryComplete);
        }
 
        private function getInventoryComplete(event:Event) : void {
            var obj:Object = JSON.decode(event.target.data);
            completeCallback(obj);
        }
    }
}

You’ll notice that I’ve imported the com.adobe.serialization.json classes from AS3CoreLib.  That provides us with the JSON.decode() method.

Now, because remote calls in Flex are asynchronous, we need to do a little fancy footwork to deal with it.  So, when you call the GetInventory() method we also have to supply a callback to fire off when the data returns from the MVC action.  This is one of my favorite aspects of ActionScript…it’s dynamic…dynamic in the JavaScript sense of the word.  So we can supply a callback that doesn’t need to be defined in our repository class itself. 

So let’s look at some code that consumes our repository method.  This is just a code-behind file for an MXML appl ication:

package InventoryApplication {
    import mx.core.Application;
    import flash.events.Event;
    import mx.controls.DataGrid;
    import mx.collections.*;
    import Data.*;
 
    public class HomeApplication extends Application {
 
        public var inventoryGrid:DataGrid = new DataGrid();
 
        public function InventoryApplication() {
            super();
            LoadInventory();
        }
 
        public function LoadInventory () : void {
            var repository:InventoryRepository = new InventoryRepository ();
            repository.GetInventory(function(data:Object) : void {
                inventoryGrid.dataProvider = data;
            });
        }
    }
}

So the only really interesting thing here is how we’re defining the callback as an anonymous function passed into the GetInventory() method.  When the data is returned we just bind it to our data grid and we’re done.

Sending Data To an ASP.NET MVC Action From Flex

So, now we can pull data out of our .NET back end, but how do send data into an MVC action from Flex?  The solution couldn’t be simpler.  So here’s a new method for the AS3 repository:

public function CreateKind(itemName:String,
    itemType:String,
    itemSize:String,
    callback:Function) : void {
 
    var variables:URLVariables = new URLVariables();
    variables.name = itemName;
    variables.type = itemType;
    variables.size = itemSize;
 
    var request:URLRequest = new URLRequest("http://localhost/Home/CreateKind");
    request.method = URLRequestMethod.POST;
    request.data = variables;
 
    var loader:URLLoader = new URLLoader(request);
}

Here you can see we’re passing in the properties of our new item and adding them to the variables object directly (another nice thing about ActionScript being dynamic).  So now these new properties will become variables in the form collection sent to our controller action.  Here’s our controller action:

public ContentResult CreateItem(string name, string type, string size) {
 
    var item = new InventoryItem
    {
        Name = name,
        Type = type,
        Size = size
    };
 
    var repo = new InventoryRepository();
    repo.SaveItem(item);
 
    return Content("true");
}

You’ll notice that the parameters it accepts are “name”, “type”, and “size”.  These are the same properties added to the Flex URLVariables object in our Flex repository class.  Through the magic of ASP.NET MVC these items are simply available to the controller action as parameters, simple as that.

So, hopefully that demonstrates how easy it is to use ASP.NET MVC to integrate a .NET back-end with Flex.  I think the advantages of this method are substantial, but do your research and take a look at the other options as well.

5 comments » | ASP.NET, ASP.NET MVC, Flex

Use jQuery.post to submit to ASP.NET MVC Actions

November 26th, 2008 — 7:02pm

Recently, Microsoft announced that jQuery will be shipping with future versions of Visual Studio.  In fact, today the ASP.NET MVC bits already ship with jQuery.  ASP.NET MVC is extremely friendly with jQuery. 

One of the things that ASP.NET MVC gives you over web forms is an easy way to expose actions to the client.  Here's where AJAX using jQuery really shines.  In the past if you wanted to initiate some server side action using JavaScript, you'd need to expose a web service of some kind and then call into your server from there.  With ASP.NET MVC you can simply submit a post to an action via a URL and you're off.

For example, I might have the following action called 'DoSomething' on my 'Thing' controller:

public ActionResult DoSomething(int thingId, string thingName, 
        DateTime thingDate) {

        var db = new ThingEntities();
        var thing = (from Thing t in db.Things
                                      where t.ID == thingId,
                                      select t).First<Thing>();

        thing.Name = thingName;
        thing.ThingDate = thingDate;

        db.SaveChanges(true);

return Content("true");
}

Calling this method from JavaScript becomes almost trivial using the jQuery.post method:

$.post("/Thing/DoSomething", { thingId: 7, thingName: 'New Thing', thingDate: '1/1/2008' }, function(data) { alert(data); });

So the post method has three parameters:

  1. The URL of the action to post to. 
  2. An object comprising the data to send with the post. 
  3. A callback method which fires when the request returns. 

It's as simple as that.  So now making calls back to your server from JavaScript is as easy as writing a controller action that takes simple types as parameters.  There are several different jQuery AJAX methods to chose from and obviously some more advanced things that you can do, but as you can see the basics are pretty simple.

2 comments » | ASP.NET MVC, jQuery

Back to top