Функциональные возможности и расхождения
Поскольку MVC не имеет строгой реализации, то реализован он может быть по-разному. Нет общепринятого определения, где должна располагаться бизнес-логика. Она может находиться как в контроллере, так и в модели. В последнем случае, модель будет содержать все бизнес-объекты со всеми данными и функциями. Некоторые фреймворки жестко задают где должна располагаться бизнес-логика, другие не имеют таких правил. Также не указано, где должна находиться проверка введённых пользователем данных. Простая валидация может встречаться даже в представлении, но чаще они встречаются в контроллере или модели. Интернационализация и форматирование данных также не имеет четких указаний по расположению.
Раздел 2
Техническое задание
Разработка web-приложения для размещения объявления о продажах
Назначение и цели создания приложения:
- Изучение технологии ASP.NET
- Изучение языка C#
- Использования современных технологий разработки в виде паттерна MVC и View шаблонов
- Самообразование
Требование к сайту:
- Возможность просмотра активных и не активных объявлений
- Возможность добавления новых объявлений
- Возможность удаления не актуальных объявлений( переноса в секцию не активных)
- Архитектура приложения, дающая возможность масштабируемости и модификации
- Использование технологии ASP.NET
- Дизайн приложения, дающий визуальное представления об расположении блоков
Раздел 3
Этапы создания приложения
Выбор системы и инструментов разработки
Для технологии ASP.NET необходим сам .NET, который, в свою очередь, разрабатывает и поддерживает Microsoft, в связи с чем выбирать можно только между VisualStudio, кроссплатформенной VisualStudio code и кроссплатформенным решениям на основе Mono. Выбор пал на платформу Visual studio, так как ОС Windows является родной для платформы .NET- отпадают некоторые проблемы, связанные со сменой платформ и понижается порог вхождения в технологию.
Так как задание не является курсовой или дипломной работой- для построения «скелета» приложения мной были выбраны принципы MVC без использования каких либо фреймворков и баз данных. Данные приложения хранятся в отдельном классе модели приложения, что позволяет полно выполнить поставленные в ТЗ цели без использования лишних инструментов.
Описание структуры приложения
TestAspNet45- название приложения
Views- Пример использования отдельной папки для представлений.
Site1.Master- Пример использования возможности шаблонов представлений, или мастер-страниц, как говорится в литературе ASP.NET.
Default.aspx- является представлением страницы добавления новых объявлений
Default.aspx.cs- контроллер представления Default.aspx
Summary.aspx- является представлением страницы добавления новых объявлений
Summary.aspx.cs- контроллер представления Summary.aspx
Style.css- файл каскадных таблиц стилей всего приложения
TestClass.cs- модель приложения, описывающая переменные, использующиеся для хранения информации об объявлениях в приложении, и возможности взаимодействия с ними
Repository.cs- модель приложения, описывающая функции для работы с хранилищем, описанным в модели TestClass
Описание приложения
Модель
TestClass.cs модель, описывающая объекты, с которыми будет взаимодействовать приложение. Аналогично, таблице реляционной базы данных.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace TestAspNet45
{
public class TestClass
{
public string Id { get; set; } //Номер объявления
[Required] //Параметр валидации поля
public string Title { get; set; } //заголовок объявления
[Required]
public string Body { get; set; } //Текст объявления
[Required]
public string Phone { get; set; } //Номер телефона
public bool? WillAttend { get; set; } //параметр актуальности объявления
}
}
Repository.cs модель, описывающая функции взаимодействия с объектами модели, содержащими данные, которые хранит приложение.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace TestAspNet45
{
public class Repository //модель с механизмами взаимодействия с хранилищем
{
private static Repository repository = new Repository(); //Создание экземпляра класса модели взаимодействия
private List<TestClass> responses = new List<TestClass>(); //Список объектов модели хранилища
public static Repository GetRepository() { // "Геттер", функция для получения хранилища
return repository;
}
public IEnumerable<TestClass> GetAllResponses() { // "Геттер", функция для получения перебора объектов хранилища
return responses;
}
public void AddResponse(TestClass response) { //Добавление объекта в хранилище
responses.Add(response);
}
}
}
Контроллеры
Summary.aspx.cs контроллер главной страницы, формирующий динамический контент, расширяя страницу шаблон(мастер-страницу). В связке Viewer-Controller Summary применено 2 способа формирования динамического контента- в Представлении(не правильно), и в Контроллере(правильно).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace TestAspNet45
{
public partial class Summary : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{}
protected string GetNoShowHtml() //Пример вывода дигнамической разметки из контроллера
{
StringBuilder html = new StringBuilder(); //создание строки
var noData = Repository.GetRepository().GetAllResponses().Where(i => !i.WillAttend.Value); //Получение значений из хранилища по ключу
foreach (var rsvp in noData) { //Перебор значений
html.Append(String.Format("<div>" +
"<h3> Тема: {1} </h3> </ br>" +
"<p>{2}</p> </ br>" +
"<h3> Номер телефона: {3} </h3>   <a href=Default.aspx?id={0}>Убрать?</a>" +
"</div>", rsvp.Id, rsvp.Title, rsvp.Body, rsvp.Phone)); //Формирование динамической разметки
}
return html.ToString(); //возврат строки в представление
}
}
}
Default.aspx.cs Контроллер страницы добавления контента. Отвечает за создание новых объектов в хранилище, и смены флага активности объявления. Показывает способы обработки Get и Post запросов.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.ModelBinding;
namespace TestAspNet45
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e) //Функиця, отвечающая за дейсвтие при загрузке страницы
{
if (IsPostBack) // Если приходит Post-данные, например кнопка send формы
{
TestClass rsvp = new TestClass(); //создание экземпляра модели
if (TryUpdateModel(rsvp, new FormValueProvider(ModelBindingExecutionContext))) //попытка заполнить поля модели данными из формы
{
rsvp.Id = Repository.GetRepository().GetAllResponses().Count().ToString(); //Создание порядкового номера
rsvp.WillAttend = true; //Активация объявления
Repository.GetRepository().AddResponse(rsvp); //добавление объекта в хранилище
Response.Redirect("Summary.aspx"); //редирект на главную страницу
}
}
if (Request.QueryString["id"] != null) { //Если страница открывается с параметром id
string id = Request.QueryString["id"];
var noData = Repository.GetRepository().GetAllResponses().Where(i => i.WillAttend.Value); //то получаем из хранилища объекты с активными объявлениями
foreach(var r in noData) //перебираем
{
if (r.Id == id) //и ищем значения, равные параметру id
{
r.WillAttend = false; //и снимаем флаг активности
break;
}
}
Response.Redirect("Summary.aspx"); //переходим на главную страницу
}
}
}
}
Представления
Front-end составляющая приложения создалась в цветовых тонах и стилях, позволяющих легко визуально контролировать расположение статических блоков, и блоков динамического контента.
Style.css файл каскадных таблиц стилей, несущий в себе описание стилей для всего приложения.
#rsvpform label{ width: 120px; display: inline-block; } #rsvpform input { margin: 2px; margin-left: 4px; width: 150px; } #rsvpform select { margin: 2px 0; width: 154px; } button[type=submit] { margin-top: 15px; padding: 5px; } table, td, th { border: thin solid black; border-collapse: collapse; padding: 5px; background-color: lemonchiffon; text-align: left; margin: 10px 0; } #validationSummary { color: red; } #willattend { height: 40px; width: 349px; } body { background-color: darkgrey; } #container { background-color:brown; width: 80%; height: auto; margin: 0 auto; } #header { background-color: wheat; width: 100%; height: 100px; } .c { border: 1px solid #333; display: inline-block; padding: 10px 15px; text-decoration: underline; color: #000; | } .c:hover { box-shadow: 0 0 5px rgba(0,0,0,0.3); background: linear-gradient(to bottom, #fcfff4, #e9e9ce); color: #a00; //margin-top: 50px; } #head_h { font-family: Mistral; color: red; -webkit-text-stroke: 1px black; } .content_div div { width: 70%; background-color: blueviolet; margin: 0 auto; } |
Site1.master файл шаблон Представления(мастер-страница). Еще один хороший подход в практике веб-программирования. Использование шаблонов Представлений позволяет делать приложение более гибким, сокращает код и позволяет внося изменения в один файл- вносить изменения во внешний вид приложения в целом.
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site1.master.cs" Inherits="TestAspNet45.Views.Site1" %>
<!DOCTYPE html>
<!-- мастер старница(шаблон представления приложения) -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<link rel="stylesheet" href="~/Styles.css" /> <!-- подключение файла стилей -->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
</head>
<body>
<div id="container">
<div id="header">
<div id="top" class="head_inside">
<h1 align="center" id="head_h" >Площадка для размещения объявлений</h1>
</div>
<div id="menu" class="head_inside">
<a href="Summary.aspx" class="c">На главную</a>
<a href="Default.aspx" class="c">Добавить объявление</a>
</div>
</div>
<div class="content_div"> <!-- Контейнер содержимого -->
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server"> <!-- Подключения динамического контента в шаблон -->
</asp:ContentPlaceHolder>
</div>
</div>
</body>
</html>
Summary.aspx Представление главной страницы. Содержимое представления встраивается в верстку мастер-страницы, создавая законченный вид приложения. Имеет элементы формирования динамического контента.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Summary.aspx.cs" Inherits="TestAspNet45.Summary"
MasterPageFile="~/Views/Site1.master" Title="Title" %>
<%@ Import Namespace="TestAspNet45" %> <!-- Служебная информация, включая подключение мастер-страницы(шабблона представления) -->
<asp:Content ID="Conten1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server" > <!-- Все, что в этом блоке- будет встроено в представление шаблона-->
<h2>Актуальные объявления</h2>
<% var yesData = Repository.GetRepository().GetAllResponses().Where(r => r.WillAttend.Value);
foreach (var rsvp in yesData) {
string htmlString = String.Format("<div>" +
"<h3> Тема: {1} </h3> </ br>" +
"<p>{2}</p> </ br>" +
"<h3> Номер телефона: {3} </h3>   <a href=Default.aspx?id={0}>Убрать?</a>" +
"</div>", rsvp.Id, rsvp.Title, rsvp.Body, rsvp.Phone);
Response.Write(htmlString);
}
%> <!-- Пример динамической разметки в представлении -->
<h2>Не актуальные объявления</h2>
<%= GetNoShowHtml()%> <!-- вывод динамической разметки из контроллера -->
</asp:Content>
Верстка сайта без динамического контента.
Default.aspx Представление формы добавления новых объявлений. Не получилось подсунуть это представление в мастер-страницу из за изменение имен элементов формы.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TestAspNet45.WebForm1" %>
<!DOCTYPE html>
<!-- страница без использования шаблона, так как не смог справится с проблеммой переименования элементов формы -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<link rel="stylesheet" href="~/Styles.css" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
</head>
<body>
<div id="container"> <!-- стандартная разметка шаблона -->
<div id="header">
<div id="top" class="head_inside">
<h1 align="center" id="head_h" >Площадка для размещения объявлений</h1>
</div>
<div id="menu" class="head_inside">
<a href="Summary.aspx" class="c">На главную</a>
</div>
</div>
<div class="content_div">
<form id="rsvpform" runat="server" > <!-- Форма, передающая данные контроллеру -->
<asp:ValidationSummary ID="validationSummary" runat="server" ShowModelStateErrors="true" /> <!-- тег валидации -->
<div>
<h1>Форма добавления объявления:</h1>
<label> Тема: </label> <input type="text" id="title" name="title" runat="server"/>
</div>
<div>
<label> Содержание: </label> <input type="text" id="body" runat="server"/>
</div>
<div>
<label> Номер телефона: </label> <input type="text" id="phone" runat="server"/>
</div>
<div>
<button type="submit">Отправить объявление</button>
</div>
</form>
</div>
</body>
</html>
Верстка формы добавления новых объявлений.
Пример использования приложения
В связи с отсутствием базы данных- каждый перезапуск приложения влечет за собой удаление всех созданных данных. Первый запуск приложения
Объявлений пока нет, но их можно до бавить!
Переходим во вкладку «Добавить объявление»:
Нас встречает форма добавления объявлений.
После добавления на главной странице формируется динамический контент с данными, которые написал пользователь. И ссылка, предлагающая убрать объявление в не активные. Добавим еще несколько штук.
При попытке отправить форму с незаполненными одним или несколькими полями- сработает валидация.
Добавлено несколько объявлений. Можно попробовать одно удалить. Поле id, как Primary key, отвечает за уникальность, и с его помощью можно удалять объявления, не боясь ошибиться.
Контроллер меняет параметр, отвечающий за активность объявления, и оно переходит в стадию не активных.
Раздел 4
Вывод
В рамках контрольной работы было создано простое web-приложение. Я изучил основы технологии ASP.NET, языка C#, и устройство приложения с использованием этих технологий. Так же я применил современные концепции в веб-разработке(MVC, шаблон представления), которые используются повсеместно. Не со всеми проблемами получилось справиться. Я так и не смог разобраться как засовывать формы в шаблоны представлений, чтобы не изменялись имена элементов, либо обращаться в контроллере к измененным именам. При необходимости развития приложения- требуется написать пагинатор для динамического контента главной страницы, админ панель, сложную валидацию, аутентификацию, и подключить базу данных.
Список литературы
https://habrahabr.ru
https://www.asp.net
https://professorweb.ru