.net MVC3有条件地验证依赖于父对象属性的属性
我有以下ViewModel:.net MVC3有条件地验证依赖于父对象属性的属性,.net,asp.net-mvc-3,validation,.net,Asp.net Mvc 3,Validation,我有以下ViewModel: public class StayDetails { public int NumberOfRooms { get; set; } public IList<RoomDetail> Rooms { get;set; } } public class RoomDetail { public int RoomNumber { get; set; } [MinIfRoomRequired("StayDetails.Numbe
public class StayDetails
{
public int NumberOfRooms { get; set; }
public IList<RoomDetail> Rooms { get;set; }
}
public class RoomDetail
{
public int RoomNumber { get; set; }
[MinIfRoomRequired("StayDetails.NumberOfRooms", "RoomNumber", 1]
public int NumberOfAdults { get;set; }
}
我遇到的问题是无法访问NumberOfRooms属性,validationContext.ObjectInstance没有任何对父对象的引用。我考虑在对象初始化期间将对StayDetails对象的引用添加到RoomDetails对象上,这样我就可以从那里引用属性,但是模型绑定不允许这样做,因为RoomDetail对象没有无参数构造函数
有什么建议吗
非常感谢,David您可以尝试使用FluentValidation进行验证。
写得少做得多…您应该在
StateDetails类
上定义验证注释,而不是RoomDetail。通过这种方式,您将获得所有值、NumberOfRooms、房间列表及其各自的RoomNumber和NumberOfOfOf。相应地更改您的验证器。我能够通过使用自定义绑定解决此问题。您需要添加一个属性以引用回父对象,例如NumberOfRooms。在我的例子中,我实际上创建了一个委托,它引用回父对象中的例程。为我在stackoverflow中遇到的VB代码和格式问题提前道歉
Public Class RoomDetail_Binder
Inherits DefaultModelBinder
Protected Overrides Function CreateModel(controllerContext As ControllerContext, bindingContext As ModelBindingContext, modelType As Type) As Object
Dim theObj As Quote_Equipment_Model = MyBase.CreateModel(controllerContext, bindingContext, modelType)
Dim theParent As StayDetails= controllerContext.HttpContext.Items("StayDetails")
If Not IsNothing(theParent) Then
theObj.NumberOfRooms=theParent.NumberOfRooms
End If
Return theObj
End Function
Protected Overrides Sub OnModelUpdated(controllerContext As ControllerContext, bindingContext As ModelBindingContext)
MyBase.OnModelUpdated(controllerContext, bindingContext)
Dim theMetadataList As List(Of MetaDataPair)
If Not controllerContext.HttpContext.Items.Contains("MetadataList") Then
theMetadataList = New List(Of MetaDataPair)
controllerContext.HttpContext.Items.Add("MetadataList", theMetadataList)
Else
theMetadataList = controllerContext.HttpContext.Items("MetadataList")
End If
theMetadataList.Add(New MetaDataPair With {.Metadata = bindingContext.ModelMetadata, .BindingModelName = bindingContext.ModelName})
End Sub
End Class
请注意,MetadataList只是
Public Class MetaDataPair
Public Property BindingModelName As String
Public Property Metadata As ModelMetadata
End Class
Protected Overrides Function CreateModel(controllerContext As ControllerContext, bindingContext As ModelBindingContext, modelType As Type) As Object
Dim theObj As StayDetails = MyBase.CreateModel(controllerContext, bindingContext, modelType)
controllerContext.HttpContext.Items("StayDetails") = theObj
Return theObj
End Function
Public Overrides Function BindModel(controllerContext As ControllerContext, bindingContext As ModelBindingContext) As Object
Dim theObj As StayDetails = MyBase.BindModel(controllerContext, bindingContext)
Dim theMetadataList As List(Of MetaDataPair) = CType(controllerContext.HttpContext.Items("MetadataList"), List(Of MetaDataPair))
For Each Metadata In theMetadataList
For Each result As ModelValidationResult In ModelValidator.GetModelValidator(Metadata.Metadata, controllerContext).Validate(Nothing)
Dim key As String = CreateSubPropertyName(Metadata.BindingModelName, result.MemberName)
If Not bindingContext.ModelState(key).Errors.Any(Function(ent) ent.ErrorMessage = result.Message) Then
bindingContext.ModelState.AddModelError(key, result.Message)
End If
Next
Next
Return theObj
End Function
末级为了确认,我将从RoomDetail对象的NumberOfMandactors字段中删除验证,并在可以执行所需逻辑时向Rooms属性添加自定义验证程序,是否会对RoomDetail属性执行任何验证?因为我们没有将“IList Rooms”标记为[必需],如果房间属性为空,则不会验证它。但它将对Rooms集合中列出的所有RoomDetail对象执行验证。是的,它将验证所有可用对象的RoomDetail属性。嗨,Priyank,那太好了,我现在有了更好的理解。
Protected Overrides Function CreateModel(controllerContext As ControllerContext, bindingContext As ModelBindingContext, modelType As Type) As Object
Dim theObj As StayDetails = MyBase.CreateModel(controllerContext, bindingContext, modelType)
controllerContext.HttpContext.Items("StayDetails") = theObj
Return theObj
End Function
Public Overrides Function BindModel(controllerContext As ControllerContext, bindingContext As ModelBindingContext) As Object
Dim theObj As StayDetails = MyBase.BindModel(controllerContext, bindingContext)
Dim theMetadataList As List(Of MetaDataPair) = CType(controllerContext.HttpContext.Items("MetadataList"), List(Of MetaDataPair))
For Each Metadata In theMetadataList
For Each result As ModelValidationResult In ModelValidator.GetModelValidator(Metadata.Metadata, controllerContext).Validate(Nothing)
Dim key As String = CreateSubPropertyName(Metadata.BindingModelName, result.MemberName)
If Not bindingContext.ModelState(key).Errors.Any(Function(ent) ent.ErrorMessage = result.Message) Then
bindingContext.ModelState.AddModelError(key, result.Message)
End If
Next
Next
Return theObj
End Function