我在大多数 .NET MVC 示例中看到的模式是让您的模型成为在 Controller 和较低层之间传递的对象,并直接与这些对象进行表单绑定(bind)。我选择了 domain-driven我在层之间传递域对象的方法。想法是将这些对象传递到 View 中。
我遇到的问题是涉及带有表单的页面。我打算为表单在返回的路上绑定(bind)到单独的对象(其中也将包含验证注释)。我将它与域对象分开,因为单个对象可能会被不同的页面更新,每个页面都有自己的验证要求(例如,一个人的地址可能甚至不会显示在一个页面上,但在另一个页面上需要,所以验证并不总是适用于通用域对象)。一旦您回发表单并需要显示错误,这会使事情变得复杂。
以更新页面为例。我将 View 键入我的域 Person 对象,页面将从中填充它的字段值。回发操作将采用该页面的表单对象并对其进行验证。如果它通过了,我使用 automapper将值复制到表单外的域对象并保存。这一切都有效。它崩溃的地方是在出现错误时重新显示该页面。如果将其键入域对象,我最终只会根据旧值而不是用户输入的值重新填充字段。如果它被输入到表单对象,那么我需要将我所有的域对象转换为每个页面的这些表单对象(如果我需要一些值,我仍然可能必须传入域对象,我将对该页面使用只读).
我确信我忽略了这里的某些东西/过于复杂了。
更新 由于@Charlino 所说的内容,在玩耍后发现了一个有趣的发现。如果我使用强类型的 html 帮助程序进行输入 (Html.TextBoxFor()),即使将 View 键入域对象,它也会记住这些值。如果我使用通用的 (Html.TextBox()) 或原始 HTML,它似乎没有。
最佳答案
我最终会为每个 View 创建一个 ViewModel 对象。
这是一些更前期的工作,因为我必须定义 ViewModel 和映射,但该代码非常简单明了,只需几秒钟即可编写完成。
通常,当我需要一个表单时,我会创建一个单独的 Form 对象,并让 ViewModel 包含它。
public class MyViewModel
{
public string SomeNonFormDisplayValue { get; set; }
public bool AnotherDisplayOnlyValue { get; set; }
public IEnumerable<Tuple<int, string>> SelectionListItems { get; set; }
public MyViewsForm Form { get; set; }
}
public class MyViewsForm
{
public string EditableProperty { get; set; }
public int SelectionListItemId { get; set; }
}
我将我的 View 输入到 ViewModel,但我让 Post Action 方法只采用该形式。
public class MyController
{
[HttpGet]
public ActionResult Edit() { ... }
[HttpPost]
public ActionResult Edit(MyViewsForm form) { ... }
}
我还创建了查询方法来检索 ViewModel,一个填充表单,另一个不填充 - 因为当我返回有错误的 POST 表单时。
关于c# - 具有域驱动设计的 MVC .NET 表单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4326378/