Custom XML model binder for ASP.NET MVC

In an earlier post I wrote about using an XML value provider to allow you to send XML to your .NET MVC action methods. This is great, until you want to accept XML where you have a model that needs XML attributes to control how it's deserialized. As the value provider stage happens before model binding it has no knowledge of the model objects that the values will be pushed into. So it can't look at your model class's XML attributes.

In cases like this, you're better of using a custom XML model binder.

To setup an XML model binder you need to create a model binder and a model binder provider. You then need to register the model binder provider in you app's startup.

XML Model Binder

using System;
using System.Web.Mvc;
using System.Xml.Serialization;

namespace XmlBinderExample.MVC.Extensions
{
    public class XmlModelBinder : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var serializer = new XmlSerializer(bindingContext.ModelType);
            try
            {
                var boundModel = serializer.Deserialize(controllerContext.HttpContext.Request.InputStream);
                return boundModel;
            }
            catch (Exception e)
            {
                // Todo: Log this failed binding
                return null;
            }
        }
    }
}

XML Model Binder Provider

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

namespace XmlBinderExample.MVC.Extensions
{
    public class XmlModelBinderProvider : IModelBinderProvider
    {
        public IModelBinder GetBinder(Type modelType)
        {
            var requestType = HttpContext.Current.Request.ContentType.ToLower();

            return (requestType == "application/xml"
                || requestType == "text/xml")
                       ? new XmlModelBinder()
                       : null;
        }
    }
}

Register the provider

In Global.asax modify your Application_Start method to include this extra line:

ModelBinderProviders.BinderProviders.Add(new XmlModelBinderProvider());

And you're done.