Skip to main content
All docs
V24.2

Reporting — Safe Deserialization

  • 4 minutes to read

DevExpress controls automatically detect potentially unsafe data types and block deserialization to address security-related issues. The NonTrustedTypeDeserializationException is thrown if a reporting control attempts to load an unsafe data type.

This article describes serialization/deserialization best practices specific to DevExpress Reporting components. Review the following help section for general security considerations related to all DevExpress components: General – Safe Deserialization.

DevExpress Reporting controls deserialize the following data types automatically:

  • Custom controls saved in XML/REPX.
  • Complex type values for properties marked with the XtraSerializableProperty attribute (for example, a reference to an object). Read the following topic for additional information in this regard: How to serialize a custom property of a DevExpress control descendant.
  • System.Object type properties (such as the Tag property) for simple data types such as integer, float, double, decimal, bool, string, etc.

Deserialize Custom Types

A custom type must be serialized to and deserialized from a string. Use IOneTypeObjectConverter to serialize the following custom types:

  • A complex parameter value (such as IList or IDictionary).
  • The control’s Tag property that contains a custom type (any type except primitive, string, decimal, date-time, etc.).

You should explicitly trust any bound data type your report references. If a custom type instance is a container for data types, use IObjectDataSerializer to serialize the custom type along with its content. Read the following section for additional information: Deserialize Data Sources.

Important

Do not use the BinaryFormatter to serialize/deserialize data. The BinaryFormatter is not secure and is not recommended for data processing purposes. Read the following topic for additional information: Deserialization Risks in Use of BinaryFormatter and Related Types.

Example

The following example serializes/deserializes the tag property value (determines whether to display time in the parameter value of the Parameter Editor.

The Tag property value

Implement the IOneTypeObjectConverter interface and register the converter at application startup:

using System.Collections.Generic;
using DevExpress.Utils.Serializing.Helpers;

var app = builder.Build();

// Register a converter for the Tag property with a custom value of the ParameterEditorSettings type.
ObjectConverter.Instance.RegisterConverter(new ParameterEditorSettingsConverter());

app.Run();

sealed class ParameterEditorSettingsConverter : IOneTypeObjectConverter {
    public Type Type => typeof(ParameterEditorSettings);

    public object FromString(string str) {
        return JsonSerializer.Deserialize<ParameterEditorSettings>(str);
    }

    public string ToString(object obj) {
        return JsonSerializer.Serialize(obj);
    }
}

Deserialize Data Sources

Data loading-related restore operations for the following data source types generate security warnings if the following data sources use untrusted types:

Use IObjectDataSerializer to serialize custom data sources.

Example

The example below creates and registers a custom serializer for an object data source.

Implement and register a custom serializer (EmployeeListSerializer) that implements safe serialization/deserialization of the Employee data source type.

using System.Collections.Generic;
using DevExpress.Utils.Serializing;

var app = builder.Build();

// Allow custom data source serialization.
DevExpress.Utils.DeserializationSettings.RegisterTrustedClass(typeof(EmployeeDataSource));
// Register a custom serializer for Employee.
ObjectDataSerializer.Register<Employee>(new EmployeeListSerializer());

app.Run();

}
sealed class EmployeeListSerializer : IObjectDataSerializer {
    public bool CanDeserialize(string value, string typeName) {
        return typeName == typeof(List<Employee>).FullName;
    }

    public bool CanSerialize(object data) {
        return data is List<Employee>;
    }

    public object Deserialize(string value, string typeName) {
        if(typeName == typeof(List<Employee>).FullName)
            return JsonSerializer.Deserialize<List<Employee>>(value);
        throw new NotSupportedException();
    }

    public string Serialize(object data) {
        return JsonSerializer.Serialize(data);
    }
}

To allow data source serialization, explicitly trust the data source type at application startup.

var app = builder.Build();

// Allow custom data source serialization.
DevExpress.Utils.DeserializationSettings.RegisterTrustedClass(typeof(EmployeeDataSource));

app.Run();
public partial class EmployeesReport : DevExpress.XtraReports.UI.XtraReport {
    public EmployeesReport() {
        // ...
        this.objectDataSource1.DataSource = typeof(WebEFCoreApp.Data.EmployeeDataSource);
        // ...
    }
}

Deserialize Report Parameters

Implement a type converter to convert custom types to/from a string to deserialize complex parameter values (for example, IList, IDictionary). The DevExpress serialization/deserialization mechanism invokes the type converter whenever it encounters a registered custom type.

Example

The example below creates a custom type converter (DictionaryConverter).

Implement the IOneTypeObjectConverter interface and register the converter at application startup.

using DevExpress.Utils.Serializing.Helpers;

var app = builder.Build();

// Register a converter for the custom parameter of the Dictionary<string, int> type.
ObjectConverter.Instance.RegisterConverter(new DictionaryConverter());

app.Run();

sealed class DictionaryConverter : IOneTypeObjectConverter {
    public Type Type => typeof(Dictionary<string, int>);

    public object FromString(string str) {
        return JsonSerializer.Deserialize<Dictionary<string, int>>(str);
    }

    public string ToString(object obj) {
        return JsonSerializer.Serialize(obj);
    }
}
See Also