Thursday, January 21, 2010

Scaffolding, автогенерация форм и интерфейсов управления данными.

Чтобы было не очень скучно, я поставлю себе определённую задачу и буду решать её, применяя технологии ASP.NET MVC. Насмотревшись всяких демо-роликов, мы сможем быстро начать писать простенькие веб-приложеница, но этого мало. Мне нужно больше.

Я хочу сделать генератор форм и списков для управления данными. Буквально недавно узнал заморское слово скафолдинг (scaffolding) и начал его везде говорить. Ну вы поняли, что всё то, о чём я только что сказал называется скафолдингом. Согласитесь, что короче сказать «скафолдинг», чем произносить это длинное заклинание про автогенерацию форм и списков по формально описанной структуре данных, хотя обычным людям всё же понятнее :) На самом деле, скафолд-приложение — это некое быстро достижимое или генерируемое прото-приложение, которое в дальнейшем можно усложнять и кастомизировать.

Ладно, с терминами разобрались. Давайте смотреть как обстоят дела со скафолдингом.
Профессионалы ASP.NET знают, что для этого надо использовать Dynamc Data, который отлично работал со старым добрым ASP.NET, а теперь даже может работать вместе с MVC, что не может не радовать. Следующие посты я буду посвящать предварительной реализации Dynamic Data for ASP.NET MVC. Буду его ковырять и понимать как с его помощью что-то делать. Тема эта достаточно обширна и в один пост её будет трудно уместить. Начнём с формального описания задачи, в котором будет содержаться ключ к её решению.

Задача скафолдинга

Большинство веб-приложений работают с данными: позволяют их смотреть, добавлять и редактировать. Это так называемые CRUD (create, read, update, delete) приложения, создание которых мы бы хотели максимально автоматизировать. Что для этого потребуется? В первую очередь, нужна схема (структура) данных, по которой можно восстановить всевозможные связи между таблицами и их полями. С этой схемой необходимо уметь как-то работать. Удобнее всего работать с объектной моделью этих данных. Далее есть два пути: (1) воспользоваться стандартными правилами отображения типов данных полей таблицы на html-форму, либо (2) задать самостоятельно, желательно максимально гибко и просто, конкретные правила отображения этих типов на форму.

С первым вариантом всё просто. Вспомните любой визуальный клиент к базе данных, например, родимый phpMyAdmin. Да, он из другой оперы про презренный php, но он хорошо иллюстрирует подход. Если поле varchar, то управляет им простой input type="text", если дата, то стандартный календарик, если bool — чекбокс, внешний ключ — Select ну и так далее.

Со вторым вариантом несколько сложнее он нужен, когда простые элементы управления: инпуты, чекбоксы, селекты и календарики, нам уже не подходят, либо помимо них нужно что-то ещё. Например, мы хотим загружать картинки с помощью SWFUpload, использовать WYSIWYG-редактор для текста, изобретать невероятный контрол, который будет управлять одновременно несколькими множественными связями и т.д. Если вы скажете, что в этом случае надо делать всё управление руками, то окажетесь неправы только отчасти. Да, все мудрёные контролы в стандартный набор не включены, но их же можно один раз написать, а потом много раз использовать — профит!

Таким образом, нам нужно разобраться каким образом можно получить интерфейс для доступа к схеме базы данных, каким образом сконфигурировать отображение этой схемы на html-форму в виде контролов, а также как это потом всё показать в ASP.NET MVC приложении.

Tuesday, January 12, 2010

Интересный факт о protected internal и немного о контроллерах

Вчера стало интересно как устроен внутри класс Controller из ASP.NET MVC 2.0 RC. Этот класс иллюстрирует замечательный паттерн Command, согласно которому, внутри класса должна быть реализована функция выполнения. В нашем случае,  Controller реализует интерфейс IController и определяет метод Execute, внутри которого подыскивает один из своих методов, способных обработать пришедший запрос, то есть вызывает один из своих Action-методов, которые возвращают объект подтипа абстрактного типа ActionResult.

Интересно то, что обычно эти экшены не создают новый объект, например new ViewResult(), а вызывают метод родительского класса Controller, например return View() или return Json(). Так вот, в классе Controller эти методы определены как protected internal, например,

protected internal JsonResult Json(object data)

Прочитав про модификатор internal в MSDN я узнал, что он ограничивает использование метода внутри сборки, то есть вызов метода с модификатором internal  в другой сборке приведёт к ошибке. Как же тогда оно работает? Как мы в своих контроллерах спокойно вызываем эти методы и никаких ошибок не происходит? Оказалось, что вместе модификаторы protected и internal связываются логическим или, то есть запись с ними следует читать, как
protected [OR] internal,
поэтому выходит, что вне сборки этот метод экземпляра класса вызывать нельзя, но наследникам класса в другой сборке — можно :)

Получается, что определив protected internal метод мы можем:
внутри сборки 
          вызывать его как из классов-наследников, так и у экземпляра класса
вне сборки
          только у наследников

Такие дела.