54

I am using this code to send notification message by C# with GCM, using Winforms, Webforms, whatever. Now I want to send to FCM (Firebase Cloud Messaging). Should I update my code? :

public class AndroidGCMPushNotification
{
    public AndroidGCMPushNotification()
    {
        //
        // TODO: Add constructor logic here
        //
    }
    public string SendNotification(string deviceId, string message)
    {
        string SERVER_API_KEY = "server api key";        
        var SENDER_ID = "application number";
        var value = message;
        WebRequest tRequest;
        tRequest = WebRequest.Create("https://android.googleapis.com/gcm/send");
        tRequest.Method = "post";
        tRequest.ContentType = " application/x-www-form-urlencoded;charset=UTF-8";
        tRequest.Headers.Add(string.Format("Authorization: key={0}", SERVER_API_KEY));

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

        string postData = "collapse_key=score_update&time_to_live=108&delay_while_idle=1&data.message=" + value + "&data.time=" + System.DateTime.Now.ToString() + "&registration_id=" + deviceId + "";
        Console.WriteLine(postData);
        Byte[] byteArray = Encoding.UTF8.GetBytes(postData);
        tRequest.ContentLength = byteArray.Length;

        Stream dataStream = tRequest.GetRequestStream();
        dataStream.Write(byteArray, 0, byteArray.Length);
        dataStream.Close();

        WebResponse tResponse = tRequest.GetResponse();

        dataStream = tResponse.GetResponseStream();

        StreamReader tReader = new StreamReader(dataStream);

        String sResponseFromServer = tReader.ReadToEnd();


        tReader.Close();
        dataStream.Close();
        tResponse.Close();
        return sResponseFromServer;
    }
}

but the GCM was changed to FCM. Is this same code to send the notification? Where can I find the SERVER_API_KEY? Is the same solution?

Teste
  • 661
  • 1
  • 6
  • 7
  • 2
    If you're interested in the **2019 version** which uses the .Net Admin SDK, please check my answer [here](https://stackoverflow.com/a/54729521/4724142) – Alfred Waligo Feb 21 '19 at 22:22

13 Answers13

82

firebase cloud messaging with c#: working all .net platform (asp.net, .netmvc, .netcore)

        WebRequest tRequest = WebRequest.Create("https://fcm.googleapis.com/fcm/send");
        tRequest.Method = "post";
        //serverKey - Key from Firebase cloud messaging server  
        tRequest.Headers.Add(string.Format("Authorization: key={0}", "AIXXXXXX...."));
        //Sender Id - From firebase project setting  
        tRequest.Headers.Add(string.Format("Sender: id={0}", "XXXXX.."));
        tRequest.ContentType = "application/json";
        var payload = new
        {
            to = "e8EHtMwqsZY:APA91bFUktufXdsDLdXXXXXX..........XXXXXXXXXXXXXX",
            priority = "high",
            content_available = true,
            notification = new
            {
                body = "Test",
                title = "Test",
                badge = 1
            },
            data = new 
            {
                key1 = "value1",
                key2 = "value2"
            }

        };

        string postbody = JsonConvert.SerializeObject(payload).ToString();
        Byte[] byteArray = Encoding.UTF8.GetBytes(postbody);
        tRequest.ContentLength = byteArray.Length;
        using (Stream dataStream = tRequest.GetRequestStream())
        {
            dataStream.Write(byteArray, 0, byteArray.Length);
            using (WebResponse tResponse = tRequest.GetResponse())
            {
                using (Stream dataStreamResponse = tResponse.GetResponseStream())
                {
                    if (dataStreamResponse != null) using (StreamReader tReader = new StreamReader(dataStreamResponse))
                        {
                            String sResponseFromServer = tReader.ReadToEnd();
                            //result.Response = sResponseFromServer;
                        }
                }
            }
        }
JMK
  • 27,273
  • 52
  • 163
  • 280
