2012-07-03 1 views
9

В проекте ASP.NET MVC мы используем AutoMapper для сопоставления из модели домена в viewmodel, а иногда и при выравнивании иерархии. Это работает как шарм и делает логику рендеринга наших взглядов очень скудной и простой.Как мутировать editmodel/postmodel для модели домена

Путаница начинается, когда мы хотим перейти в другую сторону от модели вида (или постмоделирования или редактирования) к модели домена, особенно при обновлении объектов. Мы не можем использовать автоматизированные/двухстороннее отображение, потому что:

  1. мы должны unflat уплощенной иерархии
  2. всех свойств на модели предметной области должен быть изменяемыми/у государственных сеттера
  3. вызваны изменения исходя из представления, не всегда просто плоские свойства отображаются обратно в домен, но иногда нужно вызывать методы типа «ChangeManagerForEmployee()» или аналогичные.

Это также описано в статье Джимми Bogards: The case for two-way mapping in AutoMapper, но решение этой проблемы не описано подробно, только что они идут:

От EditModel к CommandMessages - происходит от loosely- напечатано EditModel для строго типизированных, разбитых сообщений. Один EditModel может генерировать полдюжины сообщений.

В подобном SO question есть ответ на Mark Seeman, где он упоминает, что

Мы используем абстрактные картограф и услуги для отображения PostModel в объект домена

но детали - концептуальная и техническая реализация - не учитывается.

Наша идея сейчас заключается в следующем:

  1. ПОЛУЧИТЕ FormCollection в методе действия контроллера
  2. Получить оригинальную модель домена и придавить его viewModelOriginal и viewModelUpdated
  3. сливая FormCollection в viewModelUpdated с помощью UpdateModel()
  4. Используйте некоторый общий вспомогательный метод для сравнения viewModelOriginal с viewModelUpdated
  5. Либо A) Создать CommandMessages а-ля Джимми Богард или B) мутировать различия непосредственно в модели предметной области с помощью свойств и методов (возможно, отображающих 1-1 свойства непосредственно через AutoMapper)

Может кто-нибудь привести несколько примеров того, как они происходят из FormCollection через editmodel/postmodel для модели домена? «CommandMessages» или «абстрактные карты и службы»?

+1

Я бы задал этот вопрос тысячам оборотов, если бы мог. Я бесконечно искал надежный ответ на этот вопрос. – devuxer

+0

В каком процессе вы в конце концов? –

+0

Привет, Том. Мы закончили тем, что использовали решение смешивания и соответствия, где мы 1. Извлеките объект Dom из DAL/DB, 2. сгладьте объект Dom в ViewModel, 3. используйте TryUpdateModel с FormColl на ViewModel, 4.используйте AutoMapper для обратного сопоставления из сплющенной модели представления в Dom (Иерархия) для простых свойств и 5. используйте службу для сопоставления нетривиальных свойств из методов viewmodel в Dom (объект Dom и/или Dom Service). Надеюсь, что это поможет - я не уверен, какой ответ отметить как правильный, так как это своего рода смесь из нескольких ...? –

ответ

1

Я использую следующий шаблон:

[HttpPost] 
public ActionResult Update(UpdateProductViewModel viewModel) 
{ 
    // fetch the domain model that we want to update 
    Product product = repository.Get(viewModel.Id); 

    // Use AutoMapper to update only the properties of this domain model 
    // that are also part of the view model and leave the other properties unchanged 
    AutoMapper.Map<UpdateProductViewModel, Product>(viewModel, product); 

    // Pass the domain model with updated properties to the DAL 
    repository.Update(product); 

    return RedirectToAction("Success"); 
} 
+0

Привет, Дарин, спасибо за ваш ответ, но я ищу, как мутировать/переводить сплющенную viewmodel обратно в иерархию/агрегацию модели домена не только посредством сопоставления/свойств, но и с использованием методов. –

+0

Кажется, что этот шаблон приведет к нечеткому отображению объекта домена. – Artyom

1

Вы могли бы хотеть рассмотреть CQRS (Command Query Ответственность Сегрегация - Я думаю, что это может быть концепция вы отсутствовали), возможно, даже с Event Sourcing.

Практически разделение логики чтения из источника данных и запись на источник данных может означать наличие разных моделей данных для чтения и записи.

Это может быть хорошим местом для начала: http://abdullin.com/cqrs/

+0

Hi Pawel, thx Я раньше смотрел CGRS, может быть, я снова загляну в нее. У меня уже есть некоторые идеи о том, как разделять логику, но я конкретно смотрю, как перевести форму FormCollection/EditModel в модель домена, возможно, через командные сообщения, но как узнать, какие сообщения создавать? Или, если вы выполняете услуги (абстрактные карты), как я узнаю, что изменилось? Моя EditModel содержит только результаты изменений, а не сами изменения/сообщения. –

+0

Насколько я понимаю, ваша ситуация: в пользовательском интерфейсе у вас есть большая форма, которая имеет, скажем, 20 полей и значений, но вы не знаете, какие из них отправляют все значения обратно на сервер (после нажатия пользователем «Сохранить»,). Как бы я к этому приблизился, пытаясь добиться разделения команд/запросов, я бы разделил действие «Сохранить» на команды (команды поступают из пользовательского интерфейса). На практике это означало бы отправку только полей, которые были изменены. И я не думаю, что привяжу эти значения к модели представления, но рассматриваю их просто как список команд. –

