System.InvalidOperationException

System.InvalidOperationException

Old forum URL: forums.lhotka.net/forums/t/3321.aspx


bassplayer posted on Friday, August 03, 2007


I'm currently using the 2.0 of CSLA (VB.NET) and when I have the following Validation Rule:

    Protected Overrides Sub AddBusinessRules()

        ValidationRules.AddRule( _
            AddressOf Validation.CommonRules.StringRequired, "DisplaySort")
        ValidationRules.AddRule( _
            AddressOf Validation.CommonRules.StringMaxLength, _
            New CommonRules.MaxLengthRuleArgs("DisplaySort", 4))
        ValidationRules.AddRule(AddressOf NoDuplicates, "DisplaySort")

    End Sub

    Private Function NoDuplicates(ByVal target As System.Object, _
        ByVal e As RuleArgs) As Boolean

        Dim parent As Units = CType(Me.Parent, Units)
        For Each item As Unit In parent
            If item.DisplaySort = _displaySort AndAlso Not ReferenceEquals(item, Me) Then
                e.Description = "Display Sequence must be unique"
                Return False
            End If
        Next
        Return True

    End Function

This is similar to the Role.vp example in the ProjectTracker20vb project:

    Protected Overrides Sub AddBusinessRules()

      ValidationRules.AddRule( _
        AddressOf Csla.Validation.CommonRules.StringRequired, "Name")
      ValidationRules.AddRule(AddressOf NoDuplicates, "Id")

    End Sub

    Private Function NoDuplicates(ByVal target As Object, _
      ByVal e As Csla.Validation.RuleArgs) As Boolean

      Dim parent As Roles = CType(Me.Parent, Roles)
      For Each item As Role In parent
        If item.Id = mId AndAlso Not ReferenceEquals(item, Me) Then
          e.Description = "Role Id must be unique"
          Return False
        End If
      Next
      Return True

    End Function

Now, in order to have this called, I had to add the following to the New() method:


    Private Sub New()

        MarkAsChild()
        ValidationRules.CheckRules()

    End Sub


I notice the method ValidationRules.CheckRules() was NOT called in the Role.vb file, thus was never called.

The exception I'm getting is:

System.InvalidOperationException was unhandled
  Message="An error occurred creating the form. See Exception.InnerException for details.
           The error is: DataPortal.Fetch failed (System.InvalidOperationException:
           Invalid rule method (instance methods of the target object not allowed):
           NoDuplicates\r\n   at Csla.Validation.ValidationRules.ValidateHandler(MethodInfo method) in
           D:\\cad911\\CSLA20VB\\Csla\\Validation\\ValidationRules.vb:line 593\r\n  
           at Csla.Validation.ValidationRules.ValidateHandler(RuleHandler handler) in
           D:\\cad911\\CSLA20VB\\Csla\\Validation\\ValidationRules.vb:line 580\r\n
           at Csla.Validation.ValidationRules.AddRule(RuleHandler handler, String propertyName) in
           D:\\cad911\\CSLA20VB\\Csla\\Validation\\ValidationRules.vb:line 389\r\n

What I need to do is check the make sure there are no duplicate entries for my business object.  I need the ErrorProvider to turn on when there is a duplicate on my WinForm.  What am I doing wrong?

When the user is presented with a blank form that is databound to this business object, I want this check to happen when the user types in a value in the field and then tabs to the next field.




RockfordLhotka replied on Saturday, August 04, 2007

You shouldn't call ValidationRules methods in the constructor of your class - that's too early.

If you want a new object to start out validated, make the call in DataPortal_Create():

<RunLocal()> _
Private Overloads Sub DataPortal_Create()
  ValidationRules.CheckRules()
End Sub

 

bassplayer replied on Monday, August 06, 2007


Okay.   I changed it to do this:

#Region " Factory Methods "

    Public Shared Function NewUnit() As Unit

        'Return New Unit
        Return DataPortal.Create(Of Unit)()

    End Function

    Friend Shared Function GetUnit(ByVal dr As Csla.Data.SafeDataReader) As Unit

        Return New Unit(dr)

    End Function

    Private Sub New()

        'MarkAsChild()

    End Sub

    Private Sub New(ByVal dr As Csla.Data.SafeDataReader)

        MarkAsChild()
        Fetch(dr)

    End Sub

#End Region

#Region " Data Access "

    <RunLocal()> _
    Protected Overrides Sub DataPortal_Create()

        MarkAsChild()
        ValidationRules.CheckRules()

    End Sub


And I still get the System.InvalidOperationException.  I modeled this way after the Project.vb example in ProjectTracker20vb:

#Region " Factory Methods "

  Public Shared Function NewProject() As Project

    If Not CanAddObject() Then
      Throw New System.Security.SecurityException( _
        "User not authorized to add a project")
    End If
    Return DataPortal.Create(Of Project)()

  End Function


  <RunLocal()> _
  Protected Overrides Sub DataPortal_Create()

    mId = Guid.NewGuid
    Started = CStr(Today)
    ValidationRules.CheckRules()

  End Sub


What I don't understand is that either it the ValidationRules.CheckRules() being called in the constructor or being called in the DataPortal_Create(), its still being called when the object is created.



RockfordLhotka replied on Monday, August 06, 2007

It is true that the constructor and DP_C() are invoked when the object is created, but they occur at different times in the process.

 

Obviously the constructor is first, by definition.

 

Then a bunch of initialization occurs.

 

Then DP_C() is invoked.

 

Calling ValidationRules.CheckRules() before that initialization is the problem.

 

Rocky

 

Copyright (c) Marimer LLC