Корпоративный сайт за полтора месяца
Я являюсь разработчиком корпоративного сайта компании «ИнноВинн», который расположен по адресу http://innovinn.com/. Сегодня хочу рассказать, как можно создать такой сайт за небольшой срок, а точнее за полтора месяца.
Когда мне ставили задачу, основным требованием было разработать максимум функционала за минимальный срок. Также среди требований было: панель администратора, возможность добавлять и редактировать страницы, поддержка иерархии страниц и различных элементов управления типа tabs, collapsible panel. Фактически задача сводилась к разработке простой CMS.
Технологии, что использовались при создании сайта: ASP.NET 3.5 SP1, ASP.NET Dynamic Data, ASP.NET AJAX, Ajax Control Toolkit, ASP.NET RSS Toolkit, SQL Server 2005.
База данных
Первой задачей стала разработка базы данных, которая позволила бы кроме непосредственно данных хранить всю структурную информацию.
Основные таблицы:
- Таблица Pages содержит всю необходимую информацию о веб-страницах (название, заголовок, контент, а также id родительской страницы для построения иерархии);
- Таблица Blocks содержит информацию о дополнительных блоках, которые могут располагаться в любой части сайта – справа, слева, снизу или сверху. Это могут быть как обычные информационные блоки, так и блоки с различным динамическим контентом (например, списком case studies).
- Таблица People – информация о сотрудниках, management team
- Таблицы CaseStudies, Companies, Solutions содержат соответствующую информацию о компаниях-партнерах, case studies и решениях. Есть поддержка категорий для каждой сущности, что дает возможность, например, группировать партнеров по неким признакам (http://www.innovinn.com/CustomersOverview.aspx).
- Таблицы News, Jobs и Downloads однозначно указывают на свое предназначение.
- Таблица Settings хранит такие настройки сайта, как copyright, название сайта, ширина, цвета и др.
После того, как база данных была готова, следующим шагом стала разработка панели администратора.
Панель администратора
Для разработки панели администратора была выбрана технология ASP.NET Dynamic Data.
Был создан ASP.NET Dynamic Data Project, добавлен Linq to SQL класс и сгенерирован контекст для нашей базы данных.
В Glogal.asax была добавлена строка с нашим контекстом:
model.RegisterContext(typeof(InnovinnDataContext), new ContextConfiguration() { ScaffoldAllTables = true });
и регистрацией роутинга:
routes.Add(new DynamicDataRoute("ControlPanel/{table}/{action}.aspx") { Constraints = new RouteValueDictionary(new { action = "List|Details|Edit|Insert" }), Model = model });
После этого была получена базовая панель администратора:
На это было потрачено около 10 минут. Следующим этапом является кастомизация стандартного шаблона под себя.
Кастомизация панели администратора
В первую очередь необходимо было предусмотреть возможность в контенте встраивать различные динамические элементы управления, такие как tabs, collapsible panel и др. таким образом обыкновенный HTML Editor не подходил (хотя его использование также возможно – для этого необходимо в файле FieldTemplates/MultilineText_Edit.ascx заменить стандартный TextBox на свой HTML редактор). Нужно было смотреть в сторону wiki разметки.
Покодеплексив, был найден .NET Parser for Wiki Creole, хотя конкретная реализация в данный момент не важна. В течении нескольких дней функционал парсера был расширен, чтобы он поддерживал необходимые нам элементы, а именно:
- все стандартные возможности форматирования (bold, italic, p и т.д.)
- вставка элементов управления из Ajax Control Toolkit – ModalPopup, Collapsible Panel, Accordion, Tabs)
- вставка видео, аудио и даже Silverlight приложений.
Табы вставляются приблизительно таким вот образом:
[tabcontainer]
[tab title="Type title 1 here"]
Sample text 1
[tab title="Type title 2 here"]
Sample text 2
[/tabcontainer]
В результате чего получаем страницу с контролом:
Collapsible panel:
[collapsible]
[pane title="Type title 1 here"]
Sample text 1
[pane title="Type title 2 here"]
Sample text 2
[/collapsible]
На выходе получаем:
Легко, просто и удобно.
Темы и ресурсы
В панели администратора была добавлен небольшой модуль для управления ресурсами (изображениями, видео и т.д.), которые можно загрузить на сервер и использовать на страницах и в блоках по своему усмотрению.
Также была добавлена поддержка тем, когда администратор может выбрать «шкуру» для представления сайта.
Делаем front-end
Фактически все время было потрачено на дизайнерские штуки, верстку и всякие JavaScript рюшечки с hover эффектами и т.д.
Динамическое меню создано на основе CustomSitemapProvider, который стоит иерархию меню на основе данных из базы данных. Здесь возникла одна проблема, когда при добавлении очередной страницы меню почему-то не обновлялось. Причиной было то, что провайдер кэширует созданную иерархию (в противном случае наблюдались бы тормоза). Поэтому пришлось добавить небольшой функционал по принудительному обновлению меню, если есть такая необходимость.
Сделать это можно таким образом:
public class CustomSitemapProvider : StaticSiteMapProvider { SiteMapNode _rootNode; public CustomSitemapProvider() { } public void Update() { lock (this) { _rootNode = null; } } private SiteMapNode AddSiteMapNode(CustomSitemapProvider provider, SiteMapNode smn, EntitySet pages) { foreach (var child in pages) { SiteMapNode item = new SiteMapNode(provider, child.PageId.ToString(), "~/" + child.PageUrl, child.PageTitle); AddNode(item, smn); } return smn; } public override SiteMapNode BuildSiteMap() { // Since the SiteMap class is static, make sure that it is // not modified while the site map is built. lock (this) { // If there is no root node, then there is no site map. if (null == _rootNode || DataReceiver.GetSettingsByName("NeedToUpdate") == "1") { // Start with a clean slate Clear(); _rootNode = new SiteMapNode(this, "Home", "~/Default.aspx", "Home"); // Add sub nodes logic goes here } } return _rootNode; } protected override void Clear() { lock (this) { _rootNode = null; base.Clear(); } } protected override SiteMapNode GetRootNodeCore() { return BuildSiteMap(); } }
Метод Update необходим для того, чтобы принудительно обновить меню.
Список страниц, которые необходимо было реализовать:
- Default.aspx
- ContactUs.aspx
- Search.aspx
- Jobs.aspx
- News.aspx
Как видите, список очень небольшой.
Также все страницы, блоки, элементы списков (например, компании или вакансии) можно отсортировать в нужном порядке.
Создание RSS ленты новостей
Ну здесь все очень банально, идем на страницу проекта ASP.NET RSS Toolkit (http://aspnetrsstoolkit.codeplex.com/) и через 10 минут RSS лента у вас готова.
Пример ashx обработчика для создания RSS ленты:
<%@ WebHandler Language="C#" Class="RssHyperLinkFromCustomClass" %>
using System;
using System.Collections.Generic;
using System.Web;
using RssToolkit.Rss;
public class RssHyperLinkFromCustomClass: Sample5HttpHandlerBase
{
protected override void PopulateRss(string rssName, string userName)
{
Rss.Channel = new Sample5Channel();
Rss.Channel.Items = new List
if (!string.IsNullOrEmpty(rssName))
{
Rss.Channel.Title += " '" + rssName + "'";
}
if (!string.IsNullOrEmpty(userName))
{
Rss.Channel.Title += " (generated for " + userName + ")";
}
Rss.Channel.Link = "~/scenario6.aspx";
Rss.Channel.Description = "Channel For Scenario6 in ASP.NET RSS Toolkit samples.";
Rss.Channel.Ttl = "10";
Rss.Channel.User = userName;
Sample5Item item = new Sample5Item();
item.Title = "CodeGeneratedClass";
item.Description = "Consuming RSS feed programmatically using strongly typed classes";
item.Link = "~/CodeGeneratedClass.aspx";
Rss.Channel.Items.Add(item);
item = new Sample5Item();
item.Title = "ObjectDataSource";
item.Description = "Consuming RSS feed using ObjectDataSource";
item.Link = "~/ObjectDataSource.aspx";
Rss.Channel.Items.Add(item);
}
}
Подробней можно почитать здесь.
Локализация приложений
Панель администратора поддерживает локализацию по умолчанию. Для локализации приложения используются файлы ресурсов, а текущая локаль сайта устанавливается в web.config:
Это нужно для поддержки разных языков портала и, как видите, очень удобно.
В aspx страницах локализированный текст выводится таким образом:
Логирование
В принципе, до конца вопрос с логированием не решен, пока как временное решение все проблемы пишутся в отдельную таблицу. Но для логирования можно использовать log4Net или Unity, интеграция и настройка которых займет не больше часа.
Роутинг
Ну поисковые машины наше все –SEO, красивые адреса и бла-бла-бла.
Простой роутинг занял около 20 строчек. Идем в Global.asax и редактируем событие Application_BeginRequest:
protected void Application_BeginRequest(object sender, EventArgs e){
Context.RewritePath(strCustomPath);
}
где strCustomPath формируем таким образом:
strCustomPath = "Page.aspx?id=" + pageId;
Страница контактов
Здесь был еще использован компонент reCaptcha для фильтрации спам-сообщений.
Подводим итоги
Итого имеем: 1 ASP.NET разработчик – полтора месяца работы (хотя, думаю, если бы с самого начала было все понятно, уложился бы за месяц), дизайнер – неделя работы, контенщики – 1 неделя работы. Итого: два человека-месяца максимум.
Конечно же, можно придумать много дополнительных фич, поработать над usability, провести оптимизацию, поработать над полной поддержкой SEO, сделать приватную зону для клиентов, прикрутить блог и придумать много чего другого, но факт остается фактом – за полтора месяца можно создать полноценный движок, на котором будет крутиться ваш корпоративный сайт.
После простой установки и легкой настройке вы можете отдать его в руки людей, далеких от программирования, которые смогут без вашего участия развивать сайт, добавлять материал и зарабатывать на нем деньги.
Здесь наверное, нужно упомянуть, что хостинг с поддержкой ASP.NET 3.5 SP1 стоит около $80-$100 в год, а подобный функционал вполне можно разработать с использованием бесплатных версий SQL Server и Visual Studio. Таким образом, все затраты будут связаны лишь с зарплатой и хостингом. Это я к тому, что на .NET технологиях можно (и нужно) разрабатывать приложения и это не так дорого, как может показаться на первый взгляд.
P.S. Нужно добавить, что студия «сами знаете кого ТМ» оценила аналогичную работу от 30k до 50k сами знаете чего.