使用自定义ModelBinder在控制器操作中使用强类型TPH模型 - 这有点臭吗?

时间:2009-08-28 00:02:19

标签: asp.net-mvc linq-to-sql inheritance binding model

以下是我的解决方案的一些背景知识:

  • ASP.Net MVC app
  • 将Linq-to-SQL与每层次表继承一起使用
  • 默认使用DataAnnotationsModelBinder

所以我有一个Device抽象类,然后是一系列派生类(ServerDeviceDiskDevicePSUDevice等),它们在被禁止的Linq中继承它-to-SQL方式。我有一个控制器处理所有这些不同的相关模型类型,它根据类型呈现不同的部分和一个方便的下拉选择它们。我的(GET)Create方法如下所示:

// GET: /Devices/Create/3
public ActionResult Create(int? deviceTypeID)
{
    return View(DeviceFactory(deviceTypeID);
}

其中DeviceFactory是静态方法,基于int鉴别器返回其中一个派生类的新实例。 POST Create方法如下所示:

// 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);
}

我的自定义模型绑定器如下所示:

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]);
    }
}

因此,在尝试了解这一整天,阅读ActionInvoker,自定义ActionFilters以及各种其他MVC之后,我想知道我到达的解决方案是否是一个好的解决方案。帮助减轻我的恐惧,我错过了一些非常明显的概念并重新发明了轮子。 有更好或更简洁的方法吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

我的POV将实体/域类型绑定到UI根本就是“臭”。我在this answer中更详细地解释了这一点。恕我直言,你几乎应该总是使用专用的演示模型模型绑定使表示模型更容易,这是一个很好的附带好处,但在链接的答案中讨论了更重要的好处。