Home » ASP » ASP.MVC » Service Worker, Push Notification and Asp.Net MVC – Part 3 of 3 Server Side

Service Worker, Push Notification and Asp.Net MVC – Part 3 of 3 Server Side

I previously discussed about how to configure a web push notification from the client side perspective as well as how to send the notification from an ASP.Net code which could be sent from Azure Webjobs. The remaining part is how do you send to multiple devices of one user. If you have a single browser used by a user, the initial solution is good. However, the reality is that users use multiple devices. Users can use not only different browsers on different machines but also jump from computer to phone and so on. The idea is to register subscription by device and not by user.

Google Firebase documentation explains briefly the “Device group messaging” but the page talks more about Topic. I couldn’t figure out how to use the device group messaging but could use Topic for the same matter. The idea is to use a single topic per user and send a message to this topic.

The first big change is to add a subscribe method and unsubscribe that work with the topic api.

public bool UnRegisterTopic(string userIdentifierForAllDevices, string singleDeviceNoticationKey)
{
	var serverApiKey = ConfigurationManager.AppSettings["FirebaseServerKey"];
	var firebaseGoogleUrl = $"https://iid.googleapis.com/iid/v1/{singleDeviceNoticationKey}/rel/topics/{userIdentifierForAllDevices}";

	var httpClient = new WebClient();
	httpClient.Headers.Add("Content-Type", "application/json");
	httpClient.Headers.Add(HttpRequestHeader.Authorization, "key=" + serverApiKey);

	object data = new { };
	var json = JsonConvert.SerializeObject(data);
	Byte[] byteArray = Encoding.UTF8.GetBytes(json);
	var responsebytes = httpClient.UploadData(firebaseGoogleUrl, "DELETE", byteArray);
	string responsebody = Encoding.UTF8.GetString(responsebytes);
	dynamic responseObject = JsonConvert.DeserializeObject(responsebody);

	return responseObject.success == "1";
}
public bool RegisterTopic(string userIdentifierForAllDevices, string singleDeviceNoticationKey)
{
	var serverApiKey = ConfigurationManager.AppSettings["FirebaseServerKey"];
	var firebaseGoogleUrl = $"https://iid.googleapis.com/iid/v1/{singleDeviceNoticationKey}/rel/topics/{userIdentifierForAllDevices}";

	var httpClient = new WebClient();
	httpClient.Headers.Add("Content-Type", "application/json");
	httpClient.Headers.Add(HttpRequestHeader.Authorization, "key=" + serverApiKey);

	object data = new{};
	var json = JsonConvert.SerializeObject(data);
	Byte[] byteArray = Encoding.UTF8.GetBytes(json);
	var responsebytes = httpClient.UploadData(firebaseGoogleUrl, "POST", byteArray);
	string responsebody = Encoding.UTF8.GetString(responsebytes);
	dynamic responseObject = JsonConvert.DeserializeObject(responsebody);

	return responseObject.success == "1";
}