Osama Hassan
  • 821
  • 6
  • 3
21

Here is another approach of writing Notification Service inside ASP.Net REST API.

public async Task<bool> NotifyAsync(string to, string title, string body)
{
    try
    {
        // Get the server key from FCM console
        var serverKey = string.Format("key={0}", "Your server key - use app config");

        // Get the sender id from FCM console
        var senderId = string.Format("id={0}", "Your sender id - use app config");

        var data = new
        {
            to, // Recipient device token
            notification = new { title, body }
        };

        // Using Newtonsoft.Json
        var jsonBody = JsonConvert.SerializeObject(data);

        using (var httpRequest = new HttpRequestMessage(HttpMethod.Post, "https://fcm.googleapis.com/fcm/send"))
        {
            httpRequest.Headers.TryAddWithoutValidation("Authorization", serverKey);
            httpRequest.Headers.TryAddWithoutValidation("Sender", senderId);
            httpRequest.Content = new StringContent(jsonBody, Encoding.UTF8, "application/json");

            using (var httpClient = new HttpClient())
            {
                var result = await httpClient.SendAsync(httpRequest);

                if (result.IsSuccessStatusCode)
                {
                    return true;
                }
                else
                {
                    // Use result.StatusCode to handle failure
                    // Your custom error handler here
                    _logger.LogError($"Error sending notification. Status Code: {result.StatusCode}");
                }
            }
        }
    }
    catch (Exception ex)
    {
        _logger.LogError($"Exception thrown in Notify Service: {ex}");
    }

    return false;
}

References:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
Santosh
  • 2,430
  • 5
  • 33
  • 47
  • Good answer, just one problem with it is that there is no need to go with a disposable `HttpClient` but use a singleton instance of it. – Vedran Mandić Feb 22 '18 at 09:50
  • 1
    @VedranMandić Agreed. Above example if good enough for quick reference though. Check for HttpClientFactory in upcoming ASP.net Core 2.1 (https://blogs.msdn.microsoft.com/webdev/2018/02/02/asp-net-core-2-1-roadmap/#httpclientfactory). – Santosh Apr 10 '18 at 10:32
  • @Santosh if you want to broadcast message to all devices? What should you write to "to" variable? Can we send empty or comma separated etc.. ? Thanks – Fuat May 06 '18 at 21:10
  • @ShortlyFD Sending to multiple devices is a bit different. Google FCM supports messaging to Device Groups or Topics. Check https://firebase.google.com/docs/cloud-messaging/android/send-multiple – Santosh May 07 '18 at 04:59
10

I have posted this answer as this question was viewed most and this server side code was written in VS 2015 in C# for sending push notification either single device based on device id or subscribed topic to Xamarin Android app

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

    public bool Successful
    {
        get;
        set;
    }

    public string Response
    {
        get;
        set;
    }
    public Exception Error
    {
        get;
        set;
    }



    public FCMPushNotification SendNotification(string _title, string _message, string _topic)
    {
        FCMPushNotification result = new FCMPushNotification();
        try
        {
            result.Successful = true;
            result.Error = null;
           // var value = message;
            var requestUri = "https://fcm.googleapis.com/fcm/send";

            WebRequest webRequest = WebRequest.Create(requestUri);
            webRequest.Method = "POST";
            webRequest.Headers.Add(string.Format("Authorization: key={0}", YOUR_FCM_SERVER_API_KEY));
            webRequest.Headers.Add(string.Format("Sender: id={0}", YOUR_FCM_SENDER_ID));
            webRequest.ContentType = "application/json";

            var data = new
            {
               // to = YOUR_FCM_DEVICE_ID, // Uncoment this if you want to test for single device
               to="/topics/"+_topic, // this is for topic 
                notification=new
                {
                    title=_title,
                    body=_message,
                    //icon="myicon"
                }
            };
            var serializer = new JavaScriptSerializer();
            var json = serializer.Serialize(data);

            Byte[] byteArray = Encoding.UTF8.GetBytes(json);

            webRequest.ContentLength = byteArray.Length;
            using (Stream dataStream = webRequest.GetRequestStream())
            {
                dataStream.Write(byteArray, 0, byteArray.Length);

                using (WebResponse webResponse = webRequest.GetResponse())
                {
                    using (Stream dataStreamResponse = webResponse.GetResponseStream())
                    {
                        using (StreamReader tReader = new StreamReader(dataStreamResponse))
                        {
                            String sResponseFromServer = tReader.ReadToEnd();
                            result.Response = sResponseFromServer;
                        }
                    }
                }
            }

        }
        catch(Exception ex)
        {
            result.Successful = false;
            result.Response = null;
            result.Error = ex;
        }
        return result;
    }
}

