| Severity | Error |
| Reported by | PostSharp |
| Message | Advice "<Advice>" is not valid on method "<Method>": method return type must be "<ReturnType>". |
Cause
An advice method marked with OnMethodInvokeAsyncAdvice intercepts async methods, as OnInvokeAsync does in a MethodInterceptionAspect. It must have the same signature as OnInvokeAsync and return a Task, so that PostSharp can await the advice and return its task to the caller. <ReturnType> is always System.Threading.Tasks.Task.
The error usually comes from an advice declared async void, as in the following example.
using System;
using System.Threading.Tasks;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Serialization;
namespace Errors.LA0165_Error;
[PSerializable]
public class LogAttribute : MethodLevelAspect
{
[OnMethodInvokeAdvice]
public void OnInvoke( MethodInterceptionArgs args )
{
Console.WriteLine( $"Calling {args.Method.Name}." );
args.Proceed();
}
// The async advice returns void instead of Task.
[OnMethodInvokeAsyncAdvice]
public async void OnInvokeAsync( MethodInterceptionArgs args )
{
Console.WriteLine( $"Calling {args.Method.Name} asynchronously." );
await args.ProceedAsync();
}
}
public class OrderService
{
[Log]
public async Task PlaceOrderAsync( string product )
{
await Task.Yield();
Console.WriteLine( $"Order for {product} placed." );
}
}
public static class Program
{
public static async Task Main()
{
await new OrderService().PlaceOrderAsync( "Chair" );
}
}
PostSharp discards the invalid advice, so it also warns (LA0186) that PlaceOrderAsync, an async method, receives the synchronous OnInvoke advice without an async advice:
error LA0165: LA0165_Error.cs(21,23): Advice "PostSharp.Aspects.Advices.OnMethodInvokeAsyncAdvice" is not valid on method "Errors.LA0165_Error.LogAttribute.OnInvokeAsync(PostSharp.Aspects.MethodInterceptionArgs)": method return type must be "System.Threading.Tasks.Task".
warning LA0186: LA0165_Error.cs(31,23): Semantic advising for the "Errors.LA0165_Error.LogAttribute.OnInvoke(PostSharp.Aspects.MethodInterceptionArgs)" advice is enabled for the "Errors.LA0165_Error.OrderService.PlaceOrderAsync(System.String)" method, but the OnInvokeAsync advice is not implemented. To suppress this message either implement the [OnMethodInvokeAsyncAdvice] advice or set the SemanticallyAdvisedMethodKinds property of the master advice to 'None'.
Resolution
Make the advice method return Task: declare it async Task instead of async void.
In the following example, the async advice intercepts PlaceOrderAsync.
using System;
using System.Threading.Tasks;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Serialization;
namespace Errors.LA0165_Fixed;
[PSerializable]
public class LogAttribute : MethodLevelAspect
{
[OnMethodInvokeAdvice]
public void OnInvoke( MethodInterceptionArgs args )
{
Console.WriteLine( $"Calling {args.Method.Name}." );
args.Proceed();
}
// The async advice returns a Task, which PostSharp awaits.
[OnMethodInvokeAsyncAdvice]
public async Task OnInvokeAsync( MethodInterceptionArgs args )
{
Console.WriteLine( $"Calling {args.Method.Name} asynchronously." );
await args.ProceedAsync();
}
}
public class OrderService
{
[Log]
public async Task PlaceOrderAsync( string product )
{
await Task.Yield();
Console.WriteLine( $"Order for {product} placed." );
}
}
public static class Program
{
public static async Task Main()
{
await new OrderService().PlaceOrderAsync( "Chair" );
}
}
Calling PlaceOrderAsync asynchronously.
Order for Chair placed.
See Also
Reference
OnMethodInvokeAsyncAdvice
OnMethodInvokeAdvice
OnInvokeAsync
Other Resources
Advice Methods
Semantic Advising of Iterator and Async Methods