+0

Правильно, у меня есть большая форма редактирования, заполненная сплющенной моделью. Когда пользователь редактирует и отправляет форму обратно на контроллер, я не вижу, какие поля были изменены. Моя идея - сравнить набор моделей «До» и «После» (оригинал, который был заполнен и обновлен, который является исходным + объединенным значением формы сообщения через UpdateModel_), а затем сгенерировать команды оттуда (на стороне сервера). Так что, я думаю, это зависит от того, что вы подразумеваете под «UI»: UI, как на стороне клиента JS или UI, как на стороне сервера + контроллер? –

0

Вариант C: Положите все это в действии контроллера. Затем, если это становится волосатым, разложитесь на службы (абстрактные mappers) или messages-as-methods (путь сообщения команд).

Command путь сообщение:

public ActionResult Save(FooSaveModel model) { 
    MessageBroker.Process(model); 

    return RedirectToAction("List"); 
} 

И процессор:

public class FooSaveModelProcessor : IMessageHandler<FooSaveModel> { 

    public void Process(FooSaveModel message) { 
     // Message handling logic here 
    } 

} 

Это действительно просто о переносе «обработки» формы из действия контроллера и в отдельных, специализированных обработчиков ,

Но, я бы действительно пошел по этому маршруту, если действия контроллера становятся волосатыми. В противном случае просто заполните форму и при необходимости сделайте соответствующие обновления для моделей домена.

+0

Привет, Джимми, спасибо за ваш ответ. Я определенно стараюсь не доводить вещи до волоса и держать мои контроллеры легкими, как в [ASP.NET MVC 4 в действии] (http://manning.com/palermo3/). Я также смотрел командные сообщения (например [здесь] (http://codebetter.com/iancooper/2011/04/27/why-use-the-command-processor-pattern-in-the-service-layer /) и «Использование шины приложения» в книге), но откуда вы знаете, что изменилось в FooSaveModel? В старые времена веб-форм у меня было бы событие SelectedIndexChanged из раскрывающегося списка CurrentManager. Теперь у меня есть только конечный результат в FooSaveModel? –

+0

Jimmy, будет ли ваша реализация 'Process (FooSaveModel message)' подобна [предложению, которое я сделал для Pawel] (http://stackoverflow.com/questions/11313822/how-to-mutate-editmodel-postmodel-to- домен-модель # comment14932448_11320582)? То есть вы на самом деле не смотрите на «раньше» и «после» savemodels, чтобы увидеть, что изменилось, но вместо этого сравните и сопоставьте SaveModel напрямую с DomainModel, опционально вызывая методы по мере необходимости (например, «ChangeManager()»)? –

+0

Зачем вам нужно заботиться о том, что изменилось или нет? Если меня интересуют изменения определенных полей, это может означать, что мне нужно больше экранов с интерфейсами для конкретных задач (и проверки). –

0

Здесь есть некоторые сходства с тем, что я делал. Моя иерархия моделей взглядов несколько сглажена из ее эквивалентов объектов домена, но мне приходится иметь дело с вызовом явных методов обслуживания для сохранения, чтобы делать такие вещи, как добавление в дочерние коллекции, изменение важных значений и т. Д., А не просто обратное сопоставление. Мне также приходится сравнивать до и после моментальных снимков.

Мое сохранение Ajax отправлено как JSON в действие MVC и вводит это действие, магически связанное с структурой модели представления MVC. Затем я использую AutoMapper, чтобы преобразовать модель представления верхнего уровня и ее потомков обратно в свою эквивалентную структуру домена. Я определил ряд пользовательских AutoMapper ITypeConverters для тех случаев, когда новый клиентский элемент был добавлен на клиенте (я использую Knockout.js), и мне нужно вызвать явный метод службы. Что-то вроде:

  foreach (ChildViewModel childVM in viewModel.Children) 
     { 
      ChildDomainObject childDO = domainObject.Children.Where(cdo => cdo.ID.Equals(childVM.ID))).SingleOrDefault(); 
      if (childDO != null) 
      { 
       Mapper.Map<ChildViewModel, ChildDomainObject>(childVM, childDO); 
      } 
      else 
      { 
       MyService.CreateChildDO(someData, domainObject); // Supplying parent 
      } 
     } 

я сделать подобную вещь для удалений, и этот процесс каскады довольно красиво вниз по всей структуре. Я предполагаю, что сглаженная структура может быть проще или труднее - у меня есть AbstractDomainViewModel с идентификатором, с которым я делаю вышеуказанное совпадение, что помогает.

Мне нужно выполнить сравнения до и после обновления, потому что мой уровень сервиса вызывает триггерную проверку, которая может повлиять на другие части графического объекта, и это диктует, какой JSON мне нужно вернуть как ответ Ajax. Меня интересуют только изменения, которые имеют отношение к пользовательскому интерфейсу, поэтому я преобразовываю объект сохраненного домена обратно в новую модель представления, а затем получаю вспомогательный метод для сравнения двух моделей представлений, используя комбинацию ручных проверок и отражений.

Смежные вопросы