CanWriteProperty and CanReadProperty - Where?

CanWriteProperty and CanReadProperty - Where?

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


mikemir8 posted on Thursday, July 17, 2008

Hi all,
This question was already posted in this thread: http://forums.lhotka.net/forums/post/13181.aspx. But there were not many answers, I hope I have more luck.

The setter of a property usually looks like this:

            [MethodImpl(MethodImplOptions.NoInlining)]
            set {
                CanWriteProperty(true);
                if (!_description.Equals(value)) {
                    _description = value;
                    PropertyHasChanged();
                }
            }

If one were to move the call to CanWriteProperty like the following, would that have any negative implications?

            [MethodImpl(MethodImplOptions.NoInlining)]
            set {
                if (!_description.Equals(value)) {
                     CanWriteProperty(true);
                     _description = value;
                    PropertyHasChanged();
                }
            }

There are basically two reason it occured to me to do it this way. One is performace: If the property hasn't changed, you can avoid the penalty hit of using CanWriteProperty. The second has to do with data binding. Right now I'm working on a web projecte where certain users don't have access to a specific property, and DataMapper still tries to set the value in that property (even if the field was disabled and thus wasn't changed) and an exception is thrown.

Is there any reason not to do this?

Thanks,
- Miguel


nermin replied on Thursday, July 17, 2008

But then you are not performing your authorization at the beginning of the “set” block – actually not performing it at all  and although user is trying to set the property (though with the same value), there is no Authorization exception.  To me that makes it harder to test. 

 

I guess the question becomes whether to you authorization is limiting access to the set block of the property, or authorization is preventing the change of the underlying field.

 

I personally want my authorization rule to fire each time I am trying to set the value to the property.  I am curious though what would Rocky and others say about this.

 

Nermin

 

From: mikemir8 [mailto:cslanet@lhotka.net]
Sent: Thursday, July 17, 2008 4:57 PM
To: Nermin Dibek
Subject: [CSLA .NET] CanWriteProperty and CanReadProperty - Where?

 

Hi all,
This question was already posted in this thread: http://forums.lhotka.net/forums/post/13181.aspx. But there were not many answers, I hope I have more luck.

The setter of a property usually looks like this:

            [MethodImpl(MethodImplOptions.NoInlining)]
            set {
                CanWriteProperty(true);
                if (!_description.Equals(value)) {
                    _description = value;
                    PropertyHasChanged();
                }
            }

If one were to move the call to CanWriteProperty like the following, would that have any negative implications?

            [MethodImpl(MethodImplOptions.NoInlining)]
            set {
                if (!_description.Equals(value)) {
                     CanWriteProperty(true);
                     _description = value;
                    PropertyHasChanged();
                }
            }

There are basically two reason it occured to me to do it this way. One is performace: If the property hasn't changed, you can avoid the penalty hit of using CanWriteProperty. The second has to do with data binding. Right now I'm working on a web projecte where certain users don't have access to a specific property, and DataMapper still tries to set the value in that property (even if the field was disabled and thus wasn't changed) and an exception is thrown.

Is there any reason not to do this?

Thanks,
- Miguel




RockfordLhotka replied on Thursday, July 17, 2008

I think Nermin is correct, while this will work it could make testing harder. Especially in the case you describe where the value may or may not be different, so the user may or may not get an exception in different cases - that could be quite confusing.

Also, if you are worried about performance, you should switch to the overload where you provide the explicit property name. The authorization results are cached after they are first calculated, but you pay the cost of finding the property name every time when using the overload in your code.

mikemir8 replied on Friday, July 18, 2008

I'm curious then to know how others are handling the issue I describe.

Here are more details. I have a editable root list (StationList) containing Station objects. Admin users can edit all the properties in the Station objects, while regular users can only update the IsActive property. I'm binding this list to a GridView in a Asp .Net project through a CslaDataSource. In edit mode, the Enabled property of the textboxes is databound to the result of CanWriteProperty, so that regular user will only have one field enabled and the rest disabled.

In the DataSource_UpdateObject event, I'm pushing the values to the object using DataMapper. But DataMapper also tries to set values on properties even if CanWriteProperty is false for a certain property and even if the value didn't change.

So here are the alternatives I see:
* Move the position of CanWriteProperty inside the setter. Already discussed here.
* Change DataMapper so that it either checks for CanWriteProperty or for a changed value. It requires messing with the a Csla class, which I don't like. Besides it could introduce other types of confusion while testing.
* Call DataMapper.Map with the suppressExceptions set to true. The exceptions are still generated so performance wise is not a good idea, besides you can allow other types of exceptions to go unnoticed.
* Create a list of properties to ignore. The work involved seems to defeat the purpose of using DataMapper.

