use*_*835 2 validation asp.net-mvc
我正在使用自Required继承的自定义验证requiredconditional,以有条件地需要某些字段。除非有一次,这种方法在任何地方都可以很好地工作,我无法弄清楚发生了什么。它为模型中的一个属性调用两次IsValid方法(客户端验证工作正常)。模型使用此属性具有2个属性,但只有一个存在问题。最初,我认为这是因为我的条件之一是一个复选框,并且它同时回发了已检查的值和隐藏的值,但是我尝试使用单选按钮代替,甚至使用隐藏的值,但在所有情况下都具有相同的结果。这是我的观点(简化测试):
@ModelType List(Of eLADNETBusiness.AdditionalInterest)
@Code
ViewData("Title") = "Bind Coverage Entry"
End Code
<h2>Bind Coverage Entry</h2>
@Using Html.BeginForm()
@Html.AntiForgeryToken()
@Html.Hidden("hullValue", ViewBag.HullValue)
Dim currentCount As Integer = 0
@For count As Integer = 0 To Model.Count - 1
currentCount = count
@<div class="editor-label">
@Html.LabelFor(Function(model) model(currentCount).LienholderAmount)
</div>
@<div class="editor-field">
@Html.EditorFor(Function(model) model(currentCount).LienholderAmount)
@Html.ValidationMessageFor(Function(model) model(currentCount).LienholderAmount)
</div>
@<div>
@Html.EditorFor(Function(model) model(currentCount).Lienholder90Percent)
</div>
Next
@<p>
<input type="submit" value="Continue" />
</p>
End Using
Run Code Online (Sandbox Code Playgroud)
这是我的模型(简化测试):
<DataContract()> _
Public Class AdditionalInterest
<DataMember()> _
Public Property ID As Integer = 0
<RequiredConditional("Lienholder90Percent", False, ErrorMessage:="Enter Breach of Warranty lienamount or select 90 percent of insured value")> _
<Display(Name:="Lienholder Amount")> _
<DataMember()> _
Public Property LienholderAmount As Nullable(Of Integer)
<DataMember()> _
Public Property Lienholder90Percent As Boolean
Run Code Online (Sandbox Code Playgroud)
最终班
和我所需的条件属性:
Imports System.Collections.Generic
Imports System.Linq
Imports System.ComponentModel.DataAnnotations
Imports System.Web.Mvc
Imports System.Collections
Imports System.Text
Public Class RequiredConditional
Inherits RequiredAttribute
Implements IClientValidatable
Private Property PropertyNames() As String()
Private Property DesiredValues() As Object()
Public Sub New(comparePropertyNames As String(), comparePropertyDesiredValues As Object())
PropertyNames = comparePropertyNames
DesiredValues = comparePropertyDesiredValues
End Sub
Public Sub New(comparePropertyNames As String, comparePropertyDesiredValues As Object)
PropertyNames = New String() {comparePropertyNames}
DesiredValues = New String() {comparePropertyDesiredValues}
End Sub
Protected Overrides Function IsValid(value As Object, context As ValidationContext) As ValidationResult
Dim instance As Object = context.ObjectInstance
Dim type As Type = instance.GetType()
Dim propertyvalue As Object
Dim trueConditions As Integer = 0
For count As Integer = 0 To PropertyNames.Count - 1
propertyvalue = type.GetProperty(PropertyNames(count)).GetValue(instance, Nothing)
If Not propertyvalue Is Nothing Then
If DesiredValues.Count >= count + 1 Then
If propertyvalue.ToString() = DesiredValues(count).ToString() Then
trueConditions += 1
End If
End If
End If
Next
'if all conditions are met, validate value
If trueConditions = PropertyNames.Count And trueConditions = DesiredValues.Count Then
Dim result As ValidationResult = MyBase.IsValid(value, context)
Return result
End If
Return ValidationResult.Success
End Function
Public Function GetClientValidationRules(metadata As System.Web.Mvc.ModelMetadata, context As System.Web.Mvc.ControllerContext) As System.Collections.Generic.IEnumerable(Of System.Web.Mvc.ModelClientValidationRule) _
Implements System.Web.Mvc.IClientValidatable.GetClientValidationRules
Dim results As New List(Of ModelClientValidationRule)
Dim rule = New ModelClientValidationRule With {.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()), .ValidationType = "requiredif"}
Dim depProp As String = String.Empty
Dim sbProp As New StringBuilder()
Dim sbTarget As New StringBuilder()
Dim helper As New ValidationHelper
For count As Integer = 0 To PropertyNames.Count - 1
Dim prop As String = PropertyNames(count)
depProp = helper.BuildDependentPropertyName(metadata, TryCast(context, ViewContext), prop)
sbProp.AppendFormat("|{0}", depProp)
Dim targetValue As String = String.Empty
If DesiredValues.Count >= count + 1 Then
targetValue = (If(DesiredValues(count), "")).ToString()
End If
If DesiredValues(count).GetType() = GetType(Boolean) Then
targetValue = DesiredValues(count).ToString.ToLower
End If
sbTarget.AppendFormat("|{0}", targetValue)
Next
rule.ValidationParameters.Add("dependentproperty", sbProp.ToString().TrimStart("|"))
rule.ValidationParameters.Add("targetvalue", sbTarget.ToString().TrimStart("|"))
results.Add(rule)
Return results
End Function
End Class
Run Code Online (Sandbox Code Playgroud)
因此,当我单击提交并调试到requiredconditional属性时,lienholderamount属性将两次击中IsValid。第一次命中时,Lienholder90Percent的值是False,即使在模型中它是true且在表单上是正确的(并通过了客户端验证),所以此时验证失败。然后再次命中,Lienholder90Percent为True(正确)并通过验证。但是由于它在第一个失败,所以它仍然失败并显示错误消息。您会注意到该模型是一个列表,但是出于测试目的,我只发送了一个,仍然得到相同的结果。无法弄清楚为什么仅此一个属性会发生这种情况。希望这很简单,我只是看不到。我花了整整一天的时间试图弄清楚这一点。就像我说的那样,我使用了这个属性很多并且效果很好。
从ValidationAttribute而不是RequiredAttribute继承。
在填充属性后立即调用RequiredAttribute的IsValid,而在填充整个模型后调用ValidationAttribute的IsValid(这对于更复杂的验证是有意义的)。
归档时间: |
|
查看次数: |
1309 次 |
最近记录: |