Skip to main content

Miscellaneous Customizations of the Audit Trail System (XPO)

  • 4 minutes to read

Implement Custom Persistent Object to be Used as the Audit Data Storage

The Audit Trail Module uses the AuditDataItemPersistent class as the audit data storage. To store extra audit information, inherit from this class or implement the IAuditDataItemPersistent interface. In the overridden OnSaving method of your AuditDataItemPersistent descendant, initialize extra properties based on the AuditedObject, PropertyName, and other information from the base class. Set the AuditDataItemPersistentType property to your class to use it instead of the default class.

Specify the String Representation of the Null Value

The Audit Trail Module saves the null value as the “N/A” string. To change its string representation, navigate to the Localization | AuditTrail node in the Model Editor and specify the NullValueString property.

If you want to use a different null value representation in audit records in the UI, set AuditDataStore‘s NullValueString property as shown below.

In .NET 6+ Applications

File: MySolution.Blazor.Server\Startup.cs, MySolution.Win\Startup.cs, MySolution.WebApi\Startup.cs

using DevExpress.Persistent.AuditTrail;
// ...
builder.Modules
    .AddAuditTrailXpo(o => {
        o.Events.OnCustomizeAuditDataStore = context => {
            context.AuditDataStore.NullValueString = "";
        };
    })

In .NET Framework Applications

File: MySolution.Win\WinApplication.cs, MySolution.Web\WebApplication.cs.

using DevExpress.Persistent.AuditTrail;
// ...
public partial class MySolutionWinApplication : WinApplication {
    //...
    protected override void OnSetupComplete() {
        base.OnSetupComplete();
        AuditTrailService.Instance.AuditDataStore.NullValueString = "";
    }
    // ...
}

Customize the Blob Properties Storage Mechanism

The Audit Trail Module saves Blob property values as the “Blob data” string. Follow the steps below to customize this behavior.

Note

You can also use this technique to specify the string representation of reference type properties.

  1. Implement the AuditDataStore descendant and override its GetDefaultStringRepresentation method.

    File: MySolution.Module\CustomAuditDataStore.cs.

    using DevExpress.Persistent.AuditTrail;
    using DevExpress.Persistent.BaseImpl;
    // ...
    public class CustomAuditDataStore : AuditDataStore<AuditDataItemPersistent, AuditedObjectWeakReference> {
        protected override string GetDefaultStringRepresentation(object value) {
            string result = base.GetDefaultStringRepresentation(value);
            if(result == BlobDataString)
                return GetCustomBlobDataString(value);
            return result;
        }
    
        private string GetCustomBlobDataString(object value) {
            // ...  
        }
    }
    
  2. Configure the Audit Trail system to use your custom data store:

    In .NET 6+ Applications

    In the application’s Startup.cs file, add the following code to the AddAuditTrailXpo method call.

    File: MySolution.Blazor.Server\Startup.cs, MySolution.Win\Startup.cs, MySolution.WebApi\Startup.cs

    using DevExpress.Persistent.AuditTrail;
    // ...
    builder.Modules
        .AddAuditTrailXpo(o => {
            o.Events.OnCustomizeAuditDataStore = context => {
                context.AuditDataStore = new CustomAuditDataStore();
            };
        })
    

    In .NET Framework Applications

    Set the AuditTrailService.Instance.AuditDataStore property to an instance of your class.

    File: MySolution.Win\WinApplication.cs, MySolution.Web\WebApplication.cs.

    using DevExpress.Persistent.AuditTrail;
    // ...
    public partial class MySolutionWinApplication : WinApplication {
        // ...
        protected override void OnSetupComplete() {
            base.OnSetupComplete();
            AuditTrailService.Instance.AuditDataStore = new CustomAuditDataStore();
        }
        // ...
    }
    

Implement a Custom AuditTrailService (.NET 6+)

In XAF applications that target .NET 6+, the Audit Trail system is implemented as a service (IAuditTrailService). You can create and register your own implementation of the IAuditTrailService as this section describes.

To create a custom IAuditTrailService, you can use the AuditTrailServiceBase type as a base type for your custom implementation or implement the IAuditTrailService interface from scratch:

using DevExpress.Persistent.BaseImpl.AuditTrail.Services;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;

public class CustomAuditTrailService : AuditTrailServiceBase {
    private const string unknownUserName = "Unknown";
    private readonly ISecurityStrategyBase securityStrategy;
    private readonly IAuditTrailServiceRoot auditTrailServiceRoot;
    private bool isSetupAuditCalled = false;

    public CustomAuditTrailService(IServiceProvider serviceProvider, IAuditTrailServiceRoot auditTrailServiceRoot, IOptionsSnapshot<AuditTrailOptions> auditTrailServiceOptions) :
        base(serviceProvider, auditTrailServiceRoot, auditTrailServiceOptions.Value) {
        this.securityStrategy = serviceProvider.GetService<ISecurityStrategyBase>();
        this.auditTrailServiceRoot = auditTrailServiceRoot;
    }
    protected override void EnsureSetupAudit() {
        if(!isSetupAuditCalled) {
            isSetupAuditCalled = true;
            auditTrailServiceRoot.SetupAudit(serviceProvider.GetRequiredService<ITypesInfo>(), Options.AuditDataItemPersistentType);
        }
    }
    protected override string GetCurrentUserNameCore() {
        return securityStrategy != null ? securityStrategy.UserName : unknownUserName;
    }
}

Register your custom IAuditTrailService type as a scoped service:

File: MySolution.Blazor.Server\Startup.cs, MySolution.Win\Startup.cs, MySolution.WebApi\Startup.cs

// ...
public class Startup {
    // ...
    public void ConfigureServices(IServiceCollection services) {
        // ...
        services.AddXaf(Configuration, builder => {
            builder.UseApplication<MyBlazorApplication>();
            builder.Modules
            // ...
                .AddAuditTrailXpo()
            // ...
        });
        services.AddScoped<IAuditTrailService, CustomAuditTrailService>();
        // ...
    }
//...
}
See Also