JeffreySu/WeiXinMPSDK · error · MessageHandlerException

请使用异步方法 OnExecutingAsync()

Error message

请使用异步方法 OnExecutingAsync()

What it means

In the MP MessageHandler, the synchronous OnExecuting override is marked [Obsolete(..., true)] and unconditionally throws MessageHandlerException. The library migrated its message-processing pipeline to async (OnExecutingAsync), so calling the sync hook is a compile-time-warning but run-time hard error: the sync path is no longer supported.

Solutions

  1. Replace all synchronous handler invocation with the async pipeline: call MessageHandler.ExecuteAsync() (or the async request-message extension), which uses OnExecutingAsync/OnExecutedAsync.
  2. Move your pre-processing logic from an OnExecuting override into OnExecutingAsync override in your custom handler.
  3. Update old sync extension methods / framework wrappers (e.g. MessageHandler<T>.Execute sync overloads) to their Async equivalents.
  4. Treat compiler CS0619 (obsolete-with-error) on OnExecuting as the signal: fix call sites at compile time rather than at runtime.

Example fix

// before
messageHandler.OnExecuting();
messageHandler.Execute();

// after
await messageHandler.ExecuteAsync(cancellationToken); // pipeline calls OnExecutingAsync internally

// custom handler
public override async Task OnExecutingAsync(CancellationToken ct)
{
    // pre-processing here
}
Defensive patterns

Strategy: type-guard

Validate before calling

// compile-time: treat Obsolete-with-error as a build failure
#pragma warning disable CS0619 // deliberately detect sync usage
// do NOT reference messageHandler.OnExecuting();
#pragma warning restore CS0619

Type guard

bool UsesAsyncPipeline(MessageHandler<TRequest, TResponse> h) =>
    h.GetType().GetMethod(nameof(MessageHandler<TRequest, TResponse>.OnExecutingAsync)) != null;

Try / catch

try { await messageHandler.ExecuteAsync(ct); }
catch (MessageHandlerException ex) when (ex.Message.Contains("OnExecutingAsync"))
{
    logger.LogError(ex, "Sync OnExecuting invoked; migrate to ExecuteAsync");
    throw;
}

Prevention

When it happens

Trigger: Calling messageHandler.OnExecuting() directly, overriding it in a subclass and relying on the base synchronous Execute() pipeline, or using legacy sync extension/pipeline code (e.g. old Weixin MpMessageHandler helper overloads) that invokes the sync hook.

Common situations: Migrating code written against older Senparc.Weixin versions (pre-async pipeline) to a newer version where the sync OnExecuting/OnExecuted were made throw-on-use; following outdated blog samples that call sync message handler methods inside ASP.NET (non-Core) controllers.

Understand the failure class

Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.

Related errors


AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12). Data as JSON: /api/errors/afdb29db9edf9a82. Report an issue: GitHub.

Appendix: source

Thrown at src/Senparc.Weixin.MP/Senparc.Weixin.MP/MessageHandlers/MessageHandler.cs:358

        //        return null;
        //    }

        //    var responseMessage = RequestMessage.CreateResponseMessage<TR>();
        //    responseMessage.Content = content;
        //    return responseMessage;
        //}

        #endregion

        #region 消息处理

        /// <summary>
        /// OnExecuting
        /// </summary>
        [Obsolete("请使用异步方法 OnExecutingAsync()", true)]
        public override void OnExecuting()
        {
            throw new MessageHandlerException("请使用异步方法 OnExecutingAsync()");
        }

        [Obsolete("请使用异步方法 OnExecutedAsync()", true)]
        public override void OnExecuted()
        {
            throw new MessageHandlerException("请使用异步方法 OnExecutedAsync()");
        }

        #endregion }
    }
}

View on GitHub (pinned to be573f6f94)