Главная      Учебники - Разные     Лекции (разные) - часть 17

 

Поиск            

 

Індивідуального завдання

 

             

Індивідуального завдання

УДК 681.3.08:681.324.06

МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ

ХАРКІВСЬКИЙ НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ РАДІОЕЛЕКТРОНІКИ

Голодницький І.Є/б

87548, м.Маріуполь, пр.. Будівельників 107-66

ЗВІТ

З ПЕРЕДДИПЛОМНОЇ ПРАКТИКИ

м. Київ «(ЧП Рябець-Голодницька)»

у період з "3" 03 по "31" 03 2009 р.

Тема індивідуального завдання:

Програмна реалізація системи реєстрації звернень

громадян та відповідей посадових осіб

Студ. ПЗАСз-03-4 Голодницький І.Є

____

_____

Керівник практики стар.преп Харченко. С.Л.

Робота захищена з оцінкою_ "___ "_____

Харків 2009

Звіт з переддипломної практики містить 23 сторінок,29 рисунков.

Об’єктом формалізації є існуючі сервіси звернення громадян

Мета роботы – зробити автоматизацію системи звернення громадян і відповідей посадових осіб .

Метод розробки – розробка ведеться у сучасній середовищі розробки, яка дозволяє Intellisense, Refactoring, автоматичну генерацію UML структурних діаграмм.

Результатом э працююча в Інтернет веб-система, яка дає можливість оцінить якість роботи посадових осіб.

СОДЕРЖАНИЕ

Постановка задачи. 2

Введение. 3

1 Модели и алгоритмы.. 4

1.1 База данных. 4

1.1.1 Архитектура. 4

1.1.2 Модель. 5

1.2 Слой доступа к базе данных. 7

1.2.1 Особенности внедрения. 7

1.2.2 Схема доступа. 8

1.2.3 Авто заполнение сервисных колонок. 9

1.2.4 Json модели. 12

1.3 Безопасность доступа. 14

1.3.1 Анонимный доступ. 14

1.3.2 Регистрация. 16

Выводы.. 23

Список источников. 24

ПОСТАНОВКА ЗАДАЧИ

Исходя из анализа конкурентных систем в социальной области и веб-технологий, требуется выполнить формулировку решаемых задач на основании, ниже перечисленных требований:

а) Система должна быть готова к большим нагрузкам.

б) Обеспечивать широкую формализацию объектов, таким образом, чтобы производить поиск и улучшать 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 классов от объектов.

public static MedData Model

{

get {

if (HttpContext.Current.Items["Data_Context_Complaint"] == null) {

HttpContext.Current.Items["Data_Context_Complaint"] = new MedData();

}

return (MedData)HttpContext.Current.Items["Data_Context_Complaint"];

}

}

Рисунок 2.4 – Singletone доступа к базе

using(var ctx = new DataContext()) {

User user = new User {

Name = name

}

ctx.Users.InsertOnSubmit(user);

ctx.Users.SubmitChanges();

}

Рисунок 2.5 – Вариант использования контекста

User user = new User {

Name = name

}

Ctx.Model.Users.InsertOnSubmit(user);

Ctx.Model.Users.SubmitChanges();

Рисунок 2.6 – Вариант использования контекста, с Singletone (Рисунок. 2.4)

1.2.3 Авто заполнение сервисных колонок

В большинстве часто используемых entity в базе данных, есть определённые сервисные поля, которые независимы от других полей и содержат похожую информацию. DateCreated, DateModified, UserCreated, UserModified, UrlName – могут не вводиться при каждом добавлении в бизнесс обьектах, они могут быть сгенерированы.

Перехват удобней всего производить в override версии SubmitChanges. Там можно перед произведением добавления или изменений, получать все обьекты и производить над ними операции.

namespace Yabeda.Med.Data

