Search code examples
c#iosnotificationspayload

Amazon Simple Notification Service with custom iOS payload not so simple


Sending a plain text notification is easy and well documented. But I've been pulling my hair today regarding sending a custom notification for iOS that has the alert and some fields like userId.

I started with this help page and implemented something similar to the last sample, then I found this answer that seems to invalidate the last sample on the help page, as the "url" property should be outside the "aps" object. I tried a good deal of combinations but each one of them gets sent as text to the app (the whole message, with the "default" property and "APNS" object)...

If I explicitly set MessageStructure to json I get the error: "Invalid parameter: Message Structure - JSON message body failed to parse" but I'm pretty sure my JSON is good, when sent to SNS the string in the Message property looks like this:

{ "default":"You received a new message from X.", 
 "APNS_SANDBOX":"{ \"aps\": {\"alert\":\"You received a new message from X.\"}, 
                \"event\":\"Message\", 
                \"objectID\":\"7a39d9f4-2c3f-43d5-97e0-914c4a117cee\"
            }", 
 "APNS":"{ \"aps\": {\"alert\":\"You received a new message from X.\"}, 
                \"event\":\"Message\", 
                \"objectID\":\"7a39d9f4-2c3f-43d5-97e0-914c4a117cee\"
            }" 
}

Does anybody have a good example of sending a notification with custom payload through SNS in C#? Because Amazon sure hasn't...


Solution

  • Strangely when I implemented the clean way of doing this by using classes and serializing objects instead of just sending a formatted string it worked. The only difference was the spacing... in the clean version there are no spaces except in the property values:

    {"default":"You received a new message from X.","APNS_SANDBOX":"{\"aps\":{\"alert\":\"You received a new message from X.\"},\"event\":\"Message\",\"objectID\":\"7a39d9f4-2c3f-43d5-97e0-914c4a117cee\"}","APNS":"{\"aps\":{\"alert\":\"You received a new message from X.\"},\"event\":\"Message\",\"objectID\":\"7a39d9f4-2c3f-43d5-97e0-914c4a117cee\"}"}
    

    These are the classes that I'm serializing (only for APNS for the moment), use whatever properties you need instead of Event and ObjectID:

    [DataContract]
    public class AmazonSNSMessage
    {
        [DataMember(Name = "default")]
        public string Default { get; set; }
    
        [DataMember(Name = "APNS_SANDBOX")]
        public string APNSSandbox { get; set; }
    
        [DataMember(Name = "APNS")]
        public string APNSLive { get; set; }
    
        public AmazonSNSMessage(string notificationText, NotificationEvent notificationEvent, string objectID)
        {
            Default = notificationText;
            var apnsSerialized = JsonConvert.SerializeObject(new APNS
            {
                APS = new APS { Alert = notificationText },
                Event = Enum.GetName(typeof(NotificationEvent), notificationEvent),
                ObjectID = objectID
            });
            APNSLive = APNSSandbox = apnsSerialized;
        }
    
        public string SerializeToJSON()
        {
            return JsonConvert.SerializeObject(this);
        }
    }
    
    [DataContract]
    public class APNS 
    {
        [DataMember(Name = "aps")]
        public APS APS { get; set; }
    
        [DataMember(Name = "event")]
        public string Event { get; set; }
    
        [DataMember(Name = "objectID")]
        public string ObjectID { get; set; }
    }
    
    [DataContract]
    public class APS
    {
        [DataMember(Name = "alert")]
        public string Alert { get; set; }
    }
    

    So I get the Amazon SNS message by doing:

    new AmazonSNSMessage(...).SerializeToJSON();