首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在POST操作中将视图模型映射回域模型?

如何在POST操作中将视图模型映射回域模型?
EN

Stack Overflow用户
提问于 2010-02-05 16:56:55
回答 4查看 24.8K关注 0票数 88

在互联网上找到的每一篇关于使用ViewModels和利用自动映射程序的文章都给出了“控制器->视图”方向映射的指导方针。您将一个域模型和所有选择列表放入一个专门的ViewModel中,并将其传递给视图。这很清楚,也很好。

视图有一个表单,最终我们处于POST操作中。在这里,所有的模型绑定器都来到了现场,显然还有另一个视图模型,它显然与原始的ViewModel有关,至少在命名约定方面是为了绑定和验证。

如何将其映射到您的域模型?

假设它是一个插入操作,我们可以使用相同的Automapper。但是,如果这是一个更新操作呢?我们必须从存储库中检索我们的域实体,根据ViewModel中的值更新它的属性,并保存到存储库。

附录1(2010年2月9日):有时,分配模型的属性是不够的。根据视图模型的值,应该对领域模型采取一些措施。也就是说,一些方法应该在域模型上调用。也许,在控制器和域之间应该有一种应用程序服务层,以便处理视图模型……

如何组织此代码以及将其放置在何处以实现以下目标?

  • keep controllers
  • 荣获practice
  • follow域驱动设计principles
  • be DRY
  • SoC be continued ...
EN

回答 4

Stack Overflow用户

发布于 2010-05-06 02:06:42

我使用IBuilder接口并使用ValueInjecter实现它

代码语言:javascript
复制
public interface IBuilder<TEntity, TViewModel>
{
      TEntity BuildEntity(TViewModel viewModel);
      TViewModel BuildViewModel(TEntity entity);
      TViewModel RebuildViewModel(TViewModel viewModel); 
}

..。(实现) RebuildViewModel仅调用BuildViewModel(BuilEntity(viewModel))

代码语言:javascript
复制
[HttpPost]
public ActionResult Update(ViewModel model)
{
   if(!ModelState.IsValid)
    {
       return View(builder.RebuildViewModel(model);
    }

   service.SaveOrUpdate(builder.BuildEntity(model));
   return RedirectToAction("Index");
}

希望能有所帮助

更新:我现在在ProDinner ASP.net MVC Demo App中使用这种方法,它现在被称为IMapper,还有一个pdf文档详细解释了这种方法

票数 37
EN

Stack Overflow用户

发布于 2010-02-05 21:06:34

像AutoMapper这样的工具可用于用源对象中的数据更新现有对象。用于更新的控制器操作可能如下所示:

代码语言:javascript
复制
[HttpPost]
public ActionResult Update(MyViewModel viewModel)
{
    MyDataModel dataModel = this.DataRepository.GetMyData(viewModel.Id);
    Mapper<MyViewModel, MyDataModel>(viewModel, dataModel);
    this.Repostitory.SaveMyData(dataModel);
    return View(viewModel);
}

除了上面的代码片段中可见的内容之外:

  • POST数据到视图模型+验证是在ModelBinder中完成的(可以使用自定义过滤器处理进行扩展(例如,通过存储库捕获数据访问异常抛出),可以由HandleError filter

完成

控制器操作非常简单,而且关注点是分开的:映射问题在AutoMapper配置中解决,验证由ModelBinder完成,数据访问由存储库完成。

票数 7
EN

Stack Overflow用户

发布于 2010-10-08 21:42:33

我想说的是,您可以重用术语ViewModel来表示客户端交互的两个方向。如果您已经阅读了足够多的ASP.NET MVC代码,那么您可能已经看到了ViewModel和EditModel之间的区别。我认为这很重要。

ViewModel表示呈现视图所需的所有信息。这可能包括在静态非交互位置呈现的数据,也可能包括纯粹为了执行检查以决定呈现的确切内容的数据。控制器GET操作通常负责为其视图打包ViewModel。

EditModel (或者可能是ActionModel)表示执行用户想要对该帖子执行的操作所需的数据。所以EditModel实际上是在试图描述一个动作。这可能会从ViewModel中排除一些数据,尽管相关,但我认为认识到它们确实不同是很重要的。

One Idea

也就是说,你可以很容易地从模型-> ViewModel获得一个AutoMapper配置,并从EditModel ->模型获得一个不同的配置。然后,不同的控制器操作只需要使用AutoMapper。见鬼,EditModel可以有一个函数来根据模型验证它的属性,并将这些值应用到模型本身。它没有做其他任何事情,而且你在MVC中有ModelBinders来将请求映射到EditModel。

Another Idea

除此之外,我最近一直在思考的一件事是,ActionModel的想法是,客户端回发给您的实际上是用户执行的几个操作的描述,而不仅仅是一大堆数据。这当然需要客户端的一些Javascript来管理,但我认为这个想法很有趣。

本质上,当用户在您呈现的屏幕上执行操作时,Javascript将开始创建一个操作对象列表。例如,用户可能在员工信息屏幕上。他们更新姓氏并添加新地址,因为该员工最近刚结婚。在幕后,这将在列表中生成一个ChangeEmployeeName和一个AddEmployeeMailingAddress对象。用户单击“Save”提交更改,您提交两个对象的列表,每个对象仅包含执行每个操作所需的信息。

您需要一个比默认ModelBinder更智能的JSON,但是好的JSON序列化程序应该能够处理客户端操作对象到服务器端操作对象的映射。服务器端的那些(如果你在2层环境中)可以很容易地拥有在他们所使用的Model上完成操作的方法。因此,控制器操作最终只是获取要拉取的模型实例的Id和要在其上执行的操作列表。或者动作中包含id以使它们保持非常独立。

因此,这样的事情可能会在服务器端实现:

代码语言:javascript
复制
public interface IUserAction<TModel>
{
     long ModelId { get; set; }
     IEnumerable<string> Validate(TModel model);
     void Complete(TModel model);
}

[Transaction] //just assuming some sort of 2-tier with transactions handled by filter
public ActionResult Save(IEnumerable<IUserAction<Employee>> actions)
{
     var errors = new List<string>();
     foreach( var action in actions ) 
     {
         // relying on ORM's identity map to prevent multiple database hits
         var employee = _employeeRepository.Get(action.ModelId);
         errors.AddRange(action.Validate(employee));
     }

     // handle error cases possibly rendering view with them

     foreach( var action in editModel.UserActions )
     {
         var employee = _employeeRepository.Get(action.ModelId);
         action.Complete(employee);
         // against relying on ORMs ability to properly generate SQL and batch changes
         _employeeRepository.Update(employee);
     }

     // render the success view
}

这实际上使得回发操作相当通用,因为您依赖ModelBinder来获得正确的IUserAction实例和IUserAction实例来执行正确的逻辑本身,或者(更有可能的)使用信息调用模型。

如果你是在一个3层的环境中,那么IUserAction可以被简单地做成DTO,跨越边界,并在应用层上以类似的方法执行。根据您如何做这一层,它可以非常容易地拆分,并仍然保留在一个事务中(脑海中浮现的是Agatha的请求/响应,并利用DI和NHibernate的身份映射)。

无论如何,我确信这不是一个完美的想法,它将需要一些客户端的JS来管理,我还没有能够做一个项目来看看它是如何展开的,但是这篇文章试图思考如何去那里和回来,所以我想我会给出我的想法。我希望它能有所帮助,我也很乐意听到其他管理互动的方法。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2206005

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档