{

public partial class MedData

{

public override void SubmitChanges(System.Data.Linq.ConflictMode failureMode)

{

foreach(object ent in this.GetChangeSet().Inserts)

{

AutoValues auto = new AutoValues(ent);

auto.AutoUrlName();

auto.AutoDateCreated();

auto.AutoDateModified();

auto.AutoUserCreated();

auto.AutoUserModified();

}

foreach (object ent in this.GetChangeSet().Updates)

{

AutoValues auto = new AutoValues(ent);

auto.AutoDateModified();

auto.AutoUserModified();

}

base.SubmitChanges(failureMode);

}

}

}

Рисунок 2.7 – Переопределение SubmitChanges, для автозаполнения

Как видно, для Inserts, вставляються Created и UrlName значений, при Update, только Modified поля. AutoValues – это специальный класс принимающий обьект как конструктор, и производит с ним заполнения полей. Политика заполнения представляют собой осторожный подход. Поле вставляеться только в случае его существования и пустого значения внутри.

public object Entity { get; set; }

public Type EntityType { get; set; }

public AutoValues(object ent)

{

Entity = ent;

EntityType = ent.GetType();

}

private bool CheckIfValueExists(string property)

{

var name = EntityType.GetProperty(property);

if (name == null) return true;

object value = name.GetValue(Entity, null);

if (value is Guid) {

return ((Guid)value) != Guid.Empty;

}

return value != null;

}

Рисунок 2.8 – Проверка заполненности Reflection свойства

Данные функции широко используют Reflection механизмы. Для ValueType таких как Guid, производяться специальные проверки на пустоту значения.

private void AutoDefaultPut(string propertyName, object value)

{

var user = EntityType.GetProperty(propertyName);

if (user == null) return;

user.SetValue(Entity, value, null);

}

Рисунок 2.9 – Установка значения в Reflection свойство

AutoDefaultPut – проверяет указанное свойство на существование и заполняет его. Метод используеться AutoDate и AutoUser методами.

public void AutoDateModified()

{

AutoDefaultPut("DateModified", DateTime.UtcNow);

}

public void AutoUserCreated()

{

if (CheckIfValueExists("UserCreated")) return;

AutoDefaultPut("UserCreated", Data.Ctx.User.UserId);

}

Рисунок 2.10 – Пример автозаполнения Id пользователя и DateTime.

Поле с датой заполняеться текущим временем в формате универсальном формате UTC. User заполняеться текущим UserId. В случае с Url происходят дополнительные проверки и конвертация через транслит метод.

public void AutoUrlName()

{

var name = EntityType.GetProperty("DisplayName");

var url = EntityType.GetProperty("UrlName");

if (url == null || name == null) return;

string nameValue = name.GetValue(Entity, null) as string;

string urlValue = url.GetValue(Entity, null) as string;

if (nameValue != null && urlValue == null)

{

url.SetValue(Entity, nameValue.Translit(), null);

}

}

Рисунок 2.11 – Заполнение Url, из расчёта на другое свойство

