CanWriteProperty if values are not changed

CanWriteProperty 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

cid:_2_0648EA840648E85C001BBCB886257279
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

cid:_2_0648EA840648E85C001BBCB886257279
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

cid:_2_0648EA840648E85C001BBCB886257279
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