I have some Exception derived types, which add additional properties to the Exception. Searching the web for examples and guidelines on how to handle the serialization of such Exception-based types led to descriptions and code samples which were rather old. Trying these samples led always to security-errors.
To make it work, I had to additionally decorate the GetObjectData-Method with the System.Security.SecurityCritical attribute.
Interestingly, the SecurityPermission-Attribute, which was contained in all of the examples, but in various ways, seemed not to be necessary. Some examples only added it to the GetObjectData, some added it also to the deserializing-constructor. Some examples used the strong SecurityAction.Demand-action, most of the examples used the SecurityAction.LinkDemand-action and others declared SecurityAction.RequestMinimum.
My question is, whether the below Exception-derived type (for the serialization part of it) is correct for being used with nowadays .net frameworks (4.7.[x]+, Core[x], Standard2.[x]+) or if there is something missing, or if I even can remove some parts? Please note that I don’t want to seal the type. Other Exception-types should be able to derive from it.
[Serializable]
public class FooException : Exception{
readonly int m_fooValue;
public FooException(string message,int fooValue,Exception innerException=null) : base(message,innerException){
m_fooValue = fooValue;
}
[SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
protected FooException(SerializationInfo info, StreamingContext context) : base(info, context) {
m_fooValue = info.GetInt32(nameof(FooValue));
}
[SecurityCritical]
[SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
public override void GetObjectData(SerializationInfo info, StreamingContext context) {
if (info == null) throw new ArgumentNullException(nameof(info));
info.AddValue(nameof(FooValue), m_fooValue);
base.GetObjectData(info, context);
}
public int FooValue => m_fooValue;
}
The derived type (FooBarException) additionally must then also set the SecurityCritical-attribute on the deserializung-constructor for satisfying the LinkDemand:
[Serializable]
public class FooBarException : FooException{
readonly int m_barValue;
public FooBarException(string message,int fooValue, int barValue, Exception innerException = null) : base(message, fooValue, innerException) {
m_barValue = barValue;
}
[SecurityCritical] // Additional for satisfying the LinkDemand on the base constructor
[SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
protected FooBarException(SerializationInfo info, StreamingContext context) : base(info, context) {
m_barValue = info.GetInt32(nameof(BarValue));
}
[SecurityCritical]
[SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
public override void GetObjectData(SerializationInfo info, StreamingContext context) {
if (info == null) throw new ArgumentNullException(nameof(info));
info.AddValue(nameof(BarValue), m_barValue);
base.GetObjectData(info, context);
}
public int BarValue => m_barValue;
}
Sources
https://stackoverflow.com/a/100369/340628
What is the correct way to make a custom .NET Exception serializable?
https://blog.gurock.com/articles/creating-custom-exceptions-in-dotnet/
BinaryFormatter? Or something else such as Json.NET?