and its uses

// start sending push notification to apps
                FCMPushNotification fcmPush = new FCMPushNotification();                    
                fcmPush.SendNotification("your notificatin title", "Your body message","news");
                // end push notification
halfer
  • 19,824
  • 17
  • 99
  • 186
Ishwor Khanal
  • 1,312
  • 18
  • 30
5

Yes, you should update your code to use Firebase Messaging interface. There's a GitHub Project for that here.

using Stimulsoft.Base.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;

namespace _WEBAPP
{
    public class FireBasePush
    {
        private string FireBase_URL = "https://fcm.googleapis.com/fcm/send";
        private string key_server;
        public FireBasePush(String Key_Server)
        {
            this.key_server = Key_Server;
        }
        public dynamic SendPush(PushMessage message)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(FireBase_URL);
            request.Method = "POST";
            request.Headers.Add("Authorization", "key=" + this.key_server);
            request.ContentType = "application/json";
            string json = JsonConvert.SerializeObject(message);
            //json = json.Replace("content_available", "content-available");
            byte[] byteArray = Encoding.UTF8.GetBytes(json);
            request.ContentLength = byteArray.Length;
            Stream dataStream = request.GetRequestStream();
            dataStream.Write(byteArray, 0, byteArray.Length);
            dataStream.Close();
            HttpWebResponse respuesta = (HttpWebResponse)request.GetResponse();
            if (respuesta.StatusCode == HttpStatusCode.Accepted || respuesta.StatusCode == HttpStatusCode.OK || respuesta.StatusCode == HttpStatusCode.Created)
            {
                StreamReader read = new StreamReader(respuesta.GetResponseStream());
                String result = read.ReadToEnd();
                read.Close();
                respuesta.Close();
                dynamic stuff = JsonConvert.DeserializeObject(result);

                return stuff;
            }
            else
            {
                throw new Exception("Ocurrio un error al obtener la respuesta del servidor: " + respuesta.StatusCode);
            }
        }


    }
    public class PushMessage
    {
        private string _to;
        private PushMessageData _notification;

        private dynamic _data;
        private dynamic _click_action;
        public dynamic data
        {
            get { return _data; }
            set { _data = value; }
        }

        public string to
        {
            get { return _to; }
            set { _to = value; }
        }
        public PushMessageData notification
        {
            get { return _notification; }
            set { _notification = value; }
        }

        public dynamic click_action
        {
            get
            {
                return _click_action;
            }

            set
            {
                _click_action = value;
            }
        }
    }

    public class PushMessageData
    {
        private string _title;
        private string _text;
        private string _sound = "default";
        //private dynamic _content_available;
        private string _click_action;
        public string sound
        {
            get { return _sound; }
            set { _sound = value; }
        }

        public string title
        {
            get { return _title; }
            set { _title = value; }
        }
        public string text
        {
            get { return _text; }
            set { _text = value; }
        }

        public string click_action
        {
            get
            {
                return _click_action;
            }

            set
            {
                _click_action = value;
            }
        }
    }
}
checkmate711
  • 3,301
  • 2
  • 35
  • 45
4

