0

I'm trying to send a push notification though Pushover API with attached image using C# .NET. The following code returns a json formatted error "message cannot be blank". But the message variable is not empty. Since SSL is outdated I tried using TLS 1.2 explicitly. The same error appears without the image parameter.

public async Task PushImage(string title, string message, Stream image, string userKey, string appKey)
{
    // This does not work - error "message cannot be blank"
    using (HttpClient httpClient = new HttpClient())
    {
        //specify to use TLS 1.2 as default connection
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

        MultipartFormDataContent form = new MultipartFormDataContent();
        form.Add(new StringContent(appKey), "token");
        form.Add(new StringContent(userKey), "user");
        form.Add(new StringContent(message), "message");
        var imageParameter = new StreamContent(image);
        imageParameter.Headers.ContentType = MediaTypeHeaderValue.Parse("image/png");
        form.Add(imageParameter, "attachment", "image.png");
        // Remove content type that is not in the docs
        foreach (var param in form)
            param.Headers.ContentType = null;

        HttpResponseMessage responseMessage = await httpClient.PostAsync(BaseApiUrl, form);
        if (responseMessage.IsSuccessStatusCode)
            return;

        string contentText = responseMessage.Content.ReadAsStringAsync().Result;
        var response = JsonConvert.DeserializeObject<PushResponse>(contentText);
        throw new ApplicationException(
            $"Push image request failed with status {(int)responseMessage.StatusCode} {responseMessage.StatusCode}: {response.Errors.JoinStrings(". ") ?? ""}");
    }
}

Result:

{"message":"cannot be blank","errors":["message cannot be blank"],"status":0,"request":"94152901-3b8f-45d6-ae6b-f7fc10b3439c"}

I've looked at the raw request through Charles and it appears more or less as the docs suggest. However there is a small difference.

Curl - which works - produces parameters that look like this:

--------------------------30e0433d33c92cae
Content-Disposition: form-data; name="message"

my message
--------------------------30e0433d33c92cae--

HttpClient - which does not yet work - produces this for each parameter:

--70ae375f-ef30-4885-8a8a-d38363080024
Content-Disposition: form-data; name=message

my message
--70ae375f-ef30-4885-8a8a-d38363080024--

Note the difference in quotes. If I intercept the message in Charles and enclose the parameter names in double quotes as well as increase Content-Length by the same amount, it works!

wezzix
  • 1,984
  • 1
  • 19
  • 18

1 Answers1

3

It turns out that you need to enclose the parameter names in double quotes, like so:

form.Add(new StringContent(appKey), "\"token\"");
form.Add(new StringContent(userKey), "\"user\"");
form.Add(new StringContent(message), "\"message\"");
...
form.Add(imageParameter, "\"attachment\"", "image.png");

Don't ask me why. I just want to get on with my life and forget this entire day I spent debugging this issue...

wezzix
  • 1,984
  • 1
  • 19
  • 18