Pattern to Emulate a Property with no set in a DataContract?
I'm writing the WCF Service Hosts for our application. I know that in a
DataContract a
DataMember marked property must have a
get as well as a
set. Does anybody know of a good way to get around this?
Say I've got an Employee class that's a DataContract. I would like the client to be able to change FirstName and LastName and all that stuff, but I don't want them to be able to change the EmployeeId. I just want them to be albe to read it.
Both my Service and Client are .Net apps.
Any help would be very much appreciated.
Thanks,
Geoff
[721 byte] By [
TheGeoff] at [2007-12-23]
DataMember can be used on private, protected or public properties or fields. So, if you create a property accessor that has a public get property with a private or protected set (supported in 2.0), this will work on the service side. The proxy on the client, however, will always generate public get/set since it the property is included in the schema for the CLR type.
You could:
- Pre-create the proxy and data contracts for the client side, to make sure the set operation for the ID property is private.
- Prevent editing the ID field in the user interface.
Ultimately, if the user enters a new ID then they are also trying to update a different record, so it would have to be a valid ID in the first place. Not sure if that helps, but I think this is your only option given the nature of contracts.
Hi Geoff,
Like Michele mentioned, by the very nature of service/data contracts, any item/element you choose to expose via a service is by its nature something a client can make changes to.
Pre-creating the proxy and data contracts on the client-side and modifying the generated proxy code to make the property read-only is one option to make your .net client access a read-only property. This of course means that the elements that need to be customized in such fashion have to be documented somewhere and client developers has to make the necessary modifications to generated code for all such elements.
Still, remember that neither the service contract nor the data contract can enforce this read-only behavior. You are depending on the client developer to follow the right pattern.
With the same caveats as above, there is another option that might be easier to use.
One of the main goals of service orientation is that the client and service have no dependency other than sharing the contracts themselves, that is, the schemas, and that is good thing to do in general. But in some cases, where you control the client and the service, and might already be sharing some resources between them, it might not be a completely bad idea to share your data contract types (let me stress, only types that are exposed as data contracts to the outside world, not internal business objects or data objects that live within your service boundary and are not visible to the external world), between the client and the service.
If this is at all an option, its trivial to expose the right functionality to your clients.
- If you use svcutil.exe to create client proxies, just specify the /reference:<file path> option to the command line to make the generated proxy make use of your shared type library. Since the type defines a read-only EmployeeId property, the client also gets the same exact type to work with. (You would put the [DataMember] attribute on the private field that holds the employee id.)
- If you want to just create the proxies dynamically at runtime, you can put your service contract interfaces in a separate assembly from the service implementation classes themselves and then use the client-side ChannelFactory to create a service proxy:
IService1 service1Proxy = new ChannelFactory<IService1>(endPointInfo).CreateChannel();This way too, the proxy makes use of the shared types, and as a result exposes the right functionality.Using this option, you don't have to modify generated code the first time and anytime you might need to regenerate the proxy.
Hope this helps!
Rajesh