Фреймворк разработан на базе ASP.NET. Он прост в изучении и позволяет создавать бизнес-приложения и SPA без JavaScript кода. Все за счет большого количества готовых элементов управления.
Следующие статьи будут посвящены тому, с чего все началось, каково было писать собственный фреймворк и его поддержку в Visual Studio, а также какие фичи есть в последнем релизе, который вышел в начале этого года.
Для первого проекта я буду использовать Visual Studio 2017 расширением для DotVVM. После установки расширения при создании должны появится новые типы проектов. Выберем новый DotVVM .NET Core проект.
![](https://habrastorage.org/webt/au/og/it/auogitjdar9xccaxqsn4huyxkgo.png)
После создания нового DotVVM проекта, появится следующая файловая структура.
![](https://habrastorage.org/webt/9s/21/4j/9s214jmabotwjkjdoaiitlenfm8.png)
Основные файлы
- Program.cs является основной точкой входа приложения, которое присутствует во всех .NET-приложениях .NET Core. Если вы заглянете внутрь этого файла, вы увидите, что он настраивает Kestrel, интеграцию IIS, устанавливает содержимое корневого каталога и запускает веб-хост.
- DotvvmStartup.cs — это класс, который содержит конфигурацию для DotVVM. Вы можете найти метод ConfigureRoutes со строкой которая регистрирует маршрут по умолчанию:
config.RouteTable.Add ("Default", "", "Views/default.dothtml");
Если пользователь посетит домашнюю страницу, DotVVM отобразит страницу Views /default.dothtml.
- Startup.cs содержит два метода, вызываемых при запуске приложения. Метод ConfigureServices используется для регистрации служб в объекте IServiceCollection. Понадобится вызвать services.AddDotVVM для регистрации услуг, требуемых DotVVM. Метод Configure настраивает все промежуточный слой ASP.NET. Также нужно вызвать
app.UseDotVVM <DotvvmStartup>
для регистрации промежуточного слоя DotVVM, которое будет обрабатывать HTTP-запросы.
Кроме того, проект содержит папки Views и ViewModels. Первая папка содержит файл с именем default.dothtml, вторая папка ViewModel класс DefaultViewModel.cs. Эти два файла вместе создают веб-страницу DotVVM.
DotVVM использует паттерн Model-View-ViewModel (MVVM).
View (Представление) — это файл с расширением .dothtml. В принципе, это HTML-файл с несколькими синтаксическими атрибутами: директивы, элементами управления и привязки данных.
ViewModel — это класс C# с двумя целями:
Он содержит состояние страницы. Другими словами, все, что может быть изменено пользователем на странице. Если у вас есть TextBox на странице, вам нужно где-то сохранить его значение. В DotVVM вам просто нужно объявить свойство типа string в классе ViewModel и привязать ее к TextBox при помощи свойства Text.
Для обработки команды нужно просто объявить публичный метод в ViewModel.
В наш список мы сможем добавлять текущие дела как обычный текст и проверять их валидность при добавлении. Также дела можно будет отмечать их как сделаные.
Сначала добавим ToDoItem.cs класс.
public class ToDoItem
{
[Required]
public string Text { get; set; }
public bool IsDone { get; set; }
}
Так, как мы не хотим добавлять пустые дела без текста, мы будем использовать DataAnnotations [Required].
Добавим код в View и ViewModel
ViewModel — DefaultViewModel.cs
public class DefaultViewModel : MasterPageViewModel
{
//ToDoItem, который мы будем добавлять
public ToDoItem ToDoItem { get; set; } = new ToDoItem();
public DefaultViewModel()
{
}
Представление (View) — Default.dothml
<label for="todotext">Item:</label>
//привязка к тексту ToDoItem
<dot:TextBox ID="todotext"Text="{value: ToDoItem.Text}" />
В DotVVM работает со встроенными элементами управления и их свойствами. Для работы со списками используется <dot:Repeater>. Привязка образуется через свойство DataSource. При этом все внутренние элементы автоматически изменят свой контекст объекта в списке. Добавим список типа List в ViewModel и Repeater в View.
ViewModel — DefaultViewModel.cs
public class DefaultViewModel : MasterPageViewModel
{
//ToDoItem, который мы будем добавлять
public ToDoItem ToDoItem { get; set; } = new ToDoItem();
public List<ToDoItem> ToDoItems { get; set; } = new List<ToDoItem>();
public DefaultViewModel()
{
}
}
<label for="todotext">Item:</label>
//привязка к тексту ToDoItem
<dot:TextBox ID="todotext"Text="{value: ToDoItem.Text}" />
<hr />
<dot:Repeater DataSource="{value: ToDoItems}">
<span>{{value: Text}}</span>
<span Visible="{value: IsDone}">Done!</span>
</dot:Repeater>
Осталось добавить функции. Одну для добавления и одну для пометки дела в списке. Добавим их в ViewModel.
public class DefaultViewModel : MasterPageViewModel
{
//ToDoItem, который мы будем добавлять
public ToDoItem ToDoItem { get; set; } = new ToDoItem();
public List<ToDoItem> ToDoItems { get; set; } = new List<ToDoItem>();
public DefaultViewModel()
{
}
public void AddTodoItem(ToDoItem item)
{
ToDoItems.Add(ToDoItem);
ToDoItem = new ToDoItem();
}
public void MarkAsDone(ToDoItem item)
{
item.IsDone = true;
}
}
В View добавим две кнопки <dot:Button/>. Текст кнопки передается через свойство Text а метод выполнения через Click. Также можно использовать свойство IsSubmitButton, при помощи которого кнопка будет нажиматься автоматически после нажатия Enter. Используем это свойство у кнопки, которая добавляет новое дело в список.
<label for="todotext">Item:</label>
//привязка к тексту ToDoItem
<dot:TextBox ID="todotext"Text="{value: ToDoItem.Text}" />
<dot:Button Text="Add Item" IsSubmitButton="true" Click="{command: AddTodoItem(ToDoItem)}"></dot:Button>
<hr />
<dot:Repeater DataSource="{value: ToDoItems}">
<span>{{value: Text}}</span>
<span Visible="{value: IsDone}">Done!</span>
</dot:Repeater>
Осталось к каждому делу в списке добавить кнопку, которая обозначит дело как сделанное. Должна отобразится надпись «Done» а кнопка должна исчезнуть. Чтобы сделать привязку в контекст DefaultViewModel из елемента Repeater, добавим _parent. Чтобы передать весь обьект из списка, передадим в метод _this.
Последнее свойство, которое мы будем использовать в этом уроке, это Validation.Enabled. Валидация по умолчанию работает так, что любой постбэк блокируется если валидация не проходит. В нашем случае может возникнуть ситуация, когда мы захотим пометить дело как сделанное, но поле с текстом останется пустым. Чтобы разрешить постбэк и игнорировать валидацию при нажатии кнопки, изменим Validation.Enabled на значение false.
<label for="todotext">Item:</label>
//привязка к тексту ToDoItem
<dot:TextBox ID="todotext"Text="{value: ToDoItem.Text}" />
<dot:Button Text="Add Item" IsSubmitButton="true" Click="{command: AddTodoItem(ToDoItem)}"></dot:Button>
<hr />
<dot:Repeater DataSource="{value: ToDoItems}">
<span>{{value: Text}}</span>
<p><dot:Button Validation.Enabled="false" Visible="{value: !IsDone}" Text="Mark as done" Click="{command: _parent.MarkAsDone(_this)}"></dot:Button></p>
<hr />
</dot:Repeater>
Существуют также расширенные средства управления, такие как GridView или FileUpload, а также элемент управления SpaContentPlaceHolder, который превратит веб-приложение в Одностраничное приложение.
Вы также можете использовать разные типы привязок, локализацию RESX и Action фильтры, но об этом в следующей статье.
Спасибо за внимание.
Ссылки:
DotVVM на GitHub
Финальный проект
Комментарии (14)
ZonerM Автор
16.04.2018 22:34Простите за неопытность)
Именно так. Фреймворк разрабатывался для того, чтобы за счет большого количества готовых элементов управления и понятного синтаксиса создавать бизнес-приложения и SPA без JavaScript кода.Mikluho
17.04.2018 13:15Говоря «SPA без JavaScript кода» вы имеете ввиду отсутствие js в клиентском коде или то, что программисту не нужно его писать?
Да и чем ваш фреймворк лучше какой0нибуль библиотеки компонентов, типа devexpress?
И ещё вопрос — вы упоминаете postback, это именно отправка данных через post формы? Из-за которой нельзя пользоваться кнопкой back в браузере?ZonerM Автор
17.04.2018 20:29Devexpress это только элементы управления. DotVVM это готовый фреймворк, который отвечает также за взаимодействия между сервером и клиентом.
Кстати, елементы управления Devexpress можно использовать в DotVVM проекте.Mikluho
18.04.2018 09:33Ну… с компонентами devexpress обмен клиент-сервер тоже работает… примерно сам собой, т.е. не требует особых усилий со стороны программиста.
И да, хочется увидеть ответы и на другие вопросы.
kekekeks
17.04.2018 08:59_parent.MarkAsDone
Я правильно понимаю, что вот эта штука приводит к вызову на сервер а ля ASP.NET Web Forms? Что происходит с вью-моделью? Она всё это время на сервере висит в памяти? Что происходит в таком случае при перезапуске сервера?
oddmanout
17.04.2018 11:34Вью-модель шлётся с клиента при постбэке. После выполнения команды, модифицированная модель сериализуется и шлётся обратно клиенту.
ZonerM Автор
17.04.2018 20:08ViewModel посылается весь не всегда. Существует атрибут Bind и Static command. Разбору взаимодействия между сервером и клиентом будет посвящена отдельная статья.
kekekeks
17.04.2018 21:04Меня интересует наличие стейта в памяти сервера, как это происходит в том же Ooui.
ZonerM Автор
17.04.2018 22:02В двух словах, ViewModel находящийся на сервере, находится там только на время http запроса. Перезапуск на ViewModel никак не повлияет, так-как в самом ViewModel есть все необходимое для обработки запроса.
lair
17.04.2018 22:11То есть в вашем примере весь список ToDo будет летать между сервером и клиентом на каждом запросе?
Mikluho
Имхо, начать стоило с того, что это за фреймворк, кому он нужен, что в нём хорошего, что лучше, чем в других…
А то как-то скучно и грустно смотреть на очередную стандартную демку, которая ничем не способна заинтересовать.
SbWereWolf
+1. У меня чисто один вопрос зачем это нужно? что бы писать SPA на C# без JavaScript? В смысле DotVVM это замена использованию JavaScript на фронт энде?