views:

391

answers:

3

I have a class with a read-only property defined. In my code I define this as a property with a getter only.

I want to be able to send this object back and forth across a web service. When I call a "Get" method in the service, it would be populated with a value on the service side. Once I define this property, I don't want the consumer of the web service to be able to set/change this property.

When I add a reference to this web service to a project, the object has the property serialized a few different ways depending on how I try to define the object on the service side:

  • internal setter: Creates the property in the WSDL. Visual Studio generates a class with both a getter & a setter for this property.
  • no setter: Does not create the property in the WSDL. Visual Studio then obviously does not define this property at all.
  • Read-only public member variable - Does not create the property in the WSDL. Again, Visual Studio will not do anything with this property since it doesn't know about it.

Allowing the consumer of the web service to set a value for this property will not cause any harm. If the value is set, it is ignored on the web service side. I'd just prefer if the consumer can't change/set the property to begin.

Is there any way to define a property as read-only? Right now we're using C#/.NET 2.0 for the web service, and (for now at least) we have control over all of the consumers of this service, so I can try changing configurations if needed, but I prefer to only change things on the web service and not the consumers.

+2  A: 

I can be wrong, but I think the problem here is how serialization works - in order to deserialize an object the serializer creates an empty object and then sets all the properties on this object - thats why you need a setter for the properties to be included in serialization. The client code has the same "interface" to the object as the deserializer.

Grzenio
That's what I thought. I was hoping there would be some way to work around this though.
Dan Herbert
+1  A: 

Caveat, I am a Java guy so the first part of my answer focuses on what may be possible in C#.

Firstly, with a custom serializer in Java, you can do almost anything you want, including directly setting values of a protected or private field using reflection so long as the security manager doesn't prevent this activity. I don't know if there are analogous components in C# for the security manager, field access, and custom serializers, but I would suspect that there are.

Secondly, I think there is a fundamental difference in how you are viewing Web services and the Web service interface as part of your application. You are right-click generating the Web service interface from existing code - known as "code first". There are many articles out there about why WSDL first is the preferred approach. This one summarizes things fairly well, but I would recommend reading others as well. While you are thinking in terms of a shared code library between the client side and server side of your Web service and maintaining object structure and accessibility, there is no such guarantee once you publish an API as a Web service and don't have control over all of the consumers. The WSDL and XSD serve as a generic description of your Web service API and your server and client can be implemented using different data binding configurations, object classes, or languages. You should think of your Web service interface and the XML that you pass in and out of it as describing the semantics of the exchange, but not necessarily the syntax of the data (your class structure) once it is internalized (deserialized) in your client or server.

Furthermore, it is advisable to decouple your transport related structures from your internal business logic structures lest you find yourself having to refactor both your server implementation, your Web service API, and your (and other's) client implementations all at the same time.

DavidValeri
I thought about using a custom serializer, then I thought of the second point you mentioned. I can serialize the data very easily on the service side, however once it is sent to the client, they would need their own serializer to read the XML sent. This seemed like a messy way of doing things.
Dan Herbert
A: 

There's no built-in way to do this in .NET 2.0 as far as I know. In cases where I wanted to serialize a read-only property, I've implemented the IXmlSerializable interface so that I could control the ReadXml() and WriteXml() methods.

In later versions of the .NET framework, you can serialize read-only properties by setting an attribute on the backing field.

dthrasher