Here's a little background on my solution:
- ASP.Net MVC app
- Using Linq-to-SQL with table-per-hierarchy inheritance
- Using DataAnnotationsModelBinder as default
So I have a Device
abstract class and then a series of derived classes (ServerDevice
, DiskDevice
, PSUDevice
, etc) that inherit from it in the proscribed Linq-to-SQL way. I have one controller that handles all these different related model types, and it renders different partials based on the type and a handy drop down to select them. My (GET) Create method looks like this:
// GET: /Devices/Create/3
public ActionResult Create(int? deviceTypeID)
{
return View(DeviceFactory(deviceTypeID);
}
Where DeviceFactory
is a static method returns a new instance of one of the derived classes based on an int discriminator. The POST Create method looks like this:
// POST: /Devices/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([ModelBinder(typeof(DeviceModelBinder))]Device device)
{
if (!ModelState.IsValid)
return View(device);
_repository.Add(device);
_repository.Save();
TempData["message"] = string.Format("Device was created successfully.");
return RedirectToAction(Actions.Index);
}
and my custom model binder looks like this:
public class DeviceModelBinder : DataAnnotationsModelBinder
{
private readonly Dictionary<string, Type> _deviceTypes =
new Dictionary<string, Type>
{
{"1", typeof (ServerDevice)},
{"2", typeof (DiskDevice)}
// And on and on for each derived type
};
protected override object CreateModel(ControllerContext controllerContext,
ModelBindingContext bindingContext, Type modelType)
{
return base.CreateModel(controllerContext, bindingContext,
_deviceTypes[bindingContext.ValueProvider["deviceTypeID"].AttemptedValue]);
}
}
So after trying to hook this up all day, reading about ActionInvoker, custom ActionFilters, and all sorts of other MVC stuff, I'm wondering if the solution I've arrived at is a good one. Help allay my fears that I'm missing some hugely obvious concept and re-inventing the wheel. Is there a better or more concise way?
Thanks!