-
Notifications
You must be signed in to change notification settings - Fork 557
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DataContractSerializer
: Serialize child class as base class
#5437
Comments
I think you can solve this by providing a ISerializationSurrogateProvider using DataContractSerializerOperationBehavior. factory = new ChannelFactory<IDataContractResolverService>(new BasicHttpBinding(), new EndpointAddress(Endpoints.DataContractResolver_Address));
var surrogateProvider = new MySerializationSurrogateProvider();
foreach (var operation in factory.Endpoint.Contract.Operations)
{
DataContractSerializerOperationBehavior behavior =
operation.OperationBehaviors.FirstOrDefault(
x => x.GetType() == typeof(DataContractSerializerOperationBehavior)) as DataContractSerializerOperationBehavior;
behavior.SerializationSurrogateProvider = surrogateProvider;
}
public class MySerializationSurrogateProvider : ISerializationSurrogateProvider
{
public bool mySurrogateProviderIsUsed = false;
public object GetDeserializedObject(object obj, Type targetType)
{
return obj;
}
public object GetObjectToSerialize(object obj, Type targetType)
{
return obj;
}
public Type GetSurrogateType(Type type)
{
if (type == typeof(Child))
{
return typeof(Base);
}
return type;
}
} I haven't tested this specific code snippet, but I believe this should work for you. Basically when DataContractSerializer (DCS) is presented an object of type Child, we tell it to use the generated serializer for Base, which means it will only care about serializing those properties and will ignore the rest. Then when it comes to actually serialize it, the Child instance gets passed to GetObjectToSerialize and as long as the returned instance is of type Base, DCS doesn't care that it's the exact same instance. The reason for the default behavior is to avoid data loss. If you intended to serialize Child and had missed specifying KnownTypes or ServiceKnownTypes and we silently just serialized Base properties, you could lose data and not realize until it's too late. |
Thank you, for the detailled answer. Where do I typically have to execute the first lines of your code? |
Are you using a client generated by dotnet-svcutil? The code snippet I provided is when you are manually instantiating a ChannelFactory and not using the generated client. |
Yes, I'm using the svcutil generated code. Can I manually provide a ChannelFactory there? Somewhere at initialization of the WCF Client? |
You can access the channel factory on the client. By default every client instance gets its own ChannelFactory instance, but you can turn on channel factory caching as long as you are certain every instance will be using the same binding and endpoint address. The code would look like this: MyGeneratedClient.CacheSetting = CacheSetting.AlwaysOn;
var client = new MyGeneratedClient();
var surrogateProvider = new MySerializationSurrogateProvider();
foreach (var operation in client.Endpoint.Contract.Operations)
{
// Code from above
}
|
Description
I have following on my server:
and on my client:
When calling the server with
DoSth(child)
I get a serialization exception, becauseChild
is not known to the WCF DataContractSerializer:And I don't want to make it known, because the server uses only
Base
's properties. How can I send my data asBase object
?I know, I could create a new
Base
object and copy all properties, but this is not really elegant.see also https://stackoverflow.com/questions/78061526/datacontractserializer-deserialize-child-class-into-base-class
Reproduction Steps
Base
andChild
classes as described above.Child
to server.Expected behavior
Child
should be serialized asBase
, ignoring all additional properties.Actual behavior
Regression?
No response
Known Workarounds
No response
Configuration
.NET 8 on Windows 11, but should not be specific to that environment.
Other information
No response
The text was updated successfully, but these errors were encountered: