четверг, 18 февраля 2010 г.

Пишем CMS. Совет - удаленная отладка

Иногда бывает так, что кажется - невозможно понять, откуда у ошибки ноги растут. Или как решить данную проблему. В этом случае мне всегда помогает удаленная отладка. "Удаленная" - это не про код и не про машину, а про разработчика. Т.е. разработчик в прямом смысле слова удален от компьютера и кода. Можно пойти в душ, хорошо думается на обратном пути к дому. А главное - ничего не отвлекает. Когда вы сидите за компьютером и мельтешите по коду, замыливаются и глаз, и мозг. Когда код только в уме, это настоящая квинтэссенция мышления. Какое-то там сияние чистого разума. Рекомендую. Во время удаленной отладки надо представить себе вызовы, что почему вызывается и где что может ломаться. То же самое и с программированием - мысленно располагайте проблему перед собой и ищите пути решения. Это даже лучше работает, чем листок бумаги. Серьезно!

среда, 17 февраля 2010 г.

Пишем CMS. Шаг № 2. Подключаем ADO.NET Entitry Framework

Сейчас нам надо разобраться, как работать с Entity Framework. Этот момент довольно подробно описан в моем старом посте здесь, поэтому я не буду повторяться, а лишь опишу шаги и действия, которые надо сделать, чтобы:
1) Сгенерировать классы для работы с БД
2) Просмотреть список доступных языков.
Не так уж много, но для этого шага достаточно.

Итак, создайте в солюшене новый проект, который назовите, например, DAL (data access layer). После создания проекта рекомендуется указать в его свойствах название dll, которая будет сгенерировать и пространство имен, создаваемое по умолчанию. Общепринятой практикой является давать названия в формате <Название производителя>.<Название всего проекта>.<Название конкретного проекта>.

После этого добавьте в проект новый айтем - выберите ADO.NET Entity Data Model. На экране появится визард, в котором вы указываете сервер базы данных (выберите сперва Generate from database), затем укажите таблицы, которые будут использованы для генерирования классов. После этого в вашем проекте появится файлы .edmx и .designer.cs.

Поскольку мы будем вызывать методы из классы из нашего веб-проекта (на данном этапе), нужно скопировать строку подключения из файла app.config в файл web.config нашего веб-проекта.

Теперь в веб-проекте создайте каталог Language и добавьте в него две формы (на основе Master page - это будут Web Content Form). Про мастер-страницу мы поговорим немного позже, а пока, если вы еще не создали ее, то создайте, и добавьте две страницы Languages.aspx и LanguageEdit.aspx. Первая страница позволит нам просматривать список языков и удалять ненужные, вторая - создавать новые и редактировать уже имеющиеся языки.

Откройте страницу Languages.aspx и разместите на ней контрол GridView (на самом деле вы можете разместить любой другой контрол, позволяющий просматривать данные в режиме таблицы, но пусть пока будет этот). Выставьте свойство AutoGenerateColumns = false (нам не нужны столбцы, генерируемые автоматически) и добавьте в таблицу столбцы типа BoundField, для каждого столбца укажите в поле DataField соответствующее поле таблицы. После этого добавьте в референсы проекта референс на наш DAL-проект, затем откройте файл кода Languages.aspx.cs и добавьте в список пространств имен наше пространство имен .DAL.

Создайте метод, например LoadLanguages и добавьте в него простой код, который будет вытягивать все наши языки из базы (пейджинг пока не рассматриваем).

private void LoadLanguages()
{
using (WebDatabaseConnection context = new WebDatabaseConnection())
{
var query = from l in context.Language
select l;
gridLanguages.DataSource = query;
gridLanguages.DataBind();

}
}

Здесь WebDatabaseConnection context - это главный класс для работы с базой данных. Он был сгенерировать Entity Framework и найти его можно в соответствующем файле нашего DAL-проекта. Разумеется, этот код следует обрамить конструкцией try-catch, но мы этого пока делать не будем. Во-первых, потому, что нам надо четко решить, что делать в случае возникновения ошибки, а во-вторых, неплохо бы знать, какое исключение может быть выброшено, чтобы правильно интерпретировать результат. Дело в том, что мы не можем показывать пользователю исходное сообщение, которое будет содержать эксепшн, это противоречит принципам безопасности, да и не нужно особо - ведь уровень подготовки пользователя неизвестен. Поэтому обработкой ошибок мы займемся чуть позже.

Заметьте, что в этом коде мы используем простейшую конструкцию Linq to Entity Framework, чтобы получить все данные из таблицы.

Теперь в код метода PageLoad мы разместим вызов нашего метода, который будет грузить данные в таблицу:

protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
LoadLanguages();
}
}


Здесь мы сначала проверяем, является ли вызов обратным (postback) - это может случиться только в том случае, если мы производим какую-либо обработку данных, поэтому отображать данные нам в этот момент не нужно. Как же так? - спросите вы. А очень просто. Дело в том, что после каждой обработки данных мы будем делать редирект на эту же страницу. Объясню, зачем. Если мы ограничимся одним постбэком и откроем эту же страницу после постбэка без редиректа, а затем нажмем F5, чтобы обновить страницу, браузер покажет сообщение о том, что мы собираемся заново отправить данные. Допустим, мы перед этим удалили язык. У нас будет выбор - отправить данные заново или нажать Cancel. Если мы отменим действие, обновления страницы не произойдет, если нажмем Resend, наше приложение получит повторное сообщение об удалении языка, который уже был благополучно удален, в результате чего мы увидим ошибку. Конечно, можно эту ошибку обработать, но зачем? Куда как проще открыть страницу заново и, сколько мы не будем нажимать F5, повторного удаления (или иного действия) не будет.

пятница, 12 февраля 2010 г.

Пишем CMS. Шаг № 1. Подготовительная работа

Прежде всего, определимся со структурой-архитектурой-технологией. Технология - используем связку ASP.NET 3.5 + SQL Server 2005, все это будем делать в бесплатной студии 2008 (то есть конечно, наверное, не всем она досталась бесплатно, но мне лично удалось получить ее на дне разработчика). В процессе разработки надо будет постараться использовать преимущества асп3.5.
Структура сайта проста - есть основной проект, параллельно ему существует админский, а также библиотека для DAL (кто не знает, что это, отсылаю к википедии).

Пока что мне не нравится идея создавать каждую страницу на лету, поэтому сейчас мы этого делать не будем, а будем создавать спокойно странички для каждого раздела в отдельности. Например, для управления языками у нас будет две страницы Languages.aspx и LanguageEdit.aspx, которые мы положим в каталог Languages. Вполне возможно, что в процессе работы эти страницы исчезнут, но не будем загадывать раньше времени. А пока надо сделать несколько важных вещей.

1. Настроить систему контроля версий. Как это сделать, очень хорошо описано вот в этой книге: ASP.NET 3.5 Social Networking . Вообще классная книга, рекомендую (шепотом: на этом сайте ее можно скачать; disclaimer: а у меня бумажная, толстая). Можно читать вместо моего блога. Но меня чтение подобных книг неизменно уводит в сторону, я не знаю, почему. Вот еще хорошая книга Разработка Web-приложений в среде ASP.NET 2.0. Задача - проект - решение. Но код в этой книге ужасен. Поэтому рекомендую только для поиска конкретных решений, но ни в коем случае не как пример для подражания.

2. Чтобы вас с самого начала не тошнило от собственного сайта, рекомендую найти ему подходящий шаблон. Его всегда можно будет изменить, а так хоть будем видеть, что где показывать. Огромное количество бесплатных классных шаблонов здесь http://www.oswd.org/. Рекомендую сразу же поменять картинки и цвета, а то, шарясь по интернету, вы с удивлением будете обнаруживать своей собственный сайт, только с другой начинкой. =))

3. Создать БД, таблицы. Для организации локализации нам нужна таблица, в которой мы будем хранить название языка, его код (типа "ru-RU") и название файла иконки.

4. Ну и не забудьте про TDD! Я обычно использую NUnit, очень удобная штука. Для тестов стоит создать отдельный проект. Мне кажется, все знают, как подсоединить NUnit к проекту для тестирования, но если кто-то забыл, спрашивайте.

5. Также желательно подключить и настроить log4net для логгирования событий (если это вам, конечно, нужно). В той же книжке все это рассказывается тоже. С логгированием надо быть осторожным, легко можно переборщить. Сохранять в логе слеует только действительно необходимую информацию, а не все подряд. Иначе вы рискуете иметь миллионы никому не нужных записей.

Следующим номером: очень краткий курс по работе с ADO.NET Entity Framework на примере работы с языками.

Пишем CMS или любителям изобретать велосипеды

Не знаю, как вам, а мне периодически хочется сделать какой-нибудь интересный сайт или сервис. Иногда довожу свою идею до конца, чаще бросаю на середине. Но каждый раз в самом начале встает вопрос - делать с нуля или воспользоваться готовой CMS? Сначала, конечно, я начинаю шарить по интернету в поисках приличной CMS. Ну, я люблю C# и ASP.NET, а не PHP и VB.NET, поэтому список подозреваемых невелик. Но и он очень быстро сужается - почти сразу же выясняется что данная CMS или глючная или очень медленная или какая-то слишком крутая, а мне надо попроще. И, конечно, остается в итоге один вариант - опять писать с нуля. Конечно, мой сайт будет также содержать глюки и тормозить, но это будут мои глюки, которые я постепенно исправлю, и тормоза, наверное, со временем пройдут как-нибудь... сами... Но это ладно, самое-то глупое во всей этой ситуации - писать с нуля один и тот же код. Потому что почти все сайты содержат примерно одинаковую информацию и функционируют по сути совершенно одинаково. Поэтому можно попытаться создать ну не CMS, конечно, это громко сказано, а так... шаблон... фреймворк, ну что-то такое, что можно использовать и потом.
Ну что ж, сказано-сделано.
Во-первых, что за сайт. Сейчас мне нужно сделать один довольно простой сайт, который будет содержать информацию о программном продукте. Возможно, в дальнейшем в него будет добавлено что-то вроде соцсети и магазин. А пока - новости, локализация, фидбэк, страница со скриншотами ну и разное по мелочи. Самое главное - возможность быстро в админке добавлять новости, информацию о продукте, скриншоты, менять иконки флажков для языков, возможность быстро и безболезненно добавить новый язык. Ничего сложного и навороченного, как видите. Можно было бы вообще не писать все это, если бы не одно но. В процессе работы меня периодически осеняет. Ну не то чтобы конечно, в прямом смысле, но все время приходят разные идеи, как можно отрефакторить, как можно сделать удобнее. Меня бесит, например, когда код разметки смешан c JavaScript-кодом, когда переадресация на нужную страницу делается в коде, и стоит потом эту страницу переместить, как переадресация валится, и все в таком же духе. Поэтому я буду свои идеи по ходу дела выкладывать сюда. Если конечно, мне не надоест. А называться это безобразие будет "Пишем CMS. 100 шагов". Я, конечно, не думаю, что приличную CMS можно написать даже за 300 шагов, но, во-первых, 100 звучит красиво и солидно, во-вторых, у меня нет уверенности, что меня хватит даже на 50, в третьих, накрайняк всегда можно поменять первую цифру.
Поехали!