There is quite repetition in that code and you can improve it easily. The biggest change is the URL. Not only the URL domain is different (before https://fcm.googleapis.com/fcm/send and now https://iid.googleapis.com/), it has different route portions. The first part is the device notification key which is the token generated by the client side from the method “getToken”. The second portion of the route is the user identifier which I use as topic. If you really need topic across users, you can just use a string with the category needed. In my case, it is just the unique GUID of the user. This POST HTTP call will register the device for the user by a topic which is the user ID.

To send a message to the user, on all devices, the code needs also to change.

public bool QueueMessage(string to, string title, string message, string urlNotificationClick)
{
	if (string.IsNullOrEmpty(to))
	{
		return false;
	}
	var serverApiKey = ConfigurationManager.AppSettings["FirebaseServerKey"];
	var firebaseGoogleUrl = "https://fcm.googleapis.com/fcm/send";

	var httpClient = new WebClient();
	httpClient.Headers.Add("Content-Type", "application/json");
	httpClient.Headers.Add(HttpRequestHeader.Authorization, "key=" + serverApiKey);
	var timeToLiveInSecond = 24 * 60; // 1 day
	var data = new
	{
		to = "/topics/" + to ,
		data = new
		{
			notification = new
			{
				body = message,
				title = title,
				icon = "/Content/Images/Logos/BourseVirtuelle.png",
				url = urlNotificationClick,
				sound = "default"
			}
		},
		time_to_live = timeToLiveInSecond
	};

	var json = JsonConvert.SerializeObject(data);
	Byte[] byteArray = Encoding.UTF8.GetBytes(json);
	var responsebytes = httpClient.UploadData(firebaseGoogleUrl, "POST", byteArray);
	string responsebody = Encoding.UTF8.GetString(responsebytes);
	dynamic responseObject = JsonConvert.DeserializeObject(responsebody);

	return responseObject.success == "1";
}

What has changed from sending to a single user? The field “to” which is sending to topics. The “to” in the method signature is still the user unique identifier, but instead of sending directly to it, we use it has a topic. We do not use the token generated by the front end since a new one got generated per device, we only use the user id which is the topic.

If you like my article, think to buy my annual book, professionally edited by a proofreader. directly from me or on Amazon.

3 Responses so far.

  1. Garima says:

    To send message to multiple devices of same user .. I am using following solution:

    public bool QueueMessage(string to, string title, string message, string urlNotificationClick, List to)
    {
    if (string.IsNullOrEmpty(to))
    {
    return false;
    }
    var serverApiKey = “SuperLongKeyHere”;
    var firebaseGoogleUrl = “https://fcm.googleapis.com/fcm/send”;

    var httpClient = new WebClient();
    httpClient.Headers.Add(“Content-Type”, “application/json”);
    httpClient.Headers.Add(HttpRequestHeader.Authorization, “key=” + serverApiKey);
    var timeToLiveInSecond = 24 * 60; // 1 day
    var data = new
    {
    registration_ids = to.ToArray(), //string array of fcm tokens for various devices for my user
    data = new
    {
    notification = new
    {
    body = message,
    title = title,
    icon = “/Content/Images/Logos/BourseVirtuelle.png”,
    url = urlNotificationClick
    }
    },
    time_to_live = timeToLiveInSecond
    };

    var json = JsonConvert.SerializeObject(data);
    Byte[] byteArray = Encoding.UTF8.GetBytes(json);
    var responsebytes = httpClient.UploadData(firebaseGoogleUrl, “POST”, byteArray);
    string responsebody = Encoding.UTF8.GetString(responsebytes);
    dynamic responseObject = JsonConvert.DeserializeObject(responsebody);

    return responseObject.success == “1”;
    }

  2. Garima says:

    To send message to multiple devices of same user .. I am using following solution:

    public bool QueueMessage(string title, string message, string urlNotificationClick, List to)
    {
    if (string.IsNullOrEmpty(to))
    {
    return false;
    }
    var serverApiKey = “SuperLongKeyHere”;
    var firebaseGoogleUrl = “https://fcm.googleapis.com/fcm/send”;

    var httpClient = new WebClient();
    httpClient.Headers.Add(“Content-Type”, “application/json”);
    httpClient.Headers.Add(HttpRequestHeader.Authorization, “key=” + serverApiKey);
    var timeToLiveInSecond = 24 * 60; // 1 day
    var data = new
    {
    registration_ids = to.ToArray(), //string array of fcm tokens for various devices for my user
    data = new
    {
    notification = new
    {
    body = message,
    title = title,
    icon = “/Content/Images/Logos/BourseVirtuelle.png”,
    url = urlNotificationClick
    }
    },
    time_to_live = timeToLiveInSecond
    };

    var json = JsonConvert.SerializeObject(data);
    Byte[] byteArray = Encoding.UTF8.GetBytes(json);
    var responsebytes = httpClient.UploadData(firebaseGoogleUrl, “POST”, byteArray);
    string responsebody = Encoding.UTF8.GetString(responsebytes);
    dynamic responseObject = JsonConvert.DeserializeObject(responsebody);

    return responseObject.success == “1”;
    }

  3. Hi,

    Code is working but how to set icon?

Leave a Reply

Your email address will not be published. Required fields are marked *