C# 带有远程验证的ASP.NET MVC绑定
我有一个模型C# 带有远程验证的ASP.NET MVC绑定,c#,asp.net,asp.net-mvc,validation,asp.net-mvc-4,C#,Asp.net,Asp.net Mvc,Validation,Asp.net Mvc 4,我有一个模型ModelA,其中一个成员toBeRemoteChecked,还有一个模型MapToA,其中一个成员valueToMap。每当我创建ModelA的实例时,我还需要MapToA的实例,因此我有一个模型CreateModelA,其中包括一个成员ModelA和一个成员valueToMap。提交表单时,我将modelA添加到数据库表modelA,并创建一个实例并将其添加到MapToA,该实例由modelA的id和valueToMap组成。在代码方面 public class ModelA {
ModelA
,其中一个成员toBeRemoteChecked
,还有一个模型MapToA
,其中一个成员valueToMap
。每当我创建ModelA
的实例时,我还需要MapToA
的实例,因此我有一个模型CreateModelA
,其中包括一个成员ModelA
和一个成员valueToMap
。提交表单时,我将modelA
添加到数据库表modelA
,并创建一个实例并将其添加到MapToA
,该实例由modelA
的id和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
的实例时,MapToA
中的值无关紧要(而且在大多数情况下,MapToA
的多个实例具有相同的ModelA
id),但是toBeRemoteChecked
的远程验证仍然很重要
我的问题:验证方法的绑定:
public ActionResult isValid(string toBeRemoteChecked) { ... }
如果我保持原样,它在编辑ModelA
时起作用,但在通过CreateModelA
创建ModelA
时不起作用(我总是在toBeRemoteChecked
中得到空值)。当我使用BindPrefix时
public ActionResult isValid([Bind(Prefix = "modelA.toBeRemoteChecked")] string toBeRemoteChecked) { ... }
当我创建一个ModelA
时,它正在工作,但当我编辑它时,它就不工作了
当我试图通过添加来更改Create.cshtml中的“name”时@Name=“toBeRemoteChecked”…
(而不是由HTML助手创建的modelA.toBeRemoteChecked
)在@HTML.TextBoxFor
的htmlAttributes中,则验证正在工作,但值与表的绑定丢失,并且在将值保存到数据库时出现错误(空值)
那么,如何实现用于创建和编辑的不同绑定呢
到目前为止,我的解决方法是使ModelA
和CreateModelA
:IValidatableObject
并在我的public IEnumerable Validate(ValidationContext ValidationContext)
方法中检查成员以进行远程检查。但是,它会在表单顶部显示错误消息,而不是在TextFor框的位置
所以:最佳解决方案:如何进行远程验证在这两种情况下都有效的绑定
次优:如何在所属对象附近显示IValidatableObject
的错误消息(并立即获取错误消息,而不是在提交后)
不同的想法或解决方案:欢迎
谢谢。这是一个有趣的问题,与之类似,因此我在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]
是一个特定于视图的属性。您应该使用视图模型,尤其是在编辑数据时。(请参阅)我找到了一个不带继承(也不带视图模型)的解决方案,它只需对代码进行少许更改即可解决绑定问题
远程验证有两种绑定方式,您可以只传递必须进行远程检查的成员
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),所有其他成员都将保持空值或具有默认值-因此,仅当您也需要其他成员进行验证时,才需要使用Include-在我的情况下,如果省略Include,我也会使用相同的值)谢谢。至于客户端验证,我尝试了inherit选项-也让一个演示项目工作,但是当我db.ModelAset.Add(createModelA)
时,我要么会自动在数据库中添加不需要的额外列,要么在我手动从数据库中删除这些列后,我会得到一个无效列名
错误。当我在控制器中手动创建modelA
时,我可以db.ModelAset.Add(modelA)
,方法是将所有必需的成员从createModelA
复制到modelA
。这有捷径吗?(我的真实模型大约有20名成员,所以这是可能的,但不是很好)。谢谢。你需要再次阅读我的最后一段:)视图模型与数据库没有关系。确定。因此,在移动da时,我需要额外的努力