question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

FaultException implements Serializable but does not use serialization constructors

See original GitHub issue

Describe the bug As part of #3984 FaultException was marked Serializable which was released in System.ServiceModel.Primitives 4.8.0 However I am still not able to use the use case as described by Wouter. Using code that serializes FaultExceptions using remoting. After updating my dependency on System.ServiceModel.Primitives I still receive the stack trace

Failed to deserialize and get remote exception  System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.PlatformNotSupportedException: Operation is not supported on this platform.
   at System.ServiceModel.CommunicationException..ctor(SerializationInfo info, StreamingContext context)
   at System.ServiceModel.FaultException..ctor(SerializationInfo info, StreamingContext context)
   at System.ServiceModel.FaultException`1..ctor(SerializationInfo info, StreamingContext context)
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeConstructorInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at System.Runtime.Serialization.ObjectManager.CompleteISerializableObject(Object obj, SerializationInfo info, StreamingContext context)
   at System.Runtime.Serialization.ObjectManager.FixupSpecialObject(ObjectHolder holder)
   at System.Runtime.Serialization.ObjectManager.DoFixups()
   at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(BinaryParser serParser, Boolean fCheck)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, Boolean check)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
   at Microsoft.ServiceFabric.Services.Remoting.V2.RemoteException.TryDeserializeException(Stream data, Exception& result)

As far as I can tell that is because protected FaultException(SerializationInfo info, StreamingContext context) throws a PlatformNotSupportedException

In reference source that method is implemented https://github.com/microsoft/referencesource/blob/5697c29004a34d80acdaf5742d7e699022c64ecd/System.ServiceModel/System/ServiceModel/FaultException.cs#L120

The scenario is the same as described by Wouter in the referenced issue. Is this something that also needs to be taken into account?

Thanks in advance, Regards, Max

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:12
  • Comments:7 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
kaylumahcommented, Nov 30, 2020

@jnyrup Cool thanks for Sharing.

I also just created a quick example

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.ServiceModel;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            // #1 Plain FaultException using DataContractSerializer
            var dcs = new DataContractSerializer(typeof(FaultException));
            using (var ms = new MemoryStream())
            using (var sr = new StreamReader(ms))
            {
                // Serialize + Print
                dcs.WriteObject(ms, new FaultException("my fault reason"));
                ms.Position = 0;
                Console.WriteLine(sr.ReadToEnd());

                // Deserialzie
                // ms.Position = 0;
                // var result = dcs.ReadObject(ms); // throws PlatformNotSupportedException: Operation is not supported on this platform.
            }

            Console.WriteLine("-------------------");

            // #2 FaultException with FaultContract using DataContractSerializer
            var dcs2 = new DataContractSerializer(typeof(FaultException<MyFaultContract>));
            using (var ms = new MemoryStream())
            using (var sr = new StreamReader(ms))
            {
                // Serialize + Print
                dcs2.WriteObject(ms, new FaultException<MyFaultContract>(new MyFaultContract() { SomeValue = "1"}, new FaultReason("my reason")));
                ms.Position = 0;
                Console.WriteLine(sr.ReadToEnd());

                // Deserialzie
                // ms.Position = 0;
                // var result = dcs2.ReadObject(ms); // throws PlatformNotSupportedException: Operation is not supported on this platform.
            }

            Console.WriteLine("-------------------");

            // #3 Plain FaultException  using BinaryFormatter
            BinaryFormatter formatter = new BinaryFormatter();
            using (var ms = new MemoryStream())
            using (var sr = new StreamReader(ms)) {
                // Serialize + Print
                formatter.Serialize(ms, new FaultException("my fault reason"));
                ms.Position = 0;
                Console.WriteLine(sr.ReadToEnd());

                // Deserialize
                // ms.Position = 0;
                // var result = formatter.Deserialize(ms); // throws PlatformNotSupportedException: Operation is not supported on this platform.
            }

            Console.WriteLine("-------------------");

            // #4 FaultException with FaultContract using BinaryFormatter
            BinaryFormatter formatter2 = new BinaryFormatter();
            using (var ms = new MemoryStream())
            using (var sr = new StreamReader(ms)) 
            {
                // Serialize + Print
                formatter2.Serialize(ms, new FaultException<MyFaultContract>(new MyFaultContract() { SomeValue = "1" }, new FaultReason("my reason")));
                ms.Position = 0;
                Console.WriteLine(sr.ReadToEnd());

                // Deserialize
                // ms.Position = 0;
                // var result = formatter2.Deserialize(ms); // throws PlatformNotSupportedException: Operation is not supported on this platform.
            }

            Console.WriteLine("-------------------");

            Console.ReadLine();
        }
    }

    [DataContract]
    class MyFaultContract
    {
        [DataMember]
        public string SomeValue { get; set; }
        
    }
}

The above example demonstrates that both using BinaryFormatter and DataContractSerializer serialization appears to be working. In all cases deserialization fails on the PlatformNotSupportedException.

Since our use case is to serialize the exception between services and then recreate them by deserializing to again have the Fault in the context of the service, we are unable to proceed with out use case at the moment

2reactions
jnyrupcommented, Nov 30, 2020

Here’s a complete repro that shows the difference between using:

  • reference assembly in net472, and
  • nuget package in netcoreapp3.1

FaultExceptionTests.zip

Read more comments on GitHub >

github_iconTop Results From Across the Web

Getting no valid constructor error during serialization in Java
1 Answer 1 ... Just for the people, who would need the reference. As EJP clearly stated, we need to add no-args constructor...
Read more >
CA2229: Implement serialization constructors (code analysis)
The type implements the System.Runtime.Serialization.ISerializable interface, is not a delegate or interface, and one of the following ...
Read more >
Serialization in Java
If you want an object property to be not serialized to stream, you can use transient keyword like I have done with salary...
Read more >
Serializable (Java SE 17 & JDK 17)
This constructor must be accessible to the subclass that is being deserialized. It is an error to declare a class Serializable if this...
Read more >
Towards Better Serialization
Pretends to be a statically typed feature, but isn't. Serializability is a function of an object's dynamic type, not its static type; implements...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found