February 2010 Entries

Using ModelBinder with ASP.NET MVC to map UploadStatus into an action method

Up until SlickUpload 5.5, the ASP.NET MVC examples demonstrated calling the SlickUpload.GetUploadStatus() method in your action method to get the current upload status. This isn't the optimal way to get access to upload status and uploaded files in your action method -- it violates the idea of separation of concerns that MVC is built upon.

Fortunately, the fix is easy -- create and register a custom ModelBinder that maps the UploadStatus into a parameter for your action method. The model binder is simple:

using System;
using System.Web;
using System.Web.Mvc;

using Krystalware.SlickUpload;
using Krystalware.SlickUpload.Controls;
using Krystalware.SlickUpload.Status;

public class UploadStatusModelBinder : IModelBinder
{
    public static void Register(ModelBinderDictionary modelBinders)
    {
        if (!modelBinders.ContainsKey(typeof(UploadStatus)))
            modelBinders.Add(typeof(UploadStatus), new UploadStatusModelBinder());
    }

    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        UploadStatus status = HttpUploadModule.GetUploadStatus() ?? UploadConnector.GetUploadStatus();

        return status;
    }
}

The Register method manages registering this class in ASP.NET MVC's model binder lookup. Call it from your Application_Start, the same place where you register routes. Something like:

protected void Application_Start()
{
    RegisterRoutes(RouteTable.Routes);

    UploadStatusModelBinder.Register(ModelBinders.Binders);
}

The BindModel method does the actual binding. The logic pulls the UploadStatus for the current context, and if that isn't available checks to see if this is a SlickUpload based after upload postback and returns the UploadStatus for that. If it's neither, the parameter will recieve null.

So, your MVC controller action method changes from this:

public ActionResult UploadResult()
{
    UploadStatus status = SlickUpload.GetUploadStatus();

    // controller logic

    return View(status);
}

To this:

public ActionResult UploadResult(UploadStatus status)
{
    // controller logic

    return View(status);
}

SlickUpload 5.5 released

We've recently released SlickUpload 5.5. This was originally going to be v. 5.4.3, but it ended up getting some larger improvements, primarily around ASP.NET AJAX support. The ASP.NET AJAX support has been completely rewritten in version 5.5, with much improved support for advanced scenarios. We have also set up a comprehensive test suite to cover the ASP.NET AJAX functionality to ensure that it handles every edge case and continues to do so.

Several more things made it into this release:

  • Refactoring of the FileList. The file related events and methods were removed to reduce confusion and code surface area -- you can do anything you once did with this functionality by using the identical events and methods on the FileSelector.
  • Added the OnFileAdding event. This allows you to perform validation on a file before it is selected before it is added to a list. If your handler returns false, the file won't be added.

There are also a slew of small fixes and enhancements, including:

  • Added support for setting progress url
  • Fixed keyboard accessibility on downlevel template