Reject Changes to Child Collection

Reject Changes to Child Collection

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


jpmir posted on Wednesday, June 01, 2011

Hi,

How can I reject changes made to a child list based on status of a parent object?

I have a Root object like this:

    <Serializable()> _
    Partial Public Class Contrato
        Inherits BusinessBase(Of Contrato)
        ...

        (Some properties Here including ContratoId Of Type System.Int64 (primary key) and TipoContratoId of Type System.Int32)

        Then a Child member property like this:

        Private Shared ReadOnly _CuotasMemberProperty As PropertyInfo(Of CuotaList) =
                      RegisterProperty(Of CuotaList)(Function(p As Contrato) p.Cuotas,
                      Csla.RelationshipTypes.Child)

        Public ReadOnly Property Cuotas() As CuotaList
            Get
                Dim cancel As Boolean = False
                OnChildLoading(_CuotasMemberProperty, cancel)
                If Not cancel Then
                    If Not (FieldManager.FieldExists(_CuotasMemberProperty)) Then
                        Dim criteria As New MultiCob.Business.CuotaCriteria()
                        criteria.ContratoId = ContratoId
                        If (Not MultiCob.Business.CuotaList.Exists(criteria)) Then
                            LoadProperty(_CuotasMemberProperty, MultiCob.Business.CuotaList.NewList())
                        Else
                            LoadProperty(_CuotasMemberProperty,  
                                                     MultiCob.Business.CuotaList.GetByContratoId(ContratoId))
                        End If
                    End If
                End If
                Return GetProperty(_CuotasMemberProperty) 
            End Get

        End Property
         ...

    End Class

 

How could I prevent changes made to "Cuotas" based on Current "TipoContratoId" value ?

Regards,

JP

RockfordLhotka replied on Wednesday, June 01, 2011

There are two things to consider.

First, validation doesn't prevent things from happening. Validation reports that a change was invalid. So you could maybe solve your problem by using a validation rule that marks the child object's property as invalid based on the value of the parent object's property.

Second, authorization can prevent things from happening. An authorization rule can dynamically make a property read-only. So you could maybe solve your problem by attaching an authorization rule to the child property's CanWrite action that disables writing to the property based on the value of the parent object's property.

Either of these rules would go into the editable child contained by the CuotaList collection.

jpmir replied on Wednesday, June 01, 2011

Hi Rocky,

Thank you for your time. I'll go with the second option, this is the right path... 

But, I'm still confused about how this should be implemented. You said:

"... you could maybe solve your problem by attaching an authorization rule to the child property's CanWrite action..."

And that makes me think that I Should :

1.- Create a new class inheriting AuthorizationRule

2.- Implement Execute Method to check for TipoContratoId property value and set HasPermission value accordingly.

3.- Attach a new instance of this Validation rule to my object "Contrato" like this (?) :

             BusinessRules.AddRule(New ContratoPuedeEditarCuotasAuthorizationRule(_CuotasMemberProperty) 
             Note:  ContratoPuedeEditarCuotasAuthorizationRule's constructor calls Base constructor like this:

 

                              Public Sub New(ByVal CuotasProperty As IPropertyInfo)
                                  MyBase.New(AuthorizationActions.WriteProperty, CuotasProperty)
                              End Sub

 

I've tried this before (and I will do it again if required) with no success. My custom authorization rules never gets invoked.

I'm I doing something wrong?

Now,  the last line in your post you said:

"Either of these rules would go into the editable child contained by the CuotaList collection"

That's killing me... Do you mean that my custom AuthorizationRule should be attached to the ChildItem Object? (In this case "Cuota")

If so, how could I get the parent object's TipoContratoId property value in this context?

Thanks in advance!

JP

RockfordLhotka replied on Wednesday, June 01, 2011

Something like this:

    private class CheckTipoContract : Csla.Rules.AuthorizationRule
    {
      protected override void Execute(Csla.Rules.AuthorizationContext context)
      {
        var target = (ProjectResourceEdit)context.Target;
        var parent = (ProjectEdit)((ProjectResources)target.Parent).Parent;
        if (parent.TipoContratold == 0)
          context.HasPermission = false;
        else
          context.HasPermission = true;
      }
    }

This rule is in an editable child class. Notice how it sets the parent field by getting the Parent of its Parent. The immediate parent is a list, and the parent we want is the parent of the list. I think this is your scenario?

jpmir replied on Wednesday, June 01, 2011

Cool!

That's working fine, and now I realize what you were trying to acomplish. Even so, it doesn't fit perfectly into what I want to do since I need the whole collection of child items to be readonly based on this authorization rule, not just some child item's property.

Could you please point me the direction to do it?

I really appreciate your support, thanks again.

Jean Paul

RockfordLhotka replied on Wednesday, June 01, 2011

The way to make a collection "read-only" is to override the methods that occur in response to insert/move/clear/remove and to throw exceptions when they occur. But that doesn't prevent editing of existing child objects - for that you need those child objects to block editing of all their properties (like in my previous couple posts).

jpmir replied on Wednesday, June 01, 2011

Yes!!!, that should work.

Thank you very much!

Copyright (c) Marimer LLC