使用模型绑定器时在 ASP.NET MVC 中往返视图数据
Posted
技术标签:
【中文标题】使用模型绑定器时在 ASP.NET MVC 中往返视图数据【英文标题】:Round-tripping view data in ASP.NET MVC while using Model Binders 【发布时间】:2011-01-05 02:06:03 【问题描述】:假设我有一个包含以下“业务对象”的表单:
public class MyObject
public string Name get; set;
public User OtherUser get; set;
public DateTime CreateDate get; set;
public DateTime? StartDate get; set;
public DateTime? EndDate get; set;
当用户在任何字段中输入数据时,我需要往返输入他们输入的内容,以便他们更正任何粗手指等,而无需重新输入他们的响应。
因为我不能在 DateTime
字段中往返传递像“2011 年 2 月 31 日”这样的值,所以我最终使用了这样的 View Model 对象:
public class MyObjectViewModel
public string Name get; set;
public string OtherUserName get; set;
public string CreateDate get; set;
public string StartDate get; set;
public string EndDate get; set;
好的,一切都很好,花花公子,当使用以下模式时,我可以让它呈现与裸业务对象和值往返完全相同的效果:
public ActionResult Create(FormCollection form)
var model = new MyObjectViewModel();
if (TryUpdateModel(model, form) && ModelState.IsValid)
// ...
return View(model);
我有以下问题:
-
将数据从视图模型中取出并放入业务对象的最简洁方法是什么? (即上述方法的其余部分是什么?)
能否减少对象之间的字段名称重复,从而巩固我的更改?
在上面的例子中,字段
OtherUserName
是一个string
,需要转换成一个User
对象。这是谁的责任?控制器?视图模型?模型粘合剂?
【问题讨论】:
【参考方案1】:-
AutoMapper
你不需要。
映射器
例子:
[HttpPut]
public ActionResult Create(MyObjectViewModel viewModel)
if (!ModelState.IsValid)
// there are validation errors => redisplay the view
return View(viewModel);
var model = Mapper.Map<MyObjectViewModel, MyObject>(viewModel);
_repository.DoSomethingWithTheModel(model);
return RedirectToAction("Success")
【讨论】:
+100 用于 AutoMapper。为了加强#2,消除重复,imo,不应该是最强的动力。我似乎在某些点上发现了重复——ViewModels 作为应用层边界交叉点就是这样一个点——复杂性净降低了。也就是说,是的,有一些相互镜像的对象会增加复杂性。但这种复杂性相对较小。减少视图和域之间的耦合具有更大的效果,同样是 imo。 有趣... automapper 会更新现有对象的属性吗? @John,AutoMapper 自动映射具有相同名称的属性。如果有不同的名称/规则,您需要定义它们。 另外,#3 会是什么样子?我已经在使用自己的基于反射的机制进行映射,但我对工作的完成方式不满意。 @John,这取决于User
对象与string
的关系。【参考方案2】:
您的问题主要是由于允许视图模型包含无效数据引起的。在视图模型上使用与数据类相同的强类型,添加一点 javascript 验证,“Feb 31”将永远不会到达服务器。解析类型绝对是模型绑定器的责任——您不需要做任何事情,您的控制器操作只需传递一个强类型模型对象。不过,用户可能有点不同——主要区别可能是您的视图模型有一个名为用户名的字段,而数据模型需要一个用户对象,其中包含表单上没有的信息。您的控制器需要获取/创建适当的用户对象并将其添加到数据类中。
在解析模型后,您仍然会在服务器端进行一些验证,但这将是更多自定义内容,例如检查字段是否相互一致,而不是简单的字符串格式问题。
为了减少重复,我在另一个问题上发布了我的模型风格 - asp.mvc model design
【讨论】:
【参考方案3】:1) 您可以强烈键入您的视图,以便视图通过控制器“MyObject”类型。 2)不知道我明白你在问什么 3) 为什么不将此字段设为包含链接 ID 的外键的 ID?
另外 - 没有理由不能将日期时间字段传递给视图并按原样返回。您不需要将其作为字符串传递并进行转换。
PS - 我建议查看本教程 - 应该为您澄清我的答案。
http://www.asp.net/mvc/videos/what-is-aspnet-mvc-80-minute-technical-video-for-developers-building-nerddinner
【讨论】:
1) 首先,我的观点是强类型的。此外,不,如果我这样做,数据不会往返,我无法以这种方式更新现有的数据库对象。 3) 你要我让用户输入数据库中对象的 ID 吗?我认为这不会顺利进行。 1) 那么最简洁的方法是告诉您的控制器期待“MyObject”类型而不是 FormCollection。如果您使用的是强类型视图,绑定就这么简单。 3) 不,我通常通过 JSON/AJAX 检索友好名称并将其绑定到下拉列表。然后用户可以选择它,但 ID 会传递给控制器(您需要一些 javascript 帮助来执行此操作 - 在视图中需要它来将所选 ID 绑定到隐藏的模型 ID 字段)。以上是关于使用模型绑定器时在 ASP.NET MVC 中往返视图数据的主要内容,如果未能解决你的问题,请参考以下文章
为啥 ASP.Net MVC 模型绑定器将空 JSON 数组绑定到 null?
ASP.NET 5 MVC 6 RC1 API 中的自定义模型绑定异常