Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting (400) Bad Request. when trying to send GCM Message

I am trying to send message to GCM Server through C#.net

I found a good example that I am trying to use

http://www.codewithasp.net/2015/11/send-message-gcm-c-sharp-single-multiple.html

The problem is that I get "The remote server returned an error: (400) Bad Request." error whenever I try to Get the response from this line

            WebResponse wResponse = wRequest.GetResponse();

I tried to find what the prblem is, I changed the API code from Server to Android, to Browser, and the result is either (400) Bad request or (401) Unauthorized.

Not sure what I am doing wrong here, it looked very simple and straight forward in the example.

Help is much appreciated

Here is The code

        NotificationManager nm = new NotificationManager();
        List<string> ls = new List<string>(new string[] { "ABCDEFGHIJKLMNOPQRSTUVWXYZ" });

        nm.SendNotification(ls, " Hi.. This is a test","Hi.. Title",1);

and here is the class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Script.Serialization;
using System.Net;
using System.Text;
using System.IO;

namespace WebApplication1
{

    public class NotificationManager
    {
        private class NotificationMessage
        {
            public string Title;
            public string Message;
            public long ItemId;
        }

        public NotificationManager()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        public string SendNotification(List<string> deviceRegIds, string message, string title, long id)
        {
            try
            {
                string regIds = string.Join("\",\"", deviceRegIds);

                string AppId = "AIzaSyXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
                var SenderId = "1234567890";

                NotificationMessage nm = new NotificationMessage();
                nm.Title = title;
                nm.Message = message;
                nm.ItemId = id;

                var value = new JavaScriptSerializer().Serialize(nm);
                WebRequest wRequest;
                wRequest = WebRequest.Create("https://android.googleapis.com/gcm/send");
                wRequest.Method = "post";
                wRequest.ContentType = " application/json;charset=UTF-8";
                wRequest.Headers.Add(string.Format("Authorization: key={0}", AppId));

                wRequest.Headers.Add(string.Format("Sender: id={0}", SenderId));

                string postData = "{\"collapse_key\":\"score_update\",\"time_to_live\":108,\"delay_while_idle\":true,\"data\": { \"message\" : " + "\"" + value + "\",\"time\": " + "\"" + System.DateTime.Now.ToString() + "\"},\"registration_ids\":[\"" + regIds + "\"]}";

                Byte[] bytes = Encoding.UTF8.GetBytes(postData);
                wRequest.ContentLength = bytes.Length;

                Stream stream = wRequest.GetRequestStream();
                stream.Write(bytes, 0, bytes.Length);
                stream.Close();

                WebResponse wResponse = wRequest.GetResponse();

                stream = wResponse.GetResponseStream();

                StreamReader reader = new StreamReader(stream);

                String response = reader.ReadToEnd();

                HttpWebResponse httpResponse = (HttpWebResponse)wResponse;
                string status = httpResponse.StatusCode.ToString();

                reader.Close();
                stream.Close();
                wResponse.Close();

                if (status == "")
                {
                    return response;
                }
                else
                {
                    return "";
                }
            }
            catch( Exception ex)
            {
                return ex.ToString();
            }
        }
    }
}

Here is how I get the API ID and Sender ID

Sender ID

API ID

like image 943
asmgx Avatar asked Mar 12 '23 18:03

asmgx


2 Answers

I got the same error from sending a GCM Message via HttpWebRequests:

The remote server returned an error: (400) Bad Request.

StatusDescription: InvalidTokenFormat

But the issue wasn't the same. I just had the wrong url:

"https://fcm.googleapis.com/fcm/send/" //wrong
"https://fcm.googleapis.com/fcm/send"

It took me longer than I'd like to admit to figure that out. And I'd like to spare other people the trouble, from such a misleading error message.

like image 104
Aske B. Avatar answered Mar 19 '23 19:03

Aske B.


This is how i did it in C# :

public class VmFcmNotification
{
    public string body { get; set; }
    public string title { get; set; }
    public string icon { get; set; }
    public string text { get; set; }
    public string sound { get; set; }

}

public class VmFcmMessage
{
    /// <summary>
    /// This parameter specifies the recipient of a message.
    /// The value must be a registration token, notification key, or topic.
    /// Do not set this field when sending to multiple topics.
    /// </summary>
    public string to { get; set; }

    /// <summary>
    /// This parameter identifies a group of messages (e.g., with collapse_key: "Updates Available") that can be collapsed,
    /// so that only the last message gets sent when delivery can be resumed.
    /// This is intended to avoid sending too many of the same messages when the device comes back online or becomes active (see delay_while_idle).
    /// Note that there is no guarantee of the order in which messages get sent.
    /// Note: A maximum of 4 different collapse keys is allowed at any given time.
    /// This means a FCM connection server can simultaneously store 4 different send-to-sync messages per client app.
    /// If you exceed this number, there is no guarantee which 4 collapse keys the FCM connection server will keep.
    /// </summary>
    public string collapse_key { get; set; }

    /// <summary>
    /// This parameter, when set to true, allows developers to test a request without actually sending a message.
    /// The default value is false.
    /// </summary>
    public Boolean dry_run { get; set; }

    /// <summary>
    /// This parameter specifies a list of devices (registration tokens, or IDs) receiving a multicast message.
    /// It must contain at least 1 and at most 1000 registration tokens.
    /// Use this parameter only for multicast messaging, not for single recipients.
    /// Multicast messages (sending to more than 1 registration tokens) are allowed using HTTP JSON format only.
    /// </summary>
    public List<string> registration_ids { get; set; }


    public VmFcmNotification notification { get; set; }

}

Then i use this function to send :

public static Boolean SendToOneUser(String userToken, String msgTitle)
    {
        using (var client = new HttpClient())
        {
            var message = new VmFcmMessage();
            message.to = userToken;
            message.notification = new VmFcmNotification()
            {
                title = msgTitle,
                //body = desc,
                //text = desc
            };

            string postBody = JsonConvert.SerializeObject(message).ToString();

            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            var SERVER_KEY="key=AIza...........";
            client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", SERVER_KEY);

            var response = client.PostAsync("https://fcm.googleapis.com/fcm/send", new StringContent(postBody, Encoding.UTF8, "application/json"));
            var responseString = response.Result.Content.ReadAsStringAsync().Result;
            //TODO get response and handle send messages
            return true;
        }
    }
like image 43
Omid Heshmatinia Avatar answered Mar 19 '23 17:03

Omid Heshmatinia