Control name of built-in generic parameter in WCF DataContract - wcf

I am converting asmx web service to wcf while attempting to maintain backwards compatibility in the WSDL. One of the DataContract classes is generic. When the generic parameter is a built-in type, such as bool, the first letter is lowercased in WCF, whereas it was uppercased in asmx. E.g.
[Serializable]
public class MethodResult<T>
{
}
would generate
MethodResultOfBoolean
in asmx.
[DataContract(Name="MethodResultOf{0}")]
public class MethodResult<T>
{
}
generates
MethodResultOfboolean
in WCF.
Is there a way to make it use an uppercase letter in WCF?

I found that adding [XmlSerializerFormatAttribute] to the ServiceContract interface fixed this.

Related

Effects of XmlIncludeAttribue when it's used in WCF DataContract

1) Does Binding use while creating ChannelFactory makes any difference to how serialization/deserialization works? (I know that binding used should match the server side binding of the service.)
I am using KnownType attribute in one of my DataContract but it does not work. But if I use XmlIncludeAttribute, it works! (I am migrating my ASMX services to WCF.. But I am not using any MessageContracts since I have freedom to update client side proxies too.)
[XmlInclude(typeof(Males))]
[DataContract]
public abstract class Person
{
[DataMember]
public int Name { get; set; }
}
2) If I use any Attribute ( to be specific - XmlInclude)) that uses XmlSerializer for the WCF DataContract, does WCF use XmlSerializer instead of DataContractSerializer?
DataContractSerializer supports everything that XmlSerializer supports, but the reverse is not true. But if a type is decorated with [DataContract], it switches over completely to the new DataContract programming model, completely throwing away support for [Serializable], IXmlSerializable, etc. types that it otherwise would have had.
So your [XmlInclude] magic works only if you're using ASMX and the traditional XmlSerializer. If you're using DataContractSerializer, you have to do known types, and XML-isms like [XmlInclude] and XML attributes are simply not supported. You can still use XmlSerializer instead of DataContractSerializer if you want to, though; all you need to do is decorate the service or operation you want to switch over to XmlSerializer with [XmlSerializerFormatAttribute.]
Hope this helps!

WCF and System.Drawing.Color

Thanks for the quick answers all. But I am looking for an answer and not a workoaround (serialize as string) as I want to know how to use other types from the framework
I am fairly good at WCF but I think I am still at the beginners stage since I cannot serialize a System.Drawing.Color.
This is my Service Contract
using System.Drawing;
using System.ServiceModel;
namespace wcfServer
{
[ServiceContract]
public interface IColorService
{
[OperationContract]
Color DoWork();
}
}
And here is an implementation
public class ColorService : IColorService
{
public Color DoWork()
{
return Color.Yellow;
}
}
However, at the client WCF doesn't use a System.Drawing.Color but it generates it own color type (a struct) ?
The net result is that the color Yellow does not arrive at the client
I thought that this wasn't a problem since the .net Color type is marked with the serializable attribute
Kind Regards, Tom
Colors are usually a mess - there are so many of them. Just convert to color to a 32-bit ARGB structure (the Color class has a method that does this) and use that in your WCF interface. If you want to be extra careful, define your own struct with A, R, G and B (as bytes, WPF has them as doubles, but nobody really needs that), and decouple your service from any specific UI platform.
However, at the client WCF doesn't use a System.Drawing.Color but it generates it own color type (a struct)? [...] I thought that this wasn't a problem since the .net Color type is marked with the serializable attribute
I'm assuming you use basicHttp or wsHttp here. What I'm saying doesn't go for all bindings.
Communication between a WCF service and client has nothing to do with .NET. Keyword is interoperability. The client doesn't have to be written in .NET, it might very well be a PHP or Java or whatever kind of client.
WCF therefore uses SOAP to send and receive data, which all major programming languages implement. So to let a service and client exchange data, a format for that data has to be defined. You can't say "Hey, I'm gonna send a System.Drawing.Color", since that may very well not be a valid class or struct definition in the client's language.
So your service defines a WSDL, containing a schema definition, where the contents of the Color struct will be copied from System.Drawing.Color. It won't be linked to the .NET framework from the point it gets serialized and sent over the wire.
I was able to fix this problem by using "KnownTypeAttribute" on a data contract. So you can try "ServiceKnownTypeAttribute" on a service contract like this :
[ServiceContract]
[ServiceKnownType(typeof(System.Drawing.Color))]
public interface IColorService
{
[OperationContract]
Color DoWork();
}
This works fine assuming that the client code is also using .NET.
The strategy with "KnownType" worked well in my project http://www.nquotes.net/ and let me avoid additional serialization hassle. They should have included Color as one of the base types (as they do with Guid, for example, which is "known" automatically - http://msdn.microsoft.com/en-us/library/ms731923.aspx ).

