使用远程验证的ASP.NET MVC绑定

时间:2015-07-29 11:27:05

标签: c# asp.net asp.net-mvc validation asp.net-mvc-4

我的模型ModelA包含成员toBeRemoteChecked,模型MapToA包含成员valueToMap。每当我创建ModelA的实例时,我还需要MapToA的实例,因此我有一个模型CreateModelA,其中包含成员modelA和成员{{1} }。提交表单后,我将valueToMap添加到数据库表modelA并创建并添加一个实例ModelA,其中包含一个MapToA和{{ 1}}。在代码方面

modelA

当我编辑valueToMap的实例时,public class ModelA { [Key] public int ID { get; set; } [Required, Remote("isValid", "MyController", ErrorMessage = "not valid")] public string toBeRemoteChecked { get; set; } } public class MapToA { [Key] public int Map_ID { get; set; } [Required] public int modelAID { get; set; } [Required] public int valueToMap { get; set; } } public class CreateModelA { public ModelA modelA { get; set; }; public int valueToMap { get; set; }; } 中的值并不重要(在大多数情况下,ModelA的{​​{1}}个实例不止一个相同的MapToA ID),但mapToA的远程验证仍然很重要。

我的问题:验证方法的绑定:

modelA

如果我原样保留,则在编辑toBeRemoteChecked时有效,但在我通过public ActionResult isValid(string toBeRemoteChecked) { ... } 创建ModelA时却无效(我总是得到空值)在ModelA)。当我使用BindPrefix

CreateModelA

当我创建toBeRemoteChecked时它正在工作,但在我编辑它时却没有。

当我尝试更改"名称"在Create.cshtml中,通过在public ActionResult isValid([Bind(Prefix = "modelA.toBeRemoteChecked")] string toBeRemoteChecked) { ... } 的htmlAttributes中添加ModelA(而不是由HTML帮助程序创建的... @Name = "toBeRemoteChecked" ...,然后验证正在运行,但是值与表的绑定失败,当值保存到数据库时,我得到错误(空值)。

那么,我如何实现创建和编辑的不同绑定?

到目前为止,我的解决方法是制作modelA.toBeRemoteChecked@Html.TextBoxFor ModelA并检查CreateModelA方法中的成员: IValidatableObject。但是那个在表单顶部而不是在TextFor框的位置显示错误消息。

所以:最佳解决方案:如何在两种情况下进行远程验证的绑定?

第二好:如何在它所属的对象附近显示toBeRemoteChecked的错误消息(并立即获取错误消息,而不是在提交后)

不同的想法或解决方案:欢迎。

感谢。

2 个答案:

答案 0 :(得分:3)

一个有趣的问题,与this question类似,因此我在Codeplex报告了一个问题,但尚未解决。该链接包括对jquery.validate.js文件的建议修改,它将解决此问题(它会删除前缀),但这意味着您需要在更新脚本时进行维护,因此不太理想。

一种选择是将CreateModelA更改为继承自ModelA,只需添加int valueToMap属性,以便您永远不会有前缀 - 您始终使用@Html.TextBoxFor(m => m.toBeRemoteChecked)代替@Html.TextBoxFor(m => m.modelA.toBeRemoteChecked)

此外,[Remote]仅是客户端验证,这意味着您仍需要在发布时在服务器中执行验证。所以你可以接受你没有对该属性进行客户端验证,而是在属性的POST方法中添加ModelState错误并返回视图,以便它显示在关联的ValidationMessageFor()元素

附注:您的模型具有[Key]属性的事实表明这是一个数据模型,而不是视图模型,[Remote]是一个视图特定属性。您应该使用视图模型,尤其是在编辑数据时。 (参考What is ViewModel in MVC?

答案 1 :(得分:2)

我找到了一个没有继承(并且没有视图模型)的解决方案,只需对代码进行少量更改即可解决我的绑定问题。

远程验证有两种绑定方式,您可以只传递必须远程检查的成员

public ActionResult isValid(string toBeRemoteChecked) { ... }

或者您可以传递该成员的类的实例。

public ActionResult isValid(ModelA modelA) { ... }

当然,在第二个版本中,您必须将toBeRemoteChecked替换为modelA.toBeRemoteChecked。在第二个版本中,绑定在两种情况下都有效 - 在编辑时以及在上面的上下文中创建ModelA的实例时。为了使绑定工作,远程验证方法的参数名称与CreateModelA中的成员名称匹配至关重要,在我的情况下,即modelA

如果你有一个非常复杂的模型,你可以使用bind / include初始化你想要使用的成员参数modelA,即在我的情况下我会使用

public ActionResult isValid([Bind(Include = "toBeRemoteChecked")] ModelA modelA) { ... }

默认情况下(没有Include),所有其他成员将保持为null或具有默认值 - 因此,只有在需要其他成员进行验证时才需要使用Include - 在我的情况下,省略时我也会这样做包括)