Skip to content

Instantly share code, notes, and snippets.

@joelpurra
Created April 18, 2012 18:26
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joelpurra/2415633 to your computer and use it in GitHub Desktop.
Save joelpurra/2415633 to your computer and use it in GitHub Desktop.
InheritedClassModelBinder: A ModelBinder for ASP.NET MVC3 that handles creating concrete class instances mapped to an abstract superclass. Based on code by Kelly.
namespace JoelPurra.Web.Binders
{
using System;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Web.Mvc;
using rDoing.Scraper.Web.Mvc.Controllers.ViewModels.Binder.Helpers;
/// <remarks>
/// Based on
/// http://stackoverflow.com/questions/5460081/asp-net-mvc-3-defaultmodelbinder-with-inheritance-polymorphism
/// http://stackoverflow.com/questions/5460081/asp-net-mvc-3-defaultmodelbinder-with-inheritance-polymorphism/7517655#7517655
/// http://stackoverflow.com/questions/4012217/asp-net-mvc-2-binding-to-abstract-model
/// http://stackoverflow.com/questions/4012217/asp-net-mvc-2-binding-to-abstract-model/7517417#7517417
///
/// Original by Kelly
/// http://stackoverflow.com/users/85802/kelly
///
/// Edited by Joel Purra
/// https://gist.github.com/2415633
/// </remarks>
public class InheritedClassModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
if (modelType.IsAbstract)
{
// modelType is the abstract base class
// concreteModelTypeName is the concrete subclass
var concreteModelTypeName = ContextValueHelper.GetValue(controllerContext, bindingContext, "ModelTypeName");
Contract.Assert(concreteModelTypeName != null, "View does not contain ModelTypeName");
var type = modelType.Assembly.GetTypes().SingleOrDefault(x => x.IsSubclassOf(modelType) && x.Name == concreteModelTypeName);
Contract.Assert(type != null, "Invalid ModelTypeName");
var instance = bindingContext.Model ?? base.CreateModel(controllerContext, bindingContext, type);
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => instance, type);
return instance;
}
return base.CreateModel(controllerContext, bindingContext, modelType);
}
}
}
@joelpurra
Copy link
Author

Using a custom model binder to bind concrete subclasses to an abstract superclass. Found the question ASP.NET MVC 3: DefaultModelBinder with inheritance/polymorphism and used the answer from by Kelly, Kelly has added a new revision of the code in the answer to another question, ASP.NET MVC 2 - Binding To Abstract Model. I will post my version of the code here, as it's easier to keep track of it on gist.

@joelpurra
Copy link
Author

In case you see the reference to SharpArch.Web.Mvc.ModelBinder in any of the revisions it's because I'm using SharpModelBinder as a base class in my local version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment