Sonarcube does not like my implementation of serializable exception class

11.7k Views Asked by At

SonarCube shows me error "Update this implementation of 'ISerializable' to conform to the recommended serialization pattern" for the following exception implementation:

[Serializable]
public class UnrecoverableException : Exception, ISerializable
{
    public bool Ignore { get; }

    public UnrecoverableException()
    {
    }

    public UnrecoverableException(string message, Exception innerException)
        : base(message, innerException)
    {
    }

    protected UnrecoverableException(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
        Ignore= info.GetBoolean(nameof(Ignore));
    }

    public UnrecoverableException(string message, bool ignore= false) : base(message)
    {
        Ignore= ignore;
    }

    public override void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue(nameof(Ignore), Ignore);
        base.GetObjectData(info, context);
    }
}

not sure what's wrong here as to me it seems totally following rules described here https://rules.sonarsource.com/csharp/tag/pitfall/RSPEC-3925

This rules raises an issue on types that implement ISerializable without following the serialization pattern recommended by Microsoft.

  • The System.SerializableAttribute attribute is missing.

  • Non-serializable fields are not marked with the System.NonSerializedAttribute attribute.

  • There is no serialization constructor.

  • An unsealed type has a serialization constructor that is not protected.

  • A sealed type has a serialization constructor that is not private.

  • An unsealed type has a ISerializable.GetObjectData that is not both public and virtual.

  • A derived type has a serialization constructor that does not call the base constructor.

  • A derived type has a ISerializable.GetObjectData method that does not call the base method.

  • A derived type has serializable fields but the ISerializable.GetObjectData method is not overridden.

2

There are 2 best solutions below

5
MattBH On

All I had to do to pass Sonarqube's analysis was add the [Serializable] attribute to the class and add a protected constructor. i.e.:

[Serializable]
public class BadRequestException : Exception
{
    public BadRequestException(string message) : base(message)
    {

    }

    protected BadRequestException(SerializationInfo info, StreamingContext context) : base(info, context)
    {

    }
}
0
Deven Shah On

From .Net documentation standpoint, for custom exception, all we need to do is derive from Exception class and they further recommend to add empty, message and message + inner exception constructors.

However, Sonar cloud raises warning S3925 for this implementation in .Net 8. Further investigation into this requires implementing a protected constructor and override of GetObjectData as seen below. Apparently, these are now marked obsolete in .Net 8.

Finally this worked for me:

[Serializable]
public class MyException : Exception
{
    public MyException() { }
    public MyException(string message) : base(message) { }
    public MyException(string message, Exception? innerException) : base(message, innerException) { }

    [Obsolete("", DiagnosticId = "SYSLIB0051")]
    protected MyException(SerializationInfo info, StreamingContext context) : base(info, context) { }

    [Obsolete("", DiagnosticId = "SYSLIB0051")]
    public override void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        base.GetObjectData(info, context);
    }
}