Я хотів би сказати, що ви повторно використовуєте термін ViewModel для обох напрямків взаємодії з клієнтом. Якщо ви прочитали достатньо коду ASP.NET MVC у дикій природі, ви, мабуть, бачили різницю між ViewModel та EditModel. Я думаю, що це важливо.
ViewModel представляє всю інформацію, необхідну для відображення подання. Сюди можуть входити дані, які відображаються у статичних неінтерактивних місцях, а також дані виключно для здійснення перевірки, щоб вирішити, що саме відображати. Дія контролера GET, як правило, відповідає за упаковку ViewModel для її View.
EditModel (або, можливо, ActionModel) представляє дані, необхідні для виконання дії, яку користувач хотів зробити для цього POST. Тож EditModel справді намагається описати дію. Це, ймовірно, виключить деякі дані з ViewModel, і хоча пов’язані, я думаю, важливо розуміти, що вони насправді різні.
Одна ідея
Це означає, що ви можете дуже легко мати конфігурацію AutoMapper для переходу з Модель -> ViewModel та іншу, щоб перейти з EditModel -> Модель. Тоді для різних дій контролера просто потрібно використовувати AutoMapper. До біса EditModel може мати на ньому функції для перевірки його властивостей щодо моделі та застосування цих значень до самої Моделі. Це не робить нічого іншого, і у вас є ModelBinders у MVC, щоб все одно зіставити Запит із EditModel.
Ще одна ідея
Окрім того, про що я нещодавно думав, що начебто спрацьовує ідею ActionModel, це те, що клієнт до вас публікує, це насправді опис кількох дій, які виконував користувач, а не лише одна велика куля даних. Для цього, безсумнівно, потрібен певний Javascript на стороні клієнта для управління, але, на мою думку, ідея інтригує.
По суті, коли користувач виконує дії на екрані, який ви їм презентували, Javascript почне створювати список об’єктів дій. Прикладом є, можливо, користувач знаходиться на екрані інформації про працівника. Вони оновлюють прізвище та додають нову адресу, оскільки працівник нещодавно одружився. Під обкладинками це створює a ChangeEmployeeName
та AddEmployeeMailingAddress
об'єкти у списку. Користувач натискає "Зберегти", щоб здійснити зміни, і ви подаєте список двох об'єктів, кожен з яких містить лише інформацію, необхідну для виконання кожної дії.
Вам знадобиться інтелектуальніший ModelBinder, ніж стандартний, але хороший серіалізатор JSON повинен мати можливість подбати про відображення об’єктів дій на стороні клієнта до об’єктів на стороні сервера. Серверні (якщо ви перебуваєте у дворівневому середовищі) можуть легко мати методи, які завершують дію щодо Моделі, з якою вони працюють. Отже, дія Controller в кінцевому підсумку отримує лише ідентифікатор для екземпляра Model, який потрібно витягнути, і список дій, які потрібно виконати з ним. Або дії мають ідентифікатор, щоб тримати їх дуже окремими.
Тож, можливо, щось подібне реалізується на стороні сервера:
public interface IUserAction<TModel>
{
long ModelId { get; set; }
IEnumerable<string> Validate(TModel model);
void Complete(TModel model);
}
[Transaction]
public ActionResult Save(IEnumerable<IUserAction<Employee>> actions)
{
var errors = new List<string>();
foreach( var action in actions )
{
var employee = _employeeRepository.Get(action.ModelId);
errors.AddRange(action.Validate(employee));
}
foreach( var action in editModel.UserActions )
{
var employee = _employeeRepository.Get(action.ModelId);
action.Complete(employee);
_employeeRepository.Update(employee);
}
}
Це дійсно робить дію зворотного розміщення досить загальною, оскільки ви покладаєтесь на свій ModelBinder, щоб отримати правильний екземпляр IUserAction та ваш екземпляр IUserAction або виконувати правильну логіку самостійно, або (що, швидше за все,) викликати Модель з інформацією.
Якби ви знаходились у 3-рівневому середовищі, IUserAction можна було б просто зробити простими DTO для перестрілки через кордон і виконати подібним методом на рівні програми. Залежно від того, як ви робите цей шар, його можна дуже легко розділити і все одно залишатись у транзакції (на думку спадає запит / відповідь Агати та використання переваг карти ідентичності DI та NHibernate).
У будь-якому випадку, я впевнений, що це не ідеальна ідея, для управління потрібні деякі JS на стороні клієнта, і я ще не зміг зробити проект, щоб побачити, як він розвивається, але пост намагався подумати про те, як дістатися туди і назад, щоб я думав, що розкажу свої думки. Сподіваюся, це допоможе, і я хотів би почути про інші способи управління взаємодіями.