When you expect data in non-standard way and you want it to magically bind to your model, custom model binders could be a way to go.
Let’s say we want to post xml data to our controller method and we have a model for it.
public class XmlModel { public int Number { get; set; } }
Which we want to accept in our controller method:
public ActionResult Xml(XmlModel xmlModel) { return Content(xmlModel.Number.ToString()); }
Now, let’s add our xml binder:
public class XmlModelBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { var modelType = bindingContext.ModelType; return new XmlSerializer(modelType).Deserialize(controllerContext.HttpContext.Request.InputStream); } }
And XMLModelBinderProvider:
public class XMLModelBinderProvider : IModelBinderProvider { public IModelBinder GetBinder(Type modelType) { var contentType = HttpContext.Current.Request.ContentType; if (string.Compare(contentType, @"text/xml", StringComparison.OrdinalIgnoreCase) != 0) { return null; } return new XmlModelBinder(); } }
Add the provider to our Application_Start method in the Global.asax:
ModelBinderProviders.BinderProviders.Insert(0, new XMLModelBinderProvider());
To test this we can use Composer from Fiddler:
http://localhost/home/xml
User-Agent: Fiddler
Content-Type: text/xml
Request Body:
<XmlModel> <Number>42</Number> </XmlModel>
If we add breakpoint in our controller, we should see 42 coming through in our model.