Generics and Rules : CSLA 2.1Generics 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éscash_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