Это специальный созданный для данной системы транслит, удобный для внедрения в Url. Транслит сделан в виде Extension метода [extension метод в C# и статья из моего блога].

1.2.4 Json модели

Так как множество данных в результате передаёться на клиент в форме json, то вполне не лишним может оказаться дополнительный уровень абстракции в виде набора классов для сериализации. По стилю кодированию они заканчиваются на Json и находяться среди моделей. Их задача есть передавать на клиент только нужную информацию без лишних зацикленных элементов.

В целом это обычные пустые классы, как пример снизу.

namespace Yabeda.Med.Mvc.Models.Company

{

public class ShortJson

{

public string name { get; set; }

public string url { get; set; }

public Guid id { get; set; }

}

}

Рисунок 2.12 – Пример промежуточной структуры для модели данных

Они могут также содержать в одном из конструкторов аргументом класс Company из ORM модели для клонирования данных.

public ShortJson(Data.Company comp)

{

id = comp.CompanyId;

name = comp.LongName;

}

Рисунок 2.13 – Конструктор заполнения структуры ShortJson

Конструктор как метод заполнения выбран не случайно, он удобен при создании объектов в Linq методе Select.

Company.All().Select(s => new Models.Company.ShortJson(s));

Рисунок 2.14 – Пример заполнение ShortJson

Кроме того, оказалось проблемой воспользоваться механизмом UrlRouting не внутри View, а внутри Action Controller. Для этого пришлось создавать специальную заглушку.

namespace Yabeda.Med.Mvc.Controllers

{

public class BaseController<C> : Controller where C : Controller

{

….

private UrlHelper _url;

public UrlHelper Url

{

get

{

if (_url == null)

{

_url = new UrlHelper(this.ControllerContext.RequestContext);

}

return _url;

}

}

protected override void OnActionExecuting(ActionExecutingContext filterContext)

{

Ctx.Url = Url;

}

}

}

Рисунок 2.15 – Загрузка Ctx.Url

Таким образом в каждом Action контроллеров, которые наследуются от BaseController, есть возможность использования Ctx.Url. А в конструкторе CompanyJson создавать целый url.

url = Ctx.Url.Action("Show", "Company", new { name = comp.UrlName});

Рисунок 2.16 – Доступ к Ctx.Url

1.3 Безопасность доступа

1.3.1 Анонимный доступ

Любой пользователь, производящий запрос к странице, не имеющий в запросе cookies аутентификации, является для системы анонимом.

Суть анонимов достаточно проста, это неопределённый пользователь, однако он имеет права производить такие операции, как комментирование и создание анонимных жалоб. Однако в действительности, они не столь анонимны относительно внутренней структуры системы.

Каждый аноним, заходя первый раз передаёт свой IP адрес, что не мало важно, и даёт информацию о местоположении. Эта информация может быть использована в целях персонализации вывода страниц. Например, показывая жалобы или новости из своего района, ближайшие компании, статистика, плотность пользователей и тому подобную информацию.

Анонимы записываются как самые настоящие пользователи, в таблицу пользователей, однако с маркером в виде колонки IsAnonym. Такая запись является первой стадией, и её задача есть поддержание последовательности действий будущего зарегистрированного пользователя. Конечно, такой подход не лишён недостатков - меняя браузер, удаляя cookies, производя вход другим аккаунтом, отметка анонима будет очищена и создана заново. Следовательно, введённая информация так и останется ссылающейся на пользователя анонима. В случае успешной регистрации, UserId анонима уже использованная при создании комментариев, будет преобразована в нового пользователя, не меняя UserId.

Реализация механизма работы, такого анонима, производится в ручную. В asp.net 2.0, был включёна реализация AnonymousModule, однако он работает с более простой схемой, когда маркер аноним остаётся постоянно[почему?]. Проблема начинается в момент выхода из аккаунта зарегистрированного пользователя, так как UserId анонима и пользователя совпадают, то при выходе нужно удалять и анонимную, и пользовательскую cookie, а встроенный механизм этого не позволяет. Поэтому для нашей схемы реализуется свой модуль анонимных пользователей.

partial class User

{

public static User Current {

get {

return HttpContext.Current.User.Identity.IsAuthenticated ?

User.Get(HttpContext.Current.User.Identity.Name) :

RegisterAnonym();

}

}

public static User RegisterAnonym() {

return RegisterAnonym(Anonymous.Get());

}

public static User RegisterAnonym(Guid anonymId) {

User user = Rep<User>.GetById(anonymId);

if (user == null) {

user = new User {

UserId = anonymId,

IsActivated = false,

IsDeleted = false,

IsGuest = true

};

Ctx.Model.Users.InsertOnSubmit(user);

}

Ctx.Model.SubmitChanges();

Ctx.User = user;

return user;

}

Рисунок 2.17 – Регистрация анонима и текущий пользователь

Как видно, текущего пользователь получают через статическое свойство User.Current. Это свойство не кеширует пользователя, загружая его, либо анонима через RegisterAnonym. Он производит два действия: как добавление анонима, так и загрузку по UserId в случае не существования и в результате в любом случае выдаёт некого пользователя.

public class Anonymous

{

public static Guid Get()

{

HttpCookie cookie =

HttpContext.Current.Request.Cookies[CookieName];

try {

return cookie == null ? New() : new Guid(cookie.Value);

}

catch(Exception exc) {

return New();

}

}

public static Guid New()

{

Guid anonymId = Guid.NewGuid();

HttpCookie cookie =

HttpContext.Current.Response.Cookies[CookieName];

cookie.Expires = DateTime.Now.AddDays(30);

cookie.Value = anonymId.ToString();

return anonymId;

}

public static readonly string CookieName = "Yabeda.AnonId";

}

Рисунок 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:

[UserFilter(IsGuest = true)]

public ActionResult Register()

{

ViewData.Model = new PageModel { Title = "Регистрация" };

return View();

}

Рисунок 2.20 – Action регистрации

UserFilter указывает как видно, что доступ к регистрации имеет любой пользователь. Ниже листинг разметки отображаемой страницы:

<div class="register container">

<div class="inputs">

Имя: <input type="text" id="name" /> <br />

Email: <input type="text" id="email" /> <br />

Пароль: <input type="password" id="pass" /> <br />

<input type="button" class="submit" value="Регистрация" />

</div>

<div class="validation">

<div class="email">

<span class="status failed">&nbsp;</span>

1. Проверяем уникальность email

<div class="result"></div>

</div>

<div class="pass">

<span class="status failed">&nbsp;</span>

2. Проверяем качество пароля

<div class="result"></div>

</div>

<div class="send">

<span class="status failed">&nbsp;</span>

3. Отсылаем письмо на ваш email

<div class="result"></div>

</div>

</div>

</div>

Рисунок 2.21 – Разметка для страницы регистрации

Слева вводимые поля – имя, email и пароль. Справа валидационная часть. Реализация достаточно гибкая и чистая маркировка.

.register .inputs, .register .validation {

float: left; margin: 20px; padding: 10px; border: dotted 1px red;

}

.register .validation > div { margin: 20px; }

.register .validation .result { font-size: small; margin-left: 40px; }

.register .status { padding: 10px; margin: 5px; }

.register .status.failed { background-color: red }

.register .status.passed { background-color: green }

Рисунок 2.22 – CSS блоков

Первые три отвечают за оформление двух блоков и относительное позиционирование друг к другу и элементов внутри. Status класс, выражает квадрат, метку выполненности каждой из валидаций. Указанные рядом failed или passed соответствует результату, который пришёл от RegisterJson.

$(function() {

$('.register .submit').click(function() {

var params = {

name: $('.register .inputs #name').val(),

email: $('.register .inputs #email').val(),

pass: $('.register .inputs #pass').val()

};

$.getJSON(Yabeda.Services.User.RegisterJson, params, function(json) {

$('.register .validation .result').empty();

$.each(json, function(i, n) {

$('.register .validation .' + i + ' .status')

.removeClass(n.length == 0 ? 'failed' : 'passed')

.addClass(n.length == 0 ? 'passed' : 'failed');

$.each(n, function(ir, r) {

$('.register .validation .' + i + ' .result')

.append('-').append(r).append('<br />');

})

})

if ($('.register .validation .failed').size() == 0) {

setTimeout(function() {

window.location = Yabeda.Services.User.Profile;

}, 700);

}

});

});

});

Рисунок 2.23 – Код управления валидацией регистрационной информацией

На кнопку «Регистрация» устанавливается обработчик, который собирает параметры на проверку и передаёт их в RegisterJson. Если например отправить все пустые значение, то ответом Json будет строка снизу.

{"email":["Email введён неверно"],

"pass":[],

"send":["Без email, не могу послать письмо активации"]}

Рисунок 2.24 – Пример присланного RegisterJson

Формат Json в данном случае выглядит как вид валидации, и массив ошибок соответствующий ему. В Csharp для сериализации используется следующий класс.

public class ValidationJson

{

public List<string> email = new List<string>();

public List<string> pass = new List<string>();

public List<string> send = new List<string>();

}

Рисунок 2.25 – Версия ValidationJson

RegisterJson должен заполнить этот класс по мере валидации.

public ActionResult RegisterJson(string name, string email, string pass)

{

var validation = new Models.User.ValidationJson();

// 1. Check similar

if (!Emails.Check(email)){

validation.email.Add("Email введён неверно");

}

else {

if (Data.User.Get(email) != null) {

validation.email.Add("Такой пользователь существует");

}

}

// 2. Send email

if (validation.email.Count == 0)

{

// код отсылки email

}

return Json(validation);

}

Рисунок 2.26 – Проверка Email в RegisterJson Action

Сначало, как видно, идёт проверка возможности отсылки Email. Emails класс использует для проверки регулярное выражание.

public static bool Check(string email)

{

if (email == null) return false;

string reg_email = @"^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*

@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$";

return new Regex(reg_email).IsMatch(email);

}

Рисунок 2.27 – Проверка Email на правильность составления

Затем проверяется уникальность email, в списке пользователей ищутся с таким же email. Если email верен, проверяется пароль, здесь данная проверка опущена. Далее, если ошибок не найдено, происходит подготовка письма и отсылка. Для создания тела письма используется компонент StringTemplate, позволяющий совмещать списки переменных с шаблоном. Это стандартный подход, среди подобных вспомогательных шаблонных систем.

Try

{

using (var tran = new TransactionScope())

{

Data.User.RegisterUser(name, email, pass);

StringTemplateGroup group =

new StringTemplateGroup("register",

Server.MapPath("~/Views/User"));

StringTemplate st = group.GetInstanceOf("RegisterAnonym");

st.SetAttribute("user", Ctx.User);

Email("Письмо активации", st.ToString());

tran.Complete();

}

FormsAuthentication.SetAuthCookie(email, true);

}

catch (DataException dexc)

{

validation.send.Add("Проблема с базой данных");

}

catch (Exception exc)

{

validation.send.Add("Ошибка отсылки активации");

}

Рисунок 2.28 – Составление Email и отсылка

Несколько особенностей. Во-первых, здесь использована транзакция из пространства имён транзакций. По умолчанию данная транзакция после окончания using производит откат, если не был произведён коммит. В данном случае схема очень удобна, так как не требуется передавать в функции обработки переменную транзакции.

StringTemplateGroup – это класс абстракция, позволяет указать группу поиска для списка темплейтов. В нашем случае это ссылка на каталог во View. Далее идёт поиск нужного темплейта, и заполнение переменных. Пример, темплейта снизу.

<div>

Активационный код: $user.UserId$

Введите его в поле на странице регистрации

</div>

Рисунок 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:
http://www.googleappengine.ru/docs/whatisgoogleappengine.html

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:
http://www.linode.com/

16. Microsoft Azure vs Amazon, Google, and VMware [Электронный ресурс] /linode. - Режим доступа : www/ URL:
http://cloudenterprise.info/2008/10/29/microsoft-azure-vs-amazon-google-and-vmware/

17. Prado Framework [Электронный ресурс] /. - Режим доступа : www/ URL:
http://www.xisc.com/

18. MonoRail [Электронный ресурс] /. - Режим доступа : www/ URL:
http://www.castleproject.org/MonoRail/

19. Ruby On Rails [Электронный ресурс] /. - Режим доступа : www/ URL:
http://rubyonrails.org/

20. Asp.Net Mvc [Электронный ресурс] /microsoft. - Режим доступа : www/ URL:
http://www.asp.net/mvc/

21. ASP.NET MVC vs. WebForms[Электронный ресурс] /. - Режим доступа : www/ URL:
http://habrahabr.ru/blogs/net/47249/

22. JavaScript Object Inheritance[Электронный ресурс] /. - Режим доступа : www/ URL:
http://javascript.ru/tutorial/object/inheritance

23. Search Engine Friendly URLs - URL Rewriting[Электронный ресурс] /. - Режим доступа : www/ URL: http://www.seoconsultants.com/articles/1000/urls.asp