| Severity | Error |
| Reported by | PostSharp.Patterns.Model |
| Message | The [Recordable] aspect cannot open a recording scope for the async or iterator method <Method>. Make the method neither public nor internal, or add the [RecordingScope(RecordingScopeOption.Skip)] attribute to it. |
Cause
Note
Undo/redo, and the RecordableAttribute aspect, are deprecated since PostSharp 2026.0.
The RecordableAttribute aspect opens a recording scope around each public or internal method of the class, so that all the changes that the method makes are undone as a single operation. A recording scope cannot span an async method or an iterator, whose execution is split between several calls.
PostSharp reports DOM026 on the first public or internal async or iterator method of a recordable class, unless the method has RecordingScopeAttribute with Skip. Property getters, event accessors and abstract methods are not checked. <Method> is the name of the method, without its type.
In the following example, the recordable Document class has a public async method, LoadAsync.
// The Recordable aspect is deprecated.
#pragma warning disable CS0618
using System;
using System.Threading.Tasks;
using PostSharp.Patterns.Recording;
namespace Errors.DOM026_Error;
[Recordable]
public class Document
{
public string? Text { get; set; }
// The aspect opens a recording scope for each public method, which an async method cannot have.
public async Task LoadAsync( string text )
{
await Task.Yield();
this.Text = text;
}
}
public static class Program
{
public static void Main()
{
var document = new Document();
document.LoadAsync( "Hello" ).GetAwaiter().GetResult();
Console.WriteLine( $"Text: {document.Text}" );
}
}
error DOM026: DOM026_Error.cs(16,23): The [Recordable] aspect cannot open a recording scope for the async or iterator method LoadAsync. Make the method neither public nor internal, or add the [RecordingScope(RecordingScopeOption.Skip)] attribute to it.
Resolution
- Add
[RecordingScope( RecordingScopeOption.Skip )]to the method. The aspect then opens no scope for it. To group the changes of the method into one operation, open a scope yourself in the code that calls it, with OpenScope. - Otherwise, make the method
privateorprotected, which the aspect does not wrap in a scope.
In the following example, LoadAsync skips the recording scope.
// The Recordable aspect is deprecated.
#pragma warning disable CS0618
using System;
using System.Threading.Tasks;
using PostSharp.Patterns.Recording;
namespace Errors.DOM026_Fixed;
[Recordable]
public class Document
{
public string? Text { get; set; }
// The aspect does not open a recording scope for this method.
[RecordingScope( RecordingScopeOption.Skip )]
public async Task LoadAsync( string text )
{
await Task.Yield();
this.Text = text;
}
}
public static class Program
{
public static void Main()
{
var document = new Document();
document.LoadAsync( "Hello" ).GetAwaiter().GetResult();
Console.WriteLine( $"Text: {document.Text}" );
}
}
Text: Hello
See Also
Reference
RecordableAttribute
RecordingScopeAttribute
RecordingScopeOption
Other Resources
Making Your Model Recordable
Customizing Undo/Redo Operation Names
Limitations of Undo/Redo