Closed alexis-y closed 8 years ago
@alexis-y, thanks for your detailed information. Is this workaround acceptable to you?
It is a workable solution. It has moved me to develop and publish (internally) a client assembly with the fixed classes, and just instruct users of my service to use that instead of the ASR dialog. It's a little more involved, but that's fine.
We also meet this issue in Microsoft Intune service, after did some investigation I think the issue is in ClientPropertyAnnotation.cs code around line 103/104 on constructor
https://github.com/chuanboz/odata.net/blob/master/src/Microsoft.OData.Client/Metadata/ClientPropertyAnnotation.cs MethodInfo propertyGetMethod = propertyInfo.GetGetMethod(); MethodInfo propertySetMethod = propertyInfo.GetSetMethod();
the GetGetMethod/GetSetMethod have an override that takes a Boolean true to indicate non-public property.
@LaylaLiu , Ping.
@chuanboz, Sorry to reply it so late. You are right. Your suggestion could solve this issue. Are you using OData V4 or OData V3? If you are using OData V4, Would you like to contribute the fix?
The issue on v4 is fixed. And will merge fix on v3. thanks.
v3 fix is committed, close the issue.
Overview
The DataServiceContext can't read entities whose classes have a property with a non-public setter. Instead it throws an InvalidOperationException, like 'The closed type [property's type] does not have a corresponding [property name] settable property'.
Having a property with non-public setter is an easy scenario, using EF's designer in the service-side to configure the property's setter with any access other tan 'Public' will also cause the $metadata for the service to include an annotation, causing the DataSvcUtil to generate the property's setter with that access.
The net result is that I can't use properties' access to have sane restrictions server-side without causing errors to clients that use DataSvcUtil or Visual Studio's Add Service Reference tool.
I've read elsewhere that the client can't read complex types with non-public properties. This isn't the case here, as in this case we're dealing with entity types.
Tested with
EntityFramework 5.0.0, 6.1.1 Microsoft.Data.Services.Client 5.6.0, 5.6.4
Setup
Create a web application, add an EF5 o 6 designer model, add an entity, and set a property's setter access to private, protected or internal. Setup a WCF Data Service for that model. The resulting metadata for that entity should look like this:
Next, use the Add Service Reference (or DataSvcUtil) to create client proxy clases for that service. The generated class has that property's setter with non-public Access, just like in the server. So far so good.
Finally, make any query that produces that entity type.
Result
InvalidOperationException "The closed type System.String does not have a corresponding Catalog settable property"
Notice that the message is also misleading, in that "System.String" is the property's type, not the entity.
Expected result
The entities are deserialized correctly with their Catalog property set.
Additional notes
I also tried with an internal setter, then having the client assembly's decorated with
That produced the same result.
Workaround
Edit the generated DataServiceContext to remove the "SetterAccess" attributes from the private GeneratedEdmModel class. Edit the generated entities to make the properties' setter public.