WCF Serializeable entity and __BackingField

We have a 3rd party dll wich contains (among other things) our entities.
The entites are all marked with the [Serializeable] attribute.
We now need to creat a new WCF services which will expose some of this entities.
The problem is, since the entites are not declared with the DataContract and DataMember attributes, the property names are appended with __BackingField!
I know using the DataContarct\Member attributes will solve this issue, but given that I cannot modify the 3rd party dll with the entities, is there a different workaround?
Types decorated with the [Serializable] attribute have their fields serialized, not properties (that's the [Serializable] "contract"). If the 3rd party types use automatic properties (as shown below), the compiler will create a field with the k_BackingField suffix, and this is what will be serialized.
If you cannot change the types in the 3rd party library, one alternative would be to use that same library on the client. When creating the proxy for the service (using either svcutil or Add Service Reference), you can reference the 3rd party library, and the generated client won't create new types for the contracts, instead reusing the types from the library. This way you won't have to deal with types with public _BackingField property names.
Automatic properties:
[Serializable]
public class MyType
{
public string MyProp { get; set; }
}
The compiler will turn it into something similar to
[Serializable]
public class MyType
{
private string <MyProp>k_BackingField;
public string MyProp
{
[CompilerGenerated]
get { return this.<MyProp>k_BackingField; }
[CompilerGenerated]
set { this.<MyProp>k_BackingField = value; }
}
}
You can use the XmlSerializerFormatAttribute to use XmlSerializer instead of DataContractSerializer in the service implementation.
It will perform slower but it should sovle your problem.
I am assuming you want to expose these third party types from a service.
One solution which you may consider is to maintain a separate library which mirrors the types in the third party library.
This has the following benefits:
Ownership - You own the types you are exposing therefore you control the serialization/deserialization across your service boundary.
You are insulated from sudden changes to the other party's types and can change your interfaces in a controlled fashion.
From a SOA perspective if you are exposing another party's types on your service the other party should supply the types in a contractural format like XSD. I think your design calls for some fairly unreasonable hoop-jumping on your part.
It may be more work up front but it is kind of a one-off exercise.
Hope this helps some.

WCF - DataContract that inherits from an interface

I have a datacontract as part of my WCF Interface that inherits from IIdentity:
[DataContract]
public class AuthenticationIdentity : IIdentity
{
//implements IIdentity...
}
The service returns my AuthenticationIdentity objects just fine. However, when I try and do the obvious cast on the client:
AuthenticationIdentity aId = client.GetID();
IIdentity id = aId;
I get a complaint that AuthenticationIdentity cannot be cast to IIdentity. I've tried adding the ServiceKnownTypes to the interface:
[ServiceKnownType(typeof(AuthenticationIdentity))]
[ServiceKnownType(typeof(IIdentity))]
but still no luck. Any ideas?
If you control both sides of the wire (which it looks like you do since you want to cast to IIdentity), you can reference your DataContract from a shared assembly. Then you can use svcutil to share the DataContracts between the service and the consumer. Or, if you wanted to cut out svcutil altogether, you could write your own proxy to use the shared assembly.

WCF Service parameters changed in .NET 2.0 client

I created a WCF service that exposed a method that has one paramater:
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
}
The service has two endpoints defined (wsHttpBinding and basicHttpBinding) so that it would be compatable with older clients.
The service runs just fine in a .NET 3.0 and .NET 3.5 client app. However, when I create a .NET 2.0 client, the GetData method requires 2 parameters: an integer (expected) and a bool parameter called valueSpecified (unexpected). I never defined the second parameter. Why is this happening and how can I get rid of the second parameter?
Since value types can't be null (in latter versions of .net framework there is no Nullable<T>) VS besides to generate additional parameter to give you ability to not specify value type, you can call your service method like this.
service.GetData(val,true);
see this post, where John Saunders suggest to add [DataMember(Required = true)] attribute in the property.
The exact same question has been posted here.
Another way to avoid the extra boolean parameter to be generated on the client proxy when using .NET 2.0 is to switch to RPC-style enconding in the service contract (the default for both WCF and ASMX is Document Style).
This way the XmlSerializer on the client will make sure that the parameter always appears in the SOAP requests since it's part of the SOAP 1.1 specification, which is enforced when using the RPC-Style encoding.
In WCF you can specify the encoding style using the DataContractFormat attribute, either at the service or at the operation level.
[ServiceContract]
public interface IService
{
[OperationContract]
[DataContractFormat(Style = OperationFormatStyle.Rpc)]
string GetData(int value);
}
More information on the differences between RPC Style and Document Style encoding in SOAP can be found here.
In any case please consider carefully the implications of changing the contract of your services, since it can potentially break compatibility with any existing clients.
You could manually remove the valueSpecified property from GetData operation within your proxy class.