Реферат: Індивідуального завдання
Название: Індивідуального завдання Раздел: Остальные рефераты Тип: реферат | ||||||||||||||||||||||||||||
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ ХАРКІВСЬКИЙ НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ РАДІОЕЛЕКТРОНІКИ Голодницький І.Є/б 87548, м.Маріуполь, пр.. Будівельників 107-66 ЗВІТ З ПЕРЕДДИПЛОМНОЇ ПРАКТИКИ м. Київ «(ЧП Рябець-Голодницька)» у період з "3" 03 по "31" 03 2009 р. Тема індивідуального завдання: Програмна реалізація системи реєстрації звернень громадян та відповідей посадових осіб
Харків 2009 РЕФЕРАТЗвіт з переддипломної практики містить 23 сторінок,29 рисунков. Об’єктом формалізації є існуючі сервіси звернення громадян Мета роботы – зробити автоматизацію системи звернення громадян і відповідей посадових осіб . Метод розробки – розробка ведеться у сучасній середовищі розробки, яка дозволяє Intellisense, Refactoring, автоматичну генерацію UML структурних діаграмм. Результатом э працююча в Інтернет веб-система, яка дає можливість оцінить якість роботи посадових осіб. СОДЕРЖАНИЕ1.2 Слой доступа к базе данных. 7 1.2.1 Особенности внедрения. 7 1.2.3 Авто заполнение сервисных колонок. 9 ПОСТАНОВКА ЗАДАЧИИсходя из анализа конкурентных систем в социальной области и веб-технологий, требуется выполнить формулировку решаемых задач на основании, ниже перечисленных требований: а) Система должна быть готова к большим нагрузкам. б) Обеспечивать широкую формализацию объектов, таким образом, чтобы производить поиск и улучшать seo системы, засчёт собирательных страниц со ссылками, для города, специалистов, профайлов и прочих параметров. Использовать url, содержащие в названии транслитные названия компаний и имён профайлов. в) Сделать как можно более лёгкий интерфейс, с минимальным количеством действий выполняемых через Post. Редактировать, сохранять, удалять через ajax запросы. г) Валидацию производить через ajax запросы. Выводя результаты, в списке проблемных вариантов, подсвечивая не прошедшие валидацию. д) Параметры элементов при добавлении или поиске, выводить исходя из подхода, что если он списочный (выбираемый из группы вариантов), то в случае если вариантов меньше 30, показывать его select-списком, если же больше пользоваться autocomplete полем, с вспомогательным описанием возможных вариантов. Если же может существовать понятие короткого частого списка, показывать его в виде select, и в случае выбора пункта «Другие», показывать autocomplete поле. е) Поиск должен позволять использовать каждый из параметров элементов. Использовать подход как в параметрах, только при каждом выборе сокращать количество возможных вариантов поиска, чтобы можно было видеть количество новых вариантов, исходя из выбранных. И имея возможность отменить любой из выборов. ж) Производить широкую персонализацию исходя из локализованных данных по IP, или дополненных пользователем. Поощрять заполнение дополнительных параметров, но производя это редко, не нагружая пользователя этим занятием. Использовать возможности openid и подгружать специфическую информацию также оттуда. з) Позволять добавлять жалобу с главной страницы, даже при несуществующем объекте жалобы, добавляя его по потребности через Popup. Выполнить поэтапную реализацию задач с учётом вышеизложенных пунктов. ВВЕДЕНИЕДемократию часто понимают, лишь как возможность выбирать, и это правда, но у неё есть и другие проявления. Например, как возможность корректирования системы через обращения. Текущая система жалоб подразумевает личное общение жалобщика с нарушающим права должностным лицом через почтовую переписку. Почтовая переписка, как известно медленный, ненадёжный и главное не публичный механизм. Это приводит к неэффективности системы, из-за её характера. Поэтому, есть необходимость в создании системы, позволяющей пользователю товаров и услуг или любому гражданину Украины, перед вхождением в какие либо договорные отношения, иметь возможность проверить должностное лицо с точки зрения жалоб и отзывов. А должностное лицо, в свою очередь, имело бы возможность объяснить свои действия перед общественностью. Несмотря на то, что уже сейчас предпринимаются попытки государства внедрить разрозненные элементы автоматизации в сферу контроля за соблюдением гражданских прав и обязанностей, данные попытки не приводят к успешным результатам. В Киеве, в центре города установлены информационные системы, которые кроме рекламы исторических мест города, и прочей информации для туристов обладает возможностью отсылки жалоб меру города. Однако, ни ответа от должностного лица, ни публикации в информационных системах, не предусмотрено. Поэтому возникла потребность в создании системы автоматизации учёта обращений граждан и реакции должностных лиц. Система должна обеспечивать, документирование, юридическую поддержку, оценку выполняемых ответных действий, статистика жалоб на всевозможных должностных лиц и организаций. 1 МОДЕЛИ И АЛГОРИТМЫ1.1 База данных1.1.1 АрхитектураАрхитектура базы данных, решает несколько основополагающих задач. Во-первых, это простой перенос. Рассмотрим несколько сценариев. Предположим, существует команда разработчиков с локальными базами данных, сервер для тестов новой функциональности и реальный сервер. В данном случае, часто требуется многоразово переносить изменения и данные. И если изменения схемы можно прописывать как скрипты, или использовать миграционные вспомогательные утилиты, то данные переносить таким способом не так просто, особенно в случае использование числовых первичных ключей. Также это касается целостности данных, тобиш проблемы связанные с внешними ключами. Последовательные числовые ключи могут повторяться как у разработчиков и тестеров, так и на тестовом сервере. Что приводит к путанице и возможным сложно отлавливаемым проблемам связей. Конечно, можно использовать псевдослучайные числа, однако это приводит к ещё большим неожиданностям. Поэтому в случае использования числовых первичных ключей, приходиться производить перегенерирование ключей в каждой новой базе, что также приводит к сложностям выстраивания внешних ключей во внешние базы, как в случаях кластерных систем или просто вспомогательных баз. В уникальных идентификаторах есть и другие преимущество, например их можно генерировать не из базы. Суть в том, что при использовании числовых идентификаторов, сгенерировать их может часто только сама база, следовательно, она должна возвращать идентификатор отдельным запросом, а это не очень удобно, если есть желание использовать возможности блоковой вставки. Уникальные идентификаторы позволяют делать объединения нескольких таблиц, не указывая дополнительных параметров. Затем с объединением или отдельными таблицами можно производить join, что раскрывает широкие возможности при архитектировании систем. Может быть несколько таблиц, похожего типа и другая таблица, содержащая связи на любые из группы таблиц. Так можно создавать, например отдельную аудитную таблицу, ссылающуюся на любую другую. Данный подход является не плохим примером масштабирования или слабого связывания компонентов. Пример с реализацией аудитных полей универсален, однако часто не удовлетворяет условиям производительности. Поэтому от ситуации аудитные поля устанавливаются внутри таблиц. Обычно их 2 поля для создания и 2 поля для изменения, указывающие на пользователя и время действия. Также сервисными полями выступает IsDeleted. Этот подход позволяет виртуально удалять и восстанавливать объекты базы. Иногда существует поле IsModerated, указывающее на некое разрешение на показ объекта. UrlName также используется повсеместно в системе. Это поле некоторым образом должно быть связано с названием данного элемента, обычно трансформация производиться функцией специального транслита. Главное что символы не должны противоречить спецификации символов, описывающего форму url. [24]. В дальнейшем это поле используется как уникальный идентификатор, повышающий SEO системы [23]. 1.1.2 МодельКорень системы, создаваемый для первой версии, есть область жалоб, и описание структур на которых производят жалобы – жалобные элементы. Основными жалобными элементами выступают компании и люди. В будущем идёт расчёт на расширение жалобных элементов также до продуктов и групп компаний. Рисунок 2.1 – Таблица компании и персоны Как видно информационная часть состоит в основном из наименований. Остальные же параметры, которые являются фильтрами, соотносятся как многие-ко-многим. Рисунок 2.2 – Связанные фильтры к компании Как видно, каждая компания в системе позволяет указывать несколько типов компаний, например: клиника, сан. эпидем, ветеринарная, диспансер. Большая коммерческая организация может представлена быть в нескольких городах. И к каждой компании привязываются сотрудники. При этом в будующем расчитывается , добавить систему рейтингов, где будет по определённым формулам, высчитывается показатель человека, компании, города, как собственный, так и зависящий от связанных с ним рейтингов. Таким образом сотрудником, должно быть не всё равно на рейтинг всей организации, а организации на сотрудников. Рисунок 2.3 – Жалоба и теги При создании таблицы жалоб я выбрал не самую масштабированную, однако более удобную в некоторых случаях схему. С одной стороны жалоба по своей сути должна позволять присоединяться к любому Entity. Если первичный ключ элемента, на который жалуются, был бы числовым, как это обычно и бывает, это приводило бы к конфликтам. Для этого приходилось бы вводить дополнительное поле с указанием таблицы. Ещё один вариант, был бы создание единой таблицы для всех общих элементов (Personal, Company) и специальные поля как Address для Company или LastName для Personal , скрыты в наследуемых таблицах. Тогда можно было бы использовать числовое Id. В случае Guid его можно использовать без надобности в общей таблицы, так как все id уникальные. В данном случае, потребовалось ссылаться жалобой на несколько элементов. Это можно было бы решить дополнительной таблицей, не ограничивая себя количеством ссылок на жалобные объекты. Но в данном случае потребовалось также возможность использовать ForeignKey, который позволял в ORM иметь дополнительные связи и с тем создавать сложные запросы. Tag обычная реализация web 2.0 параллельных неиерархических ярлыков. Суть связок основано на идеи категоризации основанной на некоем списке названий почти не связанных друг с другом. Таким образом, любое множество тегов, может прикрепляться к множеству элементов. Здесь они используются для указания типов жалоб: на обслуживание и качество, серьозные, юридически выйгрышные дела или менее важные. 1.2 Слой доступа к базе данных1.2.1 Особенности внедренияПлатформенным уровнем доступа к базе есть встроенный в .net 3.5 – Linq to Sql. Linq to Sql – это one-to-one table mapper, тоесть работает он достаточно просто. Подключившись к серверу Sql, он получает метаданные структуры таблиц, на их основе создаёт xml файл с расширением dbml. Это промежуточный файл, содержащий дополнительную абстракцию, где можно производить например переименование таблиц. Затем существуют утилиты генераторы, создающие на основании dbml, cs классы с аттрибутами. Одним из классов, есть расширение класса DataContext, который относительно ADO.NET 2.0, являеться чем-то близким к симбиозу DataSet и DataAdapter. Он загружает данные, в форме сгенерированных классов абстракций таблиц, измененяя любые из них, мы производим трассировку изменений, что используеться при сохранении в автоматическом режиме. Также контекст отвечает за транзакции, логирование действий, конкурентные запросы. Относительно особенностей веб-приложений: контекст не имеет смысла хранить дольше одного реквеста, наоборот это может приводить к неожиданным ошибка. Тоже и с хранением состояния. По сути, дилема заключаеться в том, какое количестве записей можно было бы провести в виде одной операции с базой. Большее количество значительно эффективней, против меньшего количества одновременных операций. Зато соответственно меньше разрозненных записей, меньше проблем с устаревшими, не добавленными данными, которых будут ожидать другие пользователи и правильностью последовательности ввода зависимых записей. 1.2.2 Схема доступаОпытным путём на данный момент я пришёл к выводу что оптимальным путём управления базой есть следующие несколько принципов: 1. Использовать HttpContext.Current.Context для хранения текущего контекста. 2. В Ctx создаётся singletone Model, через который идёт доступ к базе всем приложением. Описывается на Рисунок 2.4 3. Вместо стандартной схемы Рисунок 2.5, используется Рисунок 2.6. 4. Бизнес логика прописывается как методы partial классов от объектов.
Рисунок 2.4 – Singletone доступа к базе
Рисунок 2.5 – Вариант использования контекста
Рисунок 2.6 – Вариант использования контекста, с Singletone (Рисунок. 2.4) 1.2.3 Авто заполнение сервисных колонокВ большинстве часто используемых entity в базе данных, есть определённые сервисные поля, которые независимы от других полей и содержат похожую информацию. DateCreated, DateModified, UserCreated, UserModified, UrlName – могут не вводиться при каждом добавлении в бизнесс обьектах, они могут быть сгенерированы. Перехват удобней всего производить в override версии SubmitChanges. Там можно перед произведением добавления или изменений, получать все обьекты и производить над ними операции.
Рисунок 2.7 – Переопределение SubmitChanges, для автозаполнения Как видно, для Inserts, вставляються Created и UrlName значений, при Update, только Modified поля. AutoValues – это специальный класс принимающий обьект как конструктор, и производит с ним заполнения полей. Политика заполнения представляют собой осторожный подход. Поле вставляеться только в случае его существования и пустого значения внутри.
Рисунок 2.8 – Проверка заполненности Reflection свойства Данные функции широко используют Reflection механизмы. Для ValueType таких как Guid, производяться специальные проверки на пустоту значения.
Рисунок 2.9 – Установка значения в Reflection свойство AutoDefaultPut – проверяет указанное свойство на существование и заполняет его. Метод используеться AutoDate и AutoUser методами.
Рисунок 2.10 – Пример автозаполнения Id пользователя и DateTime. Поле с датой заполняеться текущим временем в формате универсальном формате UTC. User заполняеться текущим UserId. В случае с Url происходят дополнительные проверки и конвертация через транслит метод.
Рисунок 2.11 – Заполнение Url, из расчёта на другое свойство Это специальный созданный для данной системы транслит, удобный для внедрения в Url. Транслит сделан в виде Extension метода [extension метод в C# и статья из моего блога]. 1.2.4 Json моделиТак как множество данных в результате передаёться на клиент в форме json, то вполне не лишним может оказаться дополнительный уровень абстракции в виде набора классов для сериализации. По стилю кодированию они заканчиваются на Json и находяться среди моделей. Их задача есть передавать на клиент только нужную информацию без лишних зацикленных элементов. В целом это обычные пустые классы, как пример снизу.
Рисунок 2.12 – Пример промежуточной структуры для модели данных Они могут также содержать в одном из конструкторов аргументом класс Company из ORM модели для клонирования данных.
Рисунок 2.13 – Конструктор заполнения структуры ShortJson Конструктор как метод заполнения выбран не случайно, он удобен при создании объектов в Linq методе Select.
Рисунок 2.14 – Пример заполнение ShortJson Кроме того, оказалось проблемой воспользоваться механизмом UrlRouting не внутри View, а внутри Action Controller. Для этого пришлось создавать специальную заглушку.
Рисунок 2.15 – Загрузка Ctx.Url Таким образом в каждом Action контроллеров, которые наследуются от BaseController, есть возможность использования Ctx.Url. А в конструкторе CompanyJson создавать целый url.
Рисунок 2.16 – Доступ к Ctx.Url 1.3 Безопасность доступа1.3.1 Анонимный доступЛюбой пользователь, производящий запрос к странице, не имеющий в запросе cookies аутентификации, является для системы анонимом. Суть анонимов достаточно проста, это неопределённый пользователь, однако он имеет права производить такие операции, как комментирование и создание анонимных жалоб. Однако в действительности, они не столь анонимны относительно внутренней структуры системы. Каждый аноним, заходя первый раз передаёт свой IP адрес, что не мало важно, и даёт информацию о местоположении. Эта информация может быть использована в целях персонализации вывода страниц. Например, показывая жалобы или новости из своего района, ближайшие компании, статистика, плотность пользователей и тому подобную информацию. Анонимы записываются как самые настоящие пользователи, в таблицу пользователей, однако с маркером в виде колонки IsAnonym. Такая запись является первой стадией, и её задача есть поддержание последовательности действий будущего зарегистрированного пользователя. Конечно, такой подход не лишён недостатков - меняя браузер, удаляя cookies, производя вход другим аккаунтом, отметка анонима будет очищена и создана заново. Следовательно, введённая информация так и останется ссылающейся на пользователя анонима. В случае успешной регистрации, UserId анонима уже использованная при создании комментариев, будет преобразована в нового пользователя, не меняя UserId. Реализация механизма работы, такого анонима, производится в ручную. В asp.net 2.0, был включёна реализация AnonymousModule, однако он работает с более простой схемой, когда маркер аноним остаётся постоянно[почему?]. Проблема начинается в момент выхода из аккаунта зарегистрированного пользователя, так как UserId анонима и пользователя совпадают, то при выходе нужно удалять и анонимную, и пользовательскую cookie, а встроенный механизм этого не позволяет. Поэтому для нашей схемы реализуется свой модуль анонимных пользователей.
Рисунок 2.17 – Регистрация анонима и текущий пользователь Как видно, текущего пользователь получают через статическое свойство User.Current. Это свойство не кеширует пользователя, загружая его, либо анонима через RegisterAnonym. Он производит два действия: как добавление анонима, так и загрузку по UserId в случае не существования и в результате в любом случае выдаёт некого пользователя.
Рисунок 2.18 – Класс Anonym Этот статический класс отвечает за работу с cookie: запрос идентификатора анонима, соответствующего идентификатору UserId, генерация и установка на клиент, если cookie не найден. Сгенерированный Id затем будет использован в RegisterAnonym, как видно на прошлом изображении. 1.3.2 РегистрацияРегистрация – это процесс перехода состояния пользователя в более постоянную величину. Основные задачи достижимые при использовании регистрации: улучшенный уровень персонализации и более упрощённый ввод идентификационный информации, во время пользования системой. Для создателей, регистрация, прежде всего трассировка движения, и более простой и точный способ просмотра статистики. Рисунок 2.19 – Процесс регистрации Сверху диаграмма статусов, для процесса регистрации. Как видно процесс, состоит из этапа валидации информации, отсылки email и активации по ссылке из email. Достаточно стандартный процесс в веб-приложениях. Внешне работа формы регистрации описывается в пункте [веб ресурс – сценарий – регистрация]. Здесь же далее будет описан UserController и клиентские компоненты, использованные на странице регистрации выполняющие функциональность. UserController – это управляющий элемент таких действий, как логин, логаут, регистрация, активизация и профайл пользователя. Как и задача любого mvc контроллера, он рассматривает присланные данные, наполняет в зависимости от них модель и пользуясь View отображает её. В случае с UserController, результатом некоторых действий есть json, тоесть он выступает как rest-сервис [ссылки на rest и json] вызываемый при помощи ajaj. В данном случае, регистрация и логин переносит валидацию в асинхронные вызовы, и на клиенте обрабатывает ответ. На сервере находиться входное действие Register и RegisterJson выполняющее функцию сервиса. Register выглядит как самый простой Action:
Рисунок 2.20 – Action регистрации UserFilter указывает как видно, что доступ к регистрации имеет любой пользователь. Ниже листинг разметки отображаемой страницы:
Рисунок 2.21 – Разметка для страницы регистрации Слева вводимые поля – имя, email и пароль. Справа валидационная часть. Реализация достаточно гибкая и чистая маркировка.
Рисунок 2.22 – CSS блоков Первые три отвечают за оформление двух блоков и относительное позиционирование друг к другу и элементов внутри. Status класс, выражает квадрат, метку выполненности каждой из валидаций. Указанные рядом failed или passed соответствует результату, который пришёл от RegisterJson.
Рисунок 2.23 – Код управления валидацией регистрационной информацией На кнопку «Регистрация» устанавливается обработчик, который собирает параметры на проверку и передаёт их в RegisterJson. Если например отправить все пустые значение, то ответом Json будет строка снизу.
Рисунок 2.24 – Пример присланного RegisterJson Формат Json в данном случае выглядит как вид валидации, и массив ошибок соответствующий ему. В Csharp для сериализации используется следующий класс.
Рисунок 2.25 – Версия ValidationJson RegisterJson должен заполнить этот класс по мере валидации.
Рисунок 2.26 – Проверка Email в RegisterJson Action Сначало, как видно, идёт проверка возможности отсылки Email. Emails класс использует для проверки регулярное выражание.
Рисунок 2.27 – Проверка Email на правильность составления Затем проверяется уникальность email, в списке пользователей ищутся с таким же email. Если email верен, проверяется пароль, здесь данная проверка опущена. Далее, если ошибок не найдено, происходит подготовка письма и отсылка. Для создания тела письма используется компонент StringTemplate, позволяющий совмещать списки переменных с шаблоном. Это стандартный подход, среди подобных вспомогательных шаблонных систем.
Рисунок 2.28 – Составление Email и отсылка Несколько особенностей. Во-первых, здесь использована транзакция из пространства имён транзакций. По умолчанию данная транзакция после окончания using производит откат, если не был произведён коммит. В данном случае схема очень удобна, так как не требуется передавать в функции обработки переменную транзакции. StringTemplateGroup – это класс абстракция, позволяет указать группу поиска для списка темплейтов. В нашем случае это ссылка на каталог во View. Далее идёт поиск нужного темплейта, и заполнение переменных. Пример, темплейта снизу.
Рисунок 2.29 – Пример StringTemplate шаблона для активации После проведения всех участков проверки, приходит ответ в виде сериализованного ValidationJson. Просмотр идёт двумя циклами, и затем в случае всех успешных, происходит перенаправление на Profile. В принципе попасть туда в любом случае пользователь не сможет, пока не проведёт активацию, куда его автоматически и перенаправят. ВЫВОДЫВ результате выполненных работ, была создана современная система регистрации и оценки обращений и отзывов. Система поиска и добавления превосходящая всех конкурентов в удобности и быстроте. За время разработки, было найдено множество подходов для создания и взаимодействия клиентских компонентов. СПИСОК ИСТОЧНИКОВ1. Иван Блинков Масштабируемые веб-архитектуры [Электронный ресурс] /. - Режим доступа : www/ URL: http://www.insight-it.ru/net/scalability/masshtabiruemye-veb-arkhitektury/ - 12.05.2008 г. - Загл. с экрана. 2. Иван Блинков Сегментирование базы данных [Электронный ресурс] /. - Режим доступа : www/ URL: http://www.insight-it.ru/net/scalability/segmentirovanie-bazy-dannykh/ - 12.05.2008 г. - Загл. с экрана. 3. ORGs for Scalable, Robust, Privacy-Friendly Client Cloud Computing [Электронный ресурс] /. - Режим доступа : www/ URL: http://doi.ieeecomputersociety.org/10.1109/MIC.2008.107 - 10.2008 г. - Загл. с экрана. 4. Система управления базами данных [Электронный ресурс] /wikipedia. - Режим доступа : www/ URL: http://ru.wikipedia.org/wiki/Система_управления_базами_данных. 5. Объектно-ориентированная_база_данных [Электронный ресурс] /wikipedia. - Режим доступа : www/ URL: http://ru.wikipedia.org/wiki/Объектно-ориентированная_база_данных. 6. Реляционная СУБД [Электронный ресурс] /wikipedia. - Режим доступа : www/ URL: http://ru.wikipedia.org/wiki/Реляционная_СУБД 7. Объектно-реляционная СУБД [Электронный ресурс] /wikipedia. - Режим доступа : www/ URL: http://ru.wikipedia.org/wiki/Объектно-реляционная_СУБД 8. Web 2.0 and Cloud Computing [Электронный ресурс] /. - Режим доступа : www/ URL: http://radar.oreilly.com/2008/10/web-20-and-cloud-computing.html - 26.10.2008 г. - Загл. с экрана. 9. Amazon EC2 [Электронный ресурс] /wikipedia. - Режим доступа : www/ URL: http://ru.wikipedia.org/wiki/Amazon_EC2 10. Amazon EC2 [Электронный ресурс] /wikipedia. - Режим доступа : www/ URL: http://ru.wikipedia.org/wiki/Windows_Azure 11. Amazon Web Services [Электронный ресурс] /. - Режим доступа : www/ URL: http://aws.amazon.com/ 12. Что такое Google App Engine? [Электронный ресурс] /. - Режим доступа : www/ URL: 13. Windows Azure: официальный анонс "облачной" операционной системы [Электронный ресурс] /wikipedia. - Режим доступа : www/ URL: http://www.hardwareportal.ru/news/Windows_Azure_ofitsialniy_anons_oblachnoy_operatsionnoy_sistemi_/ 14. Cloud computing [Электронный ресурс] /wikipedia. - Режим доступа : www/ URL: http://en.wikipedia.org/wiki/Cloud_computing 15. Develop. Deploy. Scale. [Электронный ресурс] /linode. - Режим доступа : www/ URL: 16. Microsoft Azure vs Amazon, Google, and VMware [Электронный ресурс] /linode. - Режим доступа : www/ URL: 17. Prado Framework [Электронный ресурс] /. - Режим доступа : www/ URL: 18. MonoRail [Электронный ресурс] /. - Режим доступа : www/ URL: 19. Ruby On Rails [Электронный ресурс] /. - Режим доступа : www/ URL: 20. Asp.Net Mvc [Электронный ресурс] /microsoft. - Режим доступа : www/ URL: 21. ASP.NET MVC vs. WebForms[Электронный ресурс] /. - Режим доступа : www/ URL: 22. JavaScript Object Inheritance[Электронный ресурс] /. - Режим доступа : www/ URL: 23. Search Engine Friendly URLs - URL Rewriting[Электронный ресурс] /. - Режим доступа : www/ URL: http://www.seoconsultants.com/articles/1000/urls.asp 24. RFC 1738 [Электронный ресурс] /. - Режим доступа : www/ URL: |