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
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.
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
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.
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.
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.
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