Open sandboxFocusImprove this doc

LA0171: Fallback Without an OnInvoke Method

Severity Error
Reported by PostSharp
Message Aspect "<Aspect>" does not implement the non-async OnInvoke advice, therefore the UnsupportedTargetAction property cannot be set to Fallback.

Cause

A MethodInterceptionAspect that overrides OnInvokeAsync(MethodInterceptionArgs) intercepts the tasks of the methods that return a Task or a Task<TResult>. Async interception does not support other targets, such as async void methods and methods that return a ValueTask<TResult>. The UnsupportedTargetAction property says what PostSharp does with them, and Fallback means that OnInvoke(MethodInterceptionArgs) intercepts them without async semantics.

PostSharp reports LA0171 when the property is set to Fallback and the aspect does not override OnInvoke(MethodInterceptionArgs): there is nothing to fall back to. PostSharp checks this for every target of the aspect, also for the targets that async interception supports, and reports the error on the target method.

In the following example, the [Log] aspect overrides only OnInvokeAsync, and its usage asks for a fallback.

using System;
using System.Threading.Tasks;
using PostSharp.Aspects;
using PostSharp.Serialization;

namespace Errors.LA0171_Error;

[PSerializable]
public class LogAttribute : MethodInterceptionAspect
{
    public override async Task OnInvokeAsync( MethodInterceptionArgs args )
    {
        Console.WriteLine( $"Calling {args.Method.Name} asynchronously." );
        await args.ProceedAsync();
    }
}

public class PriceService
{
    // Fallback needs an OnInvoke method, which the aspect does not override.
    [Log( UnsupportedTargetAction = UnsupportedTargetAction.Fallback )]
    public async ValueTask<decimal> GetPriceAsync( string product )
    {
        await Task.Yield();

        return product.Length * 1.5m;
    }
}

public static class Program
{
    public static async Task Main()
    {
        Console.WriteLine( await new PriceService().GetPriceAsync( "Coffee" ) );
    }
}
error LA0171: LA0171_Error.cs(22,37): Aspect "Errors.LA0171_Error.LogAttribute" does not implement the non-async OnInvoke advice, therefore the UnsupportedTargetAction property cannot be set to Fallback.

Resolution

In the following example, the aspect overrides OnInvoke, which intercepts the method that returns a ValueTask<decimal>.

using System;
using System.Threading.Tasks;
using PostSharp.Aspects;
using PostSharp.Serialization;

namespace Errors.LA0171_Fixed;

[PSerializable]
public class LogAttribute : MethodInterceptionAspect
{
    // The fallback for the methods that async interception does not support.
    public override void OnInvoke( MethodInterceptionArgs args )
    {
        Console.WriteLine( $"Calling {args.Method.Name}." );
        args.Proceed();
    }

    public override async Task OnInvokeAsync( MethodInterceptionArgs args )
    {
        Console.WriteLine( $"Calling {args.Method.Name} asynchronously." );
        await args.ProceedAsync();
    }
}

public class PriceService
{
    [Log( UnsupportedTargetAction = UnsupportedTargetAction.Fallback )]
    public async ValueTask<decimal> GetPriceAsync( string product )
    {
        await Task.Yield();

        return product.Length * 1.5m;
    }
}

public static class Program
{
    public static async Task Main()
    {
        Console.WriteLine( await new PriceService().GetPriceAsync( "Coffee" ) );
    }
}
Calling GetPriceAsync.
9.0

See Also

Reference

MethodInterceptionAspect
UnsupportedTargetAction

Other Resources

Intercepting Methods
Semantic Advising of Iterator and Async Methods