CanWriteProperty location; before or after?

CanWriteProperty location; before or after?

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


ZeroCoolJr posted on Thursday, March 15, 2007

Hi Everyone,

CSLA 2.0.0

What's the use of CanWriteProperty(true) construct in every property? We presumed it meant the object consumer should not be able to change this property if readonly. Which should be the right way of thinking?

Thinking 1:
set (value as Int32)
    CanWriteProperty(True)
    if _value <> value then
       _value = value
       PropertyHasChanged()
    end if
end set

- or -

Thinking 2:
set (value as Int32)
    if _value <> value then
       CanWriteProperty(true)
       _value = value
       PropertyHasChanged()
    end if
end set

We have a case that a UI section/form will depend on user's authorisation rules and the state of the section object. For e.g.:
User A - Has full access for this section but will be readonly access after this was saved.

But our UI program flow is that this section will not close automatically but let the authorisation rules effect immediately. That is to say the buttons and other controls will automatically be disabled. This was done by relying on PropertyChanged event of the object. But here's the problem, we have a piece of code that will set some values to some of these properties after the PropertyChanged event fired. Using Thinking 1, an exception will be thrown and led the user something has broken but internally there's none. Using Thinking 2, solves the problem. But we would like to ask if this is fine or are there things that we should be aware of.

Thanks,
Win

GinoK replied on Thursday, March 15, 2007

Win,

CanWriteProperty method is tied in with the AuthorisationRules set up in your business objects which if left blank will default to allowing full access to the consumer to read or write all properties.  To control authorisation you can override the method AddAuthorizationRules and allow/deny read/write access on specific properties as appropriate. By combining this with the use on Rocky's readwriteauthorisation control the UI can be setup to display or hide data from a form based on this access. In the following example only a consumer set up in the Payroll role will have access to Salary.

The CanReadProperty and CanWriteProperty are checking access not granting access in the property functions and as such should appear as in your first sample.

Regards,

Ian K

Eg .

Protected Overrides Sub AddAuthorizationRules()

AuthorizationRules.AllowWrite("Salary", "Payroll")

AuthorizationRules.AllowRead("Salary", "Payroll")

end sub

 

 

 

 

ajj3085 replied on Thursday, March 15, 2007

Adding to GinoK's response,

The first code sample you provided is correct.  That will cause an exception thrown if an unauthorized user attempts to modified the property.  By default though, if you haven't defined write access to a property one way or the other (allowed or denied) everything is allowed.  So you need to set at least one allow or deny for the CanWriteProeprty to work.

Also, you typically use the ReadWriteAuthorication extender control to automatically disable controls bound to properties to which the user cannot write.  Together, this gives you 99% of what you need.

The final step though is handling data displayed in grids, whichs RWAuth doesn't handle.  This is relatively simple though; you look through the columns on the grid and ask each instance if the property can be changed using the CanWriteProperty method (which has an overload that doesn't throw an exception).

One final note; the overload of CanWriteProperty that you are using requires you to tag the property with a NoInlining, or CanWriteProperty will not be able to determine the property name.

HTH
Andy

ZeroCoolJr replied on Thursday, March 15, 2007

Thanks for the replies guys but it seems you completely misunderstood my question. Apologies for not being clear. Anyway here goes: Smile [:)]

Currently we're using Thinking 1 with ReadWriteAuthorization control on our UI forms and as expected it works. No problem with that.

Now here's the tricky part, some features of the form depends on the PropertyChanged of the object, as an example:

private sub _object_PropertyChanged(sender as object, e as PropertyChangedEventArgs) handles _object.PropertyChanged

if e.PropertyName = "ClientId" then
    if _object.ClientId = 0 then
        ' initialize ClientSubId to 0
        _object.ClientSubId = 0
    end if
elseif e.PropertyName = "ClientSubId" then
    if _object.ClientId = 0 then
        ' show  sub form
    end if
end if

end sub

When a user hits save, the section will change its status that would make user's access right to read-only. CSLA fires OnUnknownPropertyChanged hence the above code will run again. But since this time the user can't edit, setting _object.ClientSubId = 0 bombs.

There could be lots of ways to avoid the error but we would like to have it inside the object itself. That is using Thinking 2 logic will work.

I guess the question is, is it alright to use Thinking 2? Or is there a special reason why CanWriteProperty() is positioned before the condition? Is there a difference?


Thanks,
Win

GinoK replied on Friday, March 16, 2007

Win,

Based on the fact that the CanWriteProperty() role is to establish whether or not the consumer has access write a property from  a previously established authorisation list,  its position in both your samples will have the same affect. If the user doesn't have access, the method will throw an exception either way.

The only rule one needs to follow is that you call the CanWriteProperty method before the property procedure attempts to overwrite the old value.

In reality I expect your second sample would actually be preferable as the comparison statement on the oldvalue to new value would probably be more efficient than  the calling the CanWriteProperty() needlessly when the property is not going to be changed. 

My understanding is the CanWriteProperty() and CanReadProperty() are set up to provide an standardised way of  providing security on an object.  I follow Rocky's procedures in calling the property immediately after the set or get statements as it prevents me from overlooking security in a given procedure when I do care about the access. 

 

ajj3085 replied on Friday, March 16, 2007

Win,

The solution is to set the value via the field, not the property.  Then call ValidationRules.CheckRules if need be.

Copyright (c) Marimer LLC