JeffreySu/WeiXinMPSDK · error · ArgumentNullException

httpContext

Error message

httpContext

What it means

The private TenPayNotifyHandler constructor validates its httpContext argument and throws ArgumentNullException naming "httpContext" when it is null. The HttpContext is required for reading request headers and body during payment notification processing.

Solutions

  1. Only create TenPayNotifyHandler inside an active ASP.NET Core request (e.g. from an MVC/API controller action)
  2. Pass IHttpContextAccessor.HttpContext only after checking it is not null
  3. In tests, supply a valid DefaultHttpContext instance
  4. Add an early null check on httpContext before calling the factory

Example fix

// before
var handler = TenPayNotifyHandler.Create(httpContext, settings);
// after
if (httpContext == null) throw new InvalidOperationException("TenPayNotifyHandler 只能在 HTTP 请求上下文中使用。");
var handler = TenPayNotifyHandler.Create(httpContext, settings);
Defensive patterns

Strategy: type-guard

Validate before calling

if (HttpContext is null) return BadRequest("必须在 HTTP 请求上下文中处理支付通知。");

Type guard

bool HasHttpContext(HttpContext? ctx) => ctx is not null;

Try / catch

try { var handler = TenPayNotifyHandler.Create(httpContext, settings); ... }
catch (ArgumentNullException ex) when (ex.ParamName == "httpContext") { return StatusCode(500, "缺少 HttpContext"); }

Prevention

When it happens

Trigger: Calling the factory/method that creates TenPayNotifyHandler while passing a null HttpContext (e.g. outside an HTTP request pipeline, or in unit tests with no HttpContext).

Common situations: Invoking notify-handler logic from background jobs or console code where there is no current HttpContext; tests constructing the handler manually.

Related errors


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

Appendix: source

Thrown at src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/HttpHandlers/TenPayNotifyHandler.cs:132

        }

        /// <summary>
        /// 使用自定义请求体上限的兼容构造函数。新代码优先使用 <see cref="CreateAsync"/>。
        /// </summary>
        public TenPayNotifyHandler(HttpContext httpContext, ISenparcWeixinSettingForTenpayV3 senparcWeixinSettingForTenpayV3, int maxBodyBytes)
            : this(
                httpContext,
                senparcWeixinSettingForTenpayV3,
                ReadBodyAsync(httpContext, maxBodyBytes, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult())
        {
        }

        private TenPayNotifyHandler(
            HttpContext httpContext,
            ISenparcWeixinSettingForTenpayV3 senparcWeixinSettingForTenpayV3,
            NotificationBody notificationBody)
        {
            _ = httpContext ?? throw new ArgumentNullException(nameof(httpContext));
            _httpContext = httpContext;
            _tenpayV3Setting = senparcWeixinSettingForTenpayV3 ?? Senparc.Weixin.Config.SenparcWeixinSetting.TenpayV3Setting;

            if (!_tenpayV3Setting.EncryptionType.HasValue)
            {
                throw new Senparc.Weixin.Exceptions.WeixinException("没有设置证书加密类型(EncryptionType)");
            }

            Body = notificationBody.Body;
            NotifyRequest = notificationBody.NotifyRequest;
        }

        /// <summary>
        /// 异步创建通知处理器,支持请求取消并限制请求体大小。
        /// </summary>
        public static async Task<TenPayNotifyHandler> CreateAsync(
            HttpContext httpContext,
            ISenparcWeixinSettingForTenpayV3 senparcWeixinSettingForTenpayV3 = null,

View on GitHub (pinned to be573f6f94)