Based on Teste's code .. I can confirm the following works. I can't say whether or not this is "good" code, but it certainly works and could get you back up and running quickly if you ended up with GCM to FCM server problems!

public AndroidFCMPushNotificationStatus SendNotification(string serverApiKey, string senderId, string deviceId, string message)
{
    AndroidFCMPushNotificationStatus result = new AndroidFCMPushNotificationStatus();

    try
    {
        result.Successful = false;
        result.Error = null;

        var value = message;
        WebRequest tRequest = WebRequest.Create("https://fcm.googleapis.com/fcm/send");
        tRequest.Method = "post";
        tRequest.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
        tRequest.Headers.Add(string.Format("Authorization: key={0}", serverApiKey));
        tRequest.Headers.Add(string.Format("Sender: id={0}", senderId));

        string postData = "collapse_key=score_update&time_to_live=108&delay_while_idle=1&data.message=" + value + "&data.time=" + System.DateTime.Now.ToString() + "&registration_id=" + deviceId + "";

        Byte[] byteArray = Encoding.UTF8.GetBytes(postData);
        tRequest.ContentLength = byteArray.Length;

        using (Stream dataStream = tRequest.GetRequestStream())
        {
            dataStream.Write(byteArray, 0, byteArray.Length);

            using (WebResponse tResponse = tRequest.GetResponse())
            {
                using (Stream dataStreamResponse = tResponse.GetResponseStream())
                {
                    using (StreamReader tReader = new StreamReader(dataStreamResponse))
                    {
                        String sResponseFromServer = tReader.ReadToEnd();
                        result.Response = sResponseFromServer;
                    }
                }
            }
        }
    }
    catch (Exception ex)
    {
        result.Successful = false;
        result.Response = null;
        result.Error = ex;
    }

    return result;
}


public class AndroidFCMPushNotificationStatus
{
    public bool Successful
    {
        get;
        set;
    }

    public string Response
    {
        get;
        set;
    }
    public Exception Error
    {
        get;
        set;
    }
}
Steven Elliott
  • 3,214
  • 5
  • 29
  • 40
3

You need change url from https://android.googleapis.com/gcm/send to https://fcm.googleapis.com/fcm/send and change your app library too. this tutorial can help you https://firebase.google.com/docs/cloud-messaging/server#implementing-http-connection-server-protocol

Gustavo Rozolin
  • 1,070
  • 2
  • 13
  • 21
3

Try to send a json object. Replace this:

tRequest.ContentType = " application/x-www-form-urlencoded;charset=UTF-8";    
string postData = "collapse_key=score_update&time_to_live=108&delay_while_idle=1&data.message=" + value + "&data.time=" + System.DateTime.Now.ToString() + "&registration_id=" + deviceId + "";
        Console.WriteLine(postData);
        Byte[] byteArray = Encoding.UTF8.GetBytes(postData);

For this:

tRequest.ContentType = "application/json"; 
    var data = new
        {
            to = deviceId,
            notification = new
            {
                body = "This is the message",
                title = "This is the title",
                icon = "myicon"
            }
        };

        var serializer = new JavaScriptSerializer();
        var json = serializer.Serialize(data);

        Byte[] byteArray = Encoding.UTF8.GetBytes(json);
3

Here's the code for server side firebase cloud request from C# / Asp.net.
Please note that your client side should have same topic.
e.g.

FirebaseMessaging.getInstance().subscribeToTopic("news");

public String SendNotificationFromFirebaseCloud()
{
    var result = "-1";
    var webAddr = "https://fcm.googleapis.com/fcm/send";

    var httpWebRequest = (HttpWebRequest)WebRequest.Create(webAddr);
    httpWebRequest.ContentType = "application/json";
    httpWebRequest.Headers.Add("Authorization:key=" + YOUR_FIREBASE_SERVER_KEY);
    httpWebRequest.Method = "POST";

    using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
    {
        string json = "{\"to\": \"/topics/news\",\"data\": {\"message\": \"This is a Firebase Cloud Messaging Topic Message!\",}}";


        streamWriter.Write(json);
        streamWriter.Flush();
    }

    var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
    using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
    {
        result = streamReader.ReadToEnd();
    }

    return result;
}
Pang
  • 9,564
  • 146
  • 81
  • 122
