Использование собственного ModelBinder для строго типизированных моделей TPH в действиях контроллера - это вонючий? - PullRequest
0 голосов
/ 28 августа 2009

Вот небольшая предыстория моего решения:

  • Приложение ASP.Net MVC
  • Использование Linq-to-SQL с наследованием таблиц на иерархию
  • Использование DataAnnotationsModelBinder по умолчанию

Итак, у меня есть Device абстрактный класс, а затем серия производных классов (ServerDevice, DiskDevice, PSUDevice и т. Д.), Которые наследуются от него в запрещенном способе Linq-to-SQL. У меня есть один контроллер, который обрабатывает все эти различные связанные типы моделей, и он отображает различные партиалы в зависимости от типа и удобный выпадающий список для их выбора. Мой (GET) метод Create выглядит следующим образом:

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

Где DeviceFactory - статический метод, возвращающий новый экземпляр одного из производных классов на основе целевого распознавателя. Метод 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 Ответ

1 голос
/ 28 августа 2009

Мой POV - это "вонючий" способ связать типы сущностей / доменов с пользовательским интерфейсом вообще. Я объяснил это более подробно в этом ответе . ИМХО, вы почти всегда должны использовать специальные модели презентаций. Приятным дополнительным преимуществом является то, что привязка модели значительно упрощает представление модели, но более важные преимущества обсуждаются в связанном ответе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...