Any ideas?

- Miguel

nermin replied on Friday, July 18, 2008

The way I was handling cases like that was to add an override in your business object to CanWritePropert()

Inside of it check if the property name is “IsActive”.  This is allowed for all roles and in that case you return base.CanWriteProperty().

 

Then bellow that you simply check if user is in Admin role  and base.CanWriteProperty() returns true.  If both of those conditions are true, you allow writing to the property.  Otherwise your CanWriteProperty() override returns false.

 

To me that is the simplest way to implement that business rule.

 

Nermin

 

From: mikemir8 [mailto:cslanet@lhotka.net]
Sent: Friday, July 18, 2008 11:48 AM
To: Nermin Dibek
Subject: Re: [CSLA .NET] RE: CanWriteProperty and CanReadProperty - Where?

 

I'm curious then to know how others are handling the issue I describe.

Here are more details. I have a editable root list (StationList) containing Station objects. Admin users can edit all the properties in the Station objects, while regular users can only update the IsActive property. I'm binding this list to a GridView in a Asp .Net project through a CslaDataSource. In edit mode, the Enabled property of the textboxes is databound to the result of CanWriteProperty, so that regular user will only have one field enabled and the rest disabled.

In the DataSource_UpdateObject event, I'm pushing the values to the object using DataMapper. But DataMapper also tries to set values on properties even if CanWriteProperty is false for a certain property and even if the value didn't change.

So here are the alternatives I see:
* Move the position of CanWriteProperty inside the setter. Already discussed here.
* Change DataMapper so that it either checks for CanWriteProperty or for a changed value. It requires messing with the a Csla class, which I don't like. Besides it could introduce other types of confusion while testing.
* Call DataMapper.Map with the suppressExceptions set to true. The exceptions are still generated so performance wise is not a good idea, besides you can allow other types of exceptions to go unnoticed.
* Create a list of properties to ignore. The work involved seems to defeat the purpose of using DataMapper.

Any ideas?

- Miguel


mikemir8 replied on Friday, July 18, 2008

My question is not how to setup the authorization rules. I have that setup correctly (I'm using AddAuthorizationRules, by the way, instead of what you propose).

My doubt is how to prevent DataMapper from failing when it tries to set a (non-changed) value on a property that is not available to the current user.

- Miguel

mikemir8 replied on Monday, July 21, 2008

Any ideas anyone?

rsbaker0 replied on Monday, July 21, 2008

I don't use the DataMapper but instead an ORM, and load the data directly into the backing fields rather than through properties. I'm not sure if loading using the backing fields is an option for you, but it avoids both execution of authorization and business rules when objects are being initially populated.

RockfordLhotka replied on Monday, July 21, 2008

Your best bet might be to alter DataMapper to only set values that have changed.

In other words, have DataMapper read the current value from the property, compare it to the new value, and only try to set the property if they are different.

This would avoid the exception in the normal case, but would throw an exception if the UI did accidentally allow the user to change a value they shouldn't be able to change (and so would make testing possible).

This is probably a good idea for the wish list for DataMapper actually.

RockfordLhotka replied on Monday, July 21, 2008

rsbaker0:

I don't use the DataMapper but instead an ORM, and load the data directly into the backing fields rather than through properties. I'm not sure if loading using the backing fields is an option for you, but it avoids both execution of authorization and business rules when objects are being initially populated.

That would be true for loading data from the database. But surely you don't use an ORM to copy values from a web page postback into your object?

This is a case where you would want the business logic to run, because you wouldn't want to automatically trust the data coming from the UI.

mikemir8 replied on Monday, July 21, 2008

Ok, I'll go the route of changing the DataMapper. It would be nice to have this feature added on a future release.

Thanks Rocky!

RockfordLhotka replied on Monday, July 21, 2008

I did add it to the wish list.

 

I think it would have to be an option, because you wouldn’t always want it to do that check, but it would be a good option.

 

Rocky

 

From: mikemir8 [mailto:cslanet@lhotka.net]
Sent: Monday, July 21, 2008 12:37 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] RE: RE: CanWriteProperty and CanReadProperty - Where?

 

Ok, I'll go the route of changing the DataMapper. It would be nice to have this feature added on a future release.

Thanks Rocky!


Copyright (c) Marimer LLC