Aditya varale
  • 447
  • 8
  • 6
2

You can use this library, makes it seamless to send push notifications using Firebase Service from a C# backend download here

Frank Odoom
  • 1,545
  • 18
  • 19
  • COuld you please tell me how to send notification for all the registered devices without knowing the ids. Thanks a lot. – Nelson Parra Aug 22 '18 at 14:23
  • Hi Nelson, The to value can be a device's registration token, a device group's notification key, or a single topic (prefixed with /topics/). To send to multiple topics, use the condition parameter. Check these references. https://firebase.google.com/docs/cloud-messaging/http-server-ref https://firebase.google.com/docs/cloud-messaging/android/topic-messaging – Frank Odoom Aug 22 '18 at 20:23
  • Hi Frank, thank you for the answer, I discovered another way to do that with appcenter, firebase and xamarin the best and easy way possible and it worked like a charm. Now I'm receiving and sending push notifications for all registered devices. – Nelson Parra Aug 23 '18 at 21:45
  • Share the goof news :-) – Frank Odoom Aug 24 '18 at 09:35
1
 public  SendNotice(int deviceType, string deviceToken, string message, int badge, int status, string sound)
    {
        AndroidFCMPushNotificationStatus result = new AndroidFCMPushNotificationStatus();
        try
        {
            result.Successful = false;
            result.Error = null;
            var value = message;
            WebRequest tRequest = WebRequest.Create("https://fcm.googleapis.com/fcm/send");
            tRequest.Method = "post";
            tRequest.ContentType = "application/json";
            var serializer = new JavaScriptSerializer();
            var json = "";
            tRequest.Headers.Add(string.Format("Authorization: key={0}", "AA******"));
            tRequest.Headers.Add(string.Format("Sender: id={0}", "11********"));
           if (DeviceType == 2)
            {
                var body = new
                  {
                      to = deviceToken,
                      data = new
                      {
                          custom_notification = new
                            {
                                title = "Notification",
                                body = message,
                                sound = "default",
                                priority = "high",
                                show_in_foreground = true,
                                targetScreen = notificationType,//"detail",
                                                                },
                      },

                      priority = 10
                  };

                json = serializer.Serialize(body);
            }
            else
            {
                var body = new
                {
                    to = deviceToken,
                    content_available = true,
                    notification = new
                    {
                        title = "Notification",
                        body = message,
                        sound = "default",
                        show_in_foreground = true,
                    },
                    data = new
                    {
                        targetScreen = notificationType,
                        id = 0,
                    },
                    priority = 10
                };
                json = serializer.Serialize(body);
            }

            Byte[] byteArray = Encoding.UTF8.GetBytes(json);

            tRequest.ContentLength = byteArray.Length;

            using (Stream dataStream = tRequest.GetRequestStream())
            {
                dataStream.Write(byteArray, 0, byteArray.Length);

                using (WebResponse tResponse = tRequest.GetResponse())
                {
                    using (Stream dataStreamResponse = tResponse.GetResponseStream())
                    {
                        using (StreamReader tReader = new StreamReader(dataStreamResponse))
                        {
                            String sResponseFromServer = tReader.ReadToEnd();
                            result.Response = sResponseFromServer;
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            result.Successful = false;
            result.Response = null;
            result.Error = ex;
        }
}
Dinesh.net
  • 79
  • 1
  • 9
1

I write this code and It's worked for me .

public static string ExcutePushNotification(string title, string msg, string fcmToken, object data) 
{

        var serverKey = "AAAA*******************";
        var senderId = "3333333333333";


        var result = "-1";

        var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://fcm.googleapis.com/fcm/send");
        httpWebRequest.ContentType = "application/json";
        httpWebRequest.Headers.Add(string.Format("Authorization: key={0}", serverKey));
        httpWebRequest.Headers.Add(string.Format("Sender: id={0}", senderId));
        httpWebRequest.Method = "POST";


        var payload = new
        {
            notification = new
            {
                title = title,
                body = msg,
                sound = "default"
            },

            data = new
            {
                info = data
            },
            to = fcmToken,
            priority = "high",
            content_available = true,

        };


        var serializer = new JavaScriptSerializer();

        using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
        {
            string json = serializer.Serialize(payload);
            streamWriter.Write(json);
            streamWriter.Flush();
        }

        var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
        using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
        {
            result = streamReader.ReadToEnd();
        }
        return result;
}
1

I am using this approach and it is working fine:

 public class PushNotification
 {
     private static readonly ILog Logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        // firebase
     private static Uri FireBasePushNotificationsURL = new Uri("https://fcm.googleapis.com/fcm/send");
     private static string ServerKey = ConfigurationManager.AppSettings["FIREBASESERVERKEY"];

     public static async Task<bool> SendPushNotification(List<SendNotificationModel> notificationData)
     {
         try
         {
             bool sent = false;         
             foreach (var data in notificationData)
             {
                 var messageInformation = new Message()
                 {
                     notification = new Notification()
                     {
                         title = data.Title,
                         text = data.Message,
                         ClickAction = "FCM_PLUGIN_ACTIVITY"
                      },
                      data = data.data,
                      priority="high",
                      to =data.DeviceId
                 };
                 string jsonMessage = JsonConvert.SerializeObject(messageInformation);

                 //Create request to Firebase API
                 var request = new HttpRequestMessage(HttpMethod.Post, FireBasePushNotificationsURL);

                 request.Headers.TryAddWithoutValidation("Authorization", "key=" + ServerKey);
                 request.Content = new StringContent(jsonMessage, Encoding.UTF8, "application/json");

                 HttpResponseMessage result;
                 using (var client = new HttpClient())
                 {
                     result = await client.SendAsync(request);
                     sent =  result.IsSuccessStatusCode;
                 }             
             }

                return sent;
         }
         catch(Exception ex)
         {
             Logger.Error(ex);
             return false;
          }
    }
 }
Divya Agrawal
  • 300
  • 1
  • 2
  • 15
0

Following Approach, I have used for writing Firebase Notification Service inside ASP.Net REST API.

public async Task<bool> NotifyAsync(string to, string title, string body)
    {
        try
        {
            //Server key from FCM console
            var serverKey = string.Format("key={0}", "Provide your Server key here from Fibase console");

            //Sender id from FCM console
            var senderId = string.Format("id={0}", "Provide your Sender Id here from Firebase Console");

            var data = new
            {
                to, // Recipient device token
                notification = new { title, body }
            };

            // Using Newtonsoft.Json
            var jsonBody = JsonConvert.SerializeObject(data);

            using (var httpRequest = new HttpRequestMessage(HttpMethod.Post, "https://fcm.googleapis.com/fcm/send"))
            {
                httpRequest.Headers.TryAddWithoutValidation("Authorization", serverKey);
                httpRequest.Headers.TryAddWithoutValidation("Sender", senderId);
                httpRequest.Content = new StringContent(jsonBody, Encoding.UTF8, "application/json");

                using (var httpClient = new HttpClient())
                {
                    var result = await httpClient.SendAsync(httpRequest);

                    if (result.IsSuccessStatusCode)
                    {
                        return true;
                    }
                    else
                    {
                        // Use result.StatusCode to handle failure
                        // Your custom error handler here
                        return false;
                    }
                }
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }

        return false;
    }

Refer This blog for send Group Notification https://firebase.google.com/docs/cloud-messaging/android/send-multiple