You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

C# .NET调用Pushover API发送带图推送时遇‘消息不能为空’错误

解决Pushover API返回"message cannot be blank"但消息非空的问题

我之前在调用Pushover API发送带图通知时,也碰到过一模一样的"message cannot be blank"错误——明明消息变量有值,却被服务器判定为空。结合你描述的情况,问题大概率出在请求的格式编码或者参数匹配细节上,尤其是你提到的和curl请求的细微差异,这就是突破口。

下面是几个排查和解决的方向:

  • 检查请求的Content-Type与表单编码
    Pushover对请求格式有明确要求:带图片时必须用multipart/form-data,普通消息用application/x-www-form-urlencoded。很多时候.NET的HttpClient默认处理会出问题,比如误用StringContent代替专用的表单内容类,导致服务器无法正确解析参数。
    带图片的正确做法是用MultipartFormDataContent构建请求,普通消息用FormUrlEncodedContent,不要手动拼接字符串。

  • 确认参数键名完全匹配(大小写敏感!)
    Pushover的API参数是严格按小写键名识别的,比如必须是message,而不是Message或者msg。如果你用字典、匿名类型或者模型类传递参数,一定要确保键名/属性名是小写的——比如用Dictionary<string, string>时,键要写"message",而不是首字母大写的"Message",否则服务器会识别不到这个参数,直接返回“消息为空”的错误。

  • 验证TLS 1.2的启用是否生效
    虽然你说已经启用了TLS 1.2,但要注意代码的执行顺序:必须在初始化HttpClient之前设置TLS版本。比如在.NET Framework中要这样写:

    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
    var client = new HttpClient();
    

    而在.NET Core/.NET 5+中,更推荐用HttpClientHandler配置:

    var handler = new HttpClientHandler();
    handler.SslProtocols = SslProtocols.Tls12;
    var client = new HttpClient(handler);
    

    确保这个配置生效,避免因SSL问题导致请求被截断,间接引发参数解析错误。

  • 对比curl和你的请求的具体差异
    既然你已经用Charles抓包了,重点对比这几个点:

    • 请求头的Content-Type是否正确(multipart请求要带boundary值)
    • 每个表单字段的name属性是否和curl一致,比如curl里的-F message="xxx"对应请求里的字段name必须是message
    • 消息内容是否被正确编码,有没有额外的转义或空格导致服务器解析失败

正确的带图片请求示例代码

// 启用TLS 1.2(.NET Framework环境)
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

using (var client = new HttpClient())
{
    var formData = new MultipartFormDataContent();
    
    // 添加必填参数,键名必须小写
    formData.Add(new StringContent("你的Pushover Token"), "token");
    formData.Add(new StringContent("你的用户/群组Key"), "user");
    formData.Add(new StringContent("这是测试消息,内容不为空"), "message");
    
    // 添加图片附件
    using (var imageStream = File.OpenRead(@"C:\path\to\your\image.jpg"))
    {
        var imageContent = new StreamContent(imageStream);
        imageContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/jpeg");
        // 这里的name必须是"attachment",filename可以自定义
        formData.Add(imageContent, "attachment", "test.jpg");
    }
    
    var response = await client.PostAsync("https://api.pushover.net/1/messages.json", formData);
    var responseBody = await response.Content.ReadAsStringAsync();
    Console.WriteLine(responseBody);
}

无图片的普通请求示例

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

using (var client = new HttpClient())
{
    var formData = new FormUrlEncodedContent(new Dictionary<string, string>
    {
        {"token", "你的Token"},
        {"user", "你的用户Key"},
        {"message", "普通测试消息"}
    });
    
    var response = await client.PostAsync("https://api.pushover.net/1/messages.json", formData);
    var responseBody = await response.Content.ReadAsStringAsync();
    Console.WriteLine(responseBody);
}

核心思路就是:确保请求的参数名、格式、编码完全符合Pushover的要求,通过对比curl的正确请求细节,找出你的.NET请求中的差异点,就能解决这个看似奇怪的“消息为空”错误。

内容的提问来源于stack exchange,提问作者wezzix

火山引擎 最新活动