Generics and Rules : CSLA 2.1

Generics and Rules : CSLA 2.1

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


cash_pat posted on Wednesday, August 09, 2006

Hi,

I am new to to generics as i am from VB. can anyone post some examples as to how the new strongly typed rules can be implemented. Anything showing the syntax would suffice.

regards

cash pat

xal replied on Wednesday, August 09, 2006

Protected Overrides Sub AddSharedBusinessRules()
    MyBase.AddSharedBusinessRules()
    ValidationRules.AddSharedRule(Of ObjectType, RuleArgs)( _
      AddressOf RuleMethod, New RuleArgs("PropertyName")
End Sub


Private Shared Function RuleMethod( ByVal target as ObjectType, e As RuleArgs) As Boolean
    If target.mPropertyName = 2 Then
       e.Description = "Value cannot be 2"
       Return False
    End If
    Return True
End Function

I hope that does it!

Andrés

cash_pat replied on Wednesday, August 09, 2006

Another one plz. Couldn't understand that.

xal replied on Wednesday, August 09, 2006

That's pretty much the simplest example anyone could make, but let's talk about it a little bit to see if you get it...
The rule assumes that you have a property called "PropertyName" and that it exposes a private field called "mPropertyName". It also assumes that the class name for your bo is "ObjectType"
Generic methods take the types you want to specify before the argument.

So, basically what the generic method needs is to know the type of the object you're going to work with (that's the target of the rule) and the type of the argument (which must be at least RuleArgs or inherit from ruleargs).

The target is the object that is going to be validated, so ValidationRules (which is an object inside your bo) keeps a reference to the parent (your actual BO).
When you call ValidationRules.CheckRules("PropertyName"), it looks for rules that apply to that property and calls them, passing the two arguments: the target (the bo that is being validated) and the validation argument (the ruleargs).

Your rule uses the target to access the values of the bo being validated. Since the method is inside the class, it can access it's private fields. It returns true if the value is valid and, if it's not, it set's the broken rule description and returns false.

I hope that brings a little more light into the matter.

Andrés

cash_pat replied on Wednesday, August 09, 2006

Thanks Xal. Got it right this time. Hey Another small query.

Suppose I have BO. I want to apply authorization rules base on a particular property. How do i go about it. It used to work with CSLA 1.53. Any ideas??

regards

cash pat

RockfordLhotka replied on Thursday, August 10, 2006

There was no directly support for authorization in CSLA 1.x, so whatever you were doing was something of your invention. And that may still work in 2.0 - I can't speak to that.

But in CSLA .NET 2.0 I did introduce the concept of property-level authorization. The internal implementation is discussed in Chapter 3, and you can look in Chapter 8 to see how it is used in the ProjectTracker sample app.

cash_pat replied on Friday, August 11, 2006

Let me explain the problem in detail.

I have a BO called Voucher. It has a property VoucherTypeID.

Now this BO changes its behaviour according to the VoucherTypeID which can range from Contra, Journal, Sales, Purchase etc. Some Child BO collection may or may not be loaded depending on VoucherTypeID. 

In 1.53 i used to conditionally load the child objects by checking the VoucherTypeID property. Even though the child variables were there in the Voucher BO their reppective fetch was not called. Even the update was conditional

                      If Not mChildren Is Nothing Then
              mChildren.Update(tr, Me)
           End If


Now, In 2.0 the problem is different. Users have access to different Vouchers depending on the VoucherTypeID. But the problem arises from the fact that VoucherTyepID is not known beforehand because in every Factory method there is a CanReadObject(), CanGetObject before the actual Fetch. So there is no way this authorization can be done.

   Select Case VoucherTyepID

     Case VoucherTypesEnum.VoucherTypes.Contra
           If VerifyAccessLevel(ResourceType.Contra, mAccessType) Then
               Return False
           End If

     Case VoucherTypesEnum.VoucherTypes.CreditNote
             If VerifyAccessLevel(ResourceType.CreditNote, mAccessType) Then
               Return False
             End If


     Case VoucherTypesEnum.VoucherTypes.DebitNote
           If VerifyAccessLevel(ResourceType.DebitNote, mAccessType) Then
               Return False
           End If


     Case VoucherTypesEnum.VoucherTypes.Sales

          
If VerifyAccessLevel(ResourceTypeSalesmAccessType) Then
               Return False
           End If


     Case VoucherTypesEnum.VoucherTypes.Journal

            If VerifyAccessLevel(ResourceType.Contra, mAccessType) Then
               Return False
            End If

    End Case

regards

cash pat

  

xal replied on Friday, August 11, 2006

You could just throw an exception inside the dataportal if you detect that the user doesn't have the rights to get that data.
You can also make a CarGetObject() that takes the ID as parameter and then you'd use a command object to find out if the user can or can't actually get the data.
In any case, the approach of blocking the user from getting to the data by throwing an exception is perfect, because that's the only way you have to restrict that from a bo standpoint. But also, you should find a way to restrict the user from ever seeing that "unaccesible" object in a list, so that ideally he'll never reach the exception. Or if he does see it, restrict the edit button based on criteria you get from the list.

I say that because I usually show a list of things to the user so that they can pick an item to edit. You could have a method in the read only object that indicates whether you can actually edit / remove that object or not, and enable / disable toolbars / buttons so that the user will be blocked even before they can actually communicate with the bo or the database.

Andrés

Andrés

Copyright (c) Marimer LLC