CanWriteProperty if values are not changedCanWriteProperty if values are not changed
Old forum URL: forums.lhotka.net/forums/t/5526.aspx
detritus posted on Friday, October 03, 2008
I'm having a difficulty understanding why CanWriteProperty is checked at all if the new value is same as the old one. In the end nothing will happen so why bother?
I'm having this problem in ASP.NET Mvc, where we need to write a ModelBinder class that basically maps properties from form posted dictionary to the BO itself (There is no data-binding there). If the user does not have permission to modify a property, it will return as it was (this part is also manual) and ModelBinder wil try to set same value to the BO which is fine because it's the same value anyway, but CanWriteProperty is called even if the new value is same as the old one and returns an error.
I think I can write a helper method in the base class to write the new value to the property only if it's different but it seems this should be the default behaviour.
Sinan
sergeyb replied on Friday, October 03, 2008
I think there were a few threads in the past with the same
question. INMO, if a user is not allowed to set a property, he/she should
not get to the point where SetProperty is fired, and if he does, then
security exception should be thrown regardless what new value is.
Sergey Barskiy
Principal Consultant
office: 678.405.0687 |
mobile: 404.388.1899
Microsoft Worldwide Partner of the Year | Custom
Development Solutions, Technical Innovation
From: detritus
[mailto:cslanet@lhotka.net]
Sent: Friday, October 03, 2008 5:38 PM
To: Sergey Barskiy
Subject: [CSLA .NET] CanWriteProperty if values are not changed
I'm having a difficulty understanding why CanWriteProperty
is checked at all if the new value is same as the old one. In the end nothing
will happen so why bother?
I'm having this problem in ASP.NET Mvc, where we need to write a ModelBinder
class that basically maps properties from form posted dictionary to the BO
itself (There is no data-binding there). If the user does not have permission
to modify a property, it will return as it was (this part is also manual) and
ModelBinder wil try to set same value to the BO which is fine because it's the
same value anyway, but CanWriteProperty is called even if the new value is same
as the old one and returns an error.
I think I can write a helper method in the base class to write the new value to
the property only if it's different but it seems this should be the default
behaviour.
Sinan
detritus replied on Friday, October 03, 2008
You're right, and they don't get to that point. Only this is in asp.net mvc and there is no data-binding, with manual effort you don't let users to change those boxes you assume bound to the properties, and after they're done and submit the form, you get a dictionary of properties and their values which should be written to the BO (manual data-binding if you will).
Now in this mapping method (IModelBinder implementation), I should not need to check for every property "again" to see if the user authorized to write when in fact user did not change the value anyway.
I did try to make a helper method to accomplish this like SetChangedProperty but it seems most of the fields, methods I need is either internal or private, ended up having a very ugly looking if clause for every property set statement.
Did anybody implement a IModelBinder interface with authorization in mind?
Sinan
sergeyb replied on Friday, October 03, 2008
I see. You could you CanWriteProperty method. Would
this work?
Sergey Barskiy
Principal Consultant
office: 678.405.0687 |
mobile: 404.388.1899
Microsoft Worldwide Partner of the Year | Custom
Development Solutions, Technical Innovation
From: detritus
[mailto:cslanet@lhotka.net]
Sent: Friday, October 03, 2008 6:12 PM
To: Sergey Barskiy
Subject: Re: [CSLA .NET] RE: CanWriteProperty if values are not changed
You're right, and they don't get to that point. Only this is
in asp.net mvc and there is no data-binding, with manual effort you don't let
users to change those boxes you assume bound to the properties, and after
they're done and submit the form, you get a dictionary of properties and their
values which should be written to the BO (manual data-binding if you will).
Now in this mapping method (IModelBinder implementation), I should not need to
check for every property "again" to see if the user authorized to
write when in fact user did not change the value anyway.
I did try to make a helper method to accomplish this like SetChangedProperty
but it seems most of the fields, methods I need is either internal or private,
ended up having a very ugly looking if clause for every property set statement.
Did anybody implement a IModelBinder interface with authorization in mind?
Sinan
detritus replied on Friday, October 03, 2008
If you mean I can override it, I don't think that will help, because I would need the old and new values to decide.
Sinan
sergeyb replied on Friday, October 03, 2008
Seems like the only suggestion is to have a custom property
setter instead of just SetProperty. You can do value checking, then call
SetProperty. That might be a lot of work for you though.
Sergey Barskiy
Principal Consultant
office: 678.405.0687 |
mobile: 404.388.1899
Microsoft Worldwide Partner of the Year | Custom
Development Solutions, Technical Innovation
From: detritus
[mailto:cslanet@lhotka.net]
Sent: Friday, October 03, 2008 8:58 PM
To: Sergey Barskiy
Subject: Re: [CSLA .NET] RE: RE: CanWriteProperty if values are not
changed
If you mean I can override it, I don't think that will help,
because I would need the old and new values to decide.
Sinan
detritus replied on Saturday, October 04, 2008
Other than writing that custom setter inside Csla project (which I don't want to do), I couldn't find a way to implement it (other than using reflection) in my library project (which cannot access the internals of Csla). In general practice, even the registered properties are private which makes the custom setter method in the base class not usable from outside (like from modelbinder in Web project).
Anyway, I'm going to try rasupit's idea to see how it goes.
Thanks,
Sinan
rasupit replied on Friday, October 03, 2008
I'm kinda in agreement with Sergey that you should consistently throw an exception on a write attempt made to property that is not permitted. This will actually give better experience to user so that user does not need to enter value to a field in order to find out that they don't have write permission. Of course the field should be disable to let user know that the field is not for editing.
Here is an example how to disable a text box in MVC by checking the CanWriteProperty:
Html.TextBox("Name", new {disabled=ViewData.Model.CanWriteProperty("Name", false) ? "disabled": ""})
In ModelBinder, the IModelBinder.GetValue method will return null value when the form element is disabled. Therefore you can avoid assigning value to this property when the return value is null.
Ricky
detritus replied on Saturday, October 04, 2008
That might be a good idea assuming I won't have properties that use null as a valid value. We use ExtJs, so we cannot use Html.TextBox but propably same thing could be done there.
Thanks for the tought,
Sinan
rasupit replied on Saturday, October 04, 2008
detritus: That might be a good idea assuming I won't have properties that use null as a valid value.
The value I was referring to is the value from form element; These values are all value types therefore null is an invalid value.
However unless you write your own custom binder, which I suspect you do (because you asked if any body has implement IModelBinder), you don't have to worry about this. This is how the UpdateModel or TryUpdateModel do internally therefore you'll experience this behavior when you use any of these methods to bind your object.
Ricky
detritus replied on Saturday, October 04, 2008
Thanks Ricky,
There is a problem with nullable types though, for example if the property is DateTime?, default Mvc binders returns (correctly of course) null when in fact posted value is empty string. If I disable the textbox I get back null again.
To differentiate between them I decided to check the posted dictionary keys to see if the property is in the list at all before looking its value (using default binders).
Seems working now, thanks a lot for your help.
Sinan
Copyright (c) Marimer LLC