3
votes

For my environment, I use Rest API to register/unregister my device with notification hub.

Whenever my user logs in, my app registers with GCM, gets a registration ID, then registers with notification hub to receive notification. This works without any problem.

When my user logs out, my app wants to delete that registration from notification hub so user will not longer receive any notification.

After consulting this page on how to Delete Registration

https://msdn.microsoft.com/en-us/library/azure/dn223268.aspx

I wrote the following code:

var client = new XMLHttpRequest();
client.onload = function () {
    if (client.readyState == 4) {
        if (client.status == 200) {
            // we are logged out
            console.log("(sendNHDeleteRegistrationRequest) NH delete registration is successful");
            chrome.storage.local.set({registered: false});
            updateRegisterUI();
        } else {
            console.log("(sendNHDeleteRegistrationRequest) NH delete registration is not successful");
            console.log("(sendNHDeleteRegistrationRequest) HTTP Status: " + client.status + " : " + client.statusText);
            console.log("(sendNHDeleteRegistrationRequest) HTTP Response: " + "\n" + client.responseText);
        }
    }
};

var url = gOriginalUri + "/registrations/" + gRegistrationId + "?api-version=2015-01";
    client.open("POST", url, true);
    client.setRequestHeader("Content-Type", "application/atom+xml;type=entry;charset=utf-8");
    client.setRequestHeader("Authorization", gSasToken);
    client.setRequestHeader("x-ms-version", "2015-01");

try {
    client.send();
    chrome.storage.local.set({registered: false});
    updateRegisterUI();
}
catch(err) {
    console.log(err.message);
}

But I always receive this error:

(sendNHDeleteRegistrationRequest) NH delete registration is not successful register.js:230 (sendNHDeleteRegistrationRequest) HTTP Status: 405 : Method Not Allowed register.js:231 (sendNHDeleteRegistrationRequest) HTTP Response: 405The specified HTTP verb (POST) is not valid..TrackingId:64cd952b-ffda-42f8-860b-22dd4aa397ea_G3,TimeStamp:7/31/2015 4:00:48 AM

so my question is 1. To stop receiving notification for my app when user logs out, what's the standard practice? Block the notification from firing in the app or delete the registration from the notification hub? 2. Am I using this delete registration the right way?Why am I receiving 405 Method not allowed?

thanks!

3
Is there any progress on deleting registration from Azure notification hub? I want to do the same, but couldn't find a helping hand. The documentation is also not satisfactory. Can you please help? - Ali_Waris

3 Answers

2
votes

I see you are using POST method to delete the registration. Shouldn't you be using DELETE instead?

var url = gOriginalUri + "/registrations/" + gRegistrationId + "?api-version=2015-01";
client.open("POST", url, true);
client.setRequestHeader("Content-Type", "application/atom+xml;type=entry;charset=utf-8");
client.setRequestHeader("Authorization", gSasToken);
client.setRequestHeader("x-ms-version", "2015-01");

Try:

client.open("DELETE", url, true);
1
votes

In order to delete a registration I use the following code, it's C# code that I wrote for a ASP.NET .NET Core project, but maybe it helps:

const string hubName = "hubname";
const string apiVersion = "?api-version=2015-01";
const string fullSharedAccessKey = @"fullsharedaccesskey";
const string messageChannel = @"/messages";
const string registrationChannel = @"/registrations";
const string installationChannel = @"/installations";

public async Task<int> DeleteRegistration(string registrationId)
{
    var accessKey = ToAccessKey(fullSharedAccessKey);
    Uri uri = new Uri($"{accessKey.Endpoint}{hubName}{registrationChannel}/{registrationId}/{apiVersion}");
    var sasToken = createToken(uri.AbsoluteUri, accessKey.SasKeyName, accessKey.SasKeyValue);

    using (HttpClient client = new HttpClient())
    {
        HttpRequestMessage message = new HttpRequestMessage()
        {

            RequestUri = uri,
            Method = HttpMethod.Delete

        };

        message.Headers.Add("Authorization", sasToken);
        message.Headers.Add("If-Match", "*");

        var result = await client.SendAsync(message);
    }
    return 0;
}

private AzureNotificationsAccessKey ToAccessKey(string connectionString)
{
    var key = new AzureNotificationsAccessKey();

    // Parse Connection string
    char[] separator = { ';' };
    string[] parts = connectionString.Split(separator);
    for (int i = 0; i < parts.Length; i++)
    {
        if (parts[i].StartsWith("Endpoint"))
            key.Endpoint = "https" + parts[i].Substring(11);
        if (parts[i].StartsWith("SharedAccessKeyName"))
            key.SasKeyName = parts[i].Substring(20);
        if (parts[i].StartsWith("SharedAccessKey"))
            key.SasKeyValue = parts[i].Substring(16);
    }

    return key;
}

/// <summary> 
/// Code  for generating of SAS token for authorization with Service Bus 
/// 
/// This handy function can be found on this helpful blog post:
/// http://developers.de/blogs/damir_dobric/archive/2013/10/17/how-to-create-shared-access-signature-for-service-bus.aspx
/// </summary> 
/// <param name="resourceUri"></param> 
/// <param name="keyName"></param> 
/// <param name="key"></param> 
/// <returns></returns> 
private string createToken(string resourceUri, string keyName, string key)
{
    TimeSpan sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
    var expiry = Convert.ToString((int)sinceEpoch.TotalSeconds + 3600); //EXPIRES in 1h 
    string stringToSign = EncodeUrl(resourceUri) + "\n" + expiry;
    HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));

    var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
    var sasToken = String.Format(CultureInfo.InvariantCulture,
    "SharedAccessSignature sig={1}&se={2}&skn={3}&sr={0}",
        EncodeUrl(resourceUri), EncodeUrl(signature), expiry, keyName);

    return sasToken;
}

public class AzureNotificationsAccessKey
{
    public string Endpoint { get; set; }
    public string SasKeyName { get; set; }
    public string SasKeyValue { get; set; }
}
0
votes

I do prefer to use ANH SDK which supplies a method for that!

// go to the Acess Policies page to take your ConnectionString and Namespace
var hubClient = NotificationHubClient.CreateClientFromConnectionString("Your Connection String", "Your namespace");

// take the registrations using your FirebaseToken or Tags, for instance
var registrations = await hubClient.GetRegistrationsByChannelAsync(yourFirebaseToken, 100);

// Finally, remove them
foreach (var registration in registrations)
{
  await hubClient.DeleteRegistrationAsync(registration);
}