Giter VIP home page Giter VIP logo

azure-notificationhubs-dotnet's Introduction

NuGet

.NET Client for Azure Notification Hubs

This repository contains source code for Azure Notification Hubs .NET SDK as well as samples for using the client. This library is also available via NuGet as part of Microsoft.Azure.NotificationHubs.

Table of Contents:

Building Code

To build the Microsoft.Azure.NotificationHubs, you need support for .NET Standard 2.0. This requires a minimum of .NET Core 3.1, .NET Framework 4.6.2 or Mono 5.4. This project ships with two unit test files, one for .NET Core 6.0, and one for .NET Framework 4.6.2 or Mono. This library ships binaries for .NET Standard 2.0, .NET Standard 2.1 and .NET 6.0.

Getting Started

To get started, you can find all the classes in the Microsoft.Azure.NotificationHubs namespace, for example:

using Microsoft.Azure.NotificationHubs;

Azure Notification Hubs Management Operations

This section details the usage of the Azure Notification Hubs SDK for .NET management operations for CRUD operations on Notification Hubs and Notification Hub Namespaces.

Create a namespace manager

var namespaceManager = new NamespaceManagerClient("connection string");

Create an Azure Notification Hub

var hub = new NotificationHubDescription("hubname");
hub.WnsCredential = new WnsCredential("sid","key");
hub = await namespaceManager.CreateNotificationHubAsync(hub);

Get a Azure Notification Hub

var hub = await namespaceManager.GetNotificationHubAsync("hubname", CancellationToken.None);

Update an Azure Notification Hub

hub.FcmCredential = new FcmCredential("key");
hub = await namespaceManager.UpdateNotificationHubAsync(hub, CancellationToken.None);

Delete an Azure Notification Hub

await namespaceManager.DeleteNotificationHubAsync("hubname", CancellationToken.None);

Azure Notification Hubs Operations

The NotificationHubClient class and INotificationHubClient interface is the main entry point for installations/registrations, but also sending push notifications. To create a NotificationHubClient, you need the connection string from your Access Policy with the desired permissions such as Listen, Manage and Send, and in addition, the hub name to use.

INotificationHubClient hub = new NotificationHubClient("connection string", "hubname");

Azure Notification Hubs Installation API

An Installation is an enhanced registration that includes a bag of push related properties. It is the latest and best approach to registering your devices.

The following are some key advantages to using installations:

  • Creating or updating an installation is fully idempotent. So you can retry it without any concerns about duplicate registrations.
  • The installation model supports a special tag format ($InstallationId:{INSTALLATION_ID}) that enables sending a notification directly to the specific device. For example, if the app's code sets an installation ID of joe93developer for this particular device, a developer can target this device when sending a notification to the $InstallationId:{joe93developer} tag. This enables you to target a specific device without having to do any additional coding.
  • Using installations also enables you to do partial registration updates. The partial update of an installation is requested with a PATCH method using the JSON-Patch standard. This is useful when you want to update tags on the registration. You don't have to pull down the entire registration and then resend all the previous tags again.

Using this SDK, you can do these Installation API operations. For example, we can create an installation for an Amazon Kindle Fire using the Installation class.

var installation = new Installation
{
    InstallationId = "installation-id",
    PushChannel = "adm-push-channel",
    Platform = NotificationPlatform.Adm
};
await hub.CreateOrUpdateInstallationAsync(installation);

Alternatively, we can use specific installation classes per type for example AdmInstallation for Amazon Kindle Fire devices.

var installation = new AdmInstallation("installation-id", "adm-push-channel");
await hub.CreateOrUpdateInstallationAsync(installation);

An installation can have multiple tags and multiple templates with its own set of tags and headers.

installation.Tags = new List<string> { "foo" };
installation.Templates = new Dictionary<string, InstallationTemplate>
{
    { "template1", new InstallationTemplate { Body = "{\"data\":{\"key1\":\"$(value1)\"}}" } },
    { "template2", new InstallationTemplate { Body = "{\"data\":{\"key2\":\"$(value2)\"}}" } }
};
await hub.CreateOrUpdateInstallationAsync(installation);

For advanced scenarios we have partial update capability which allows to modify only particular properties of the installation object. Basically partial update is subset of JSON Patch operations you can run against Installation object.

var addChannel = new PartialUpdateOperation
{ 
    Operation = UpdateOperationType.Add, ,
    Path = "/pushChannel", 
    Value = "adm-push-channel2"
};
var addTag = new PartialUpdateOperation
{
    Operation = UpdateOperationType.Add, 
    Path = "/tags", 
    Value = "bar"
};
var replaceTemplate = new PartialUpdateOperation
{
    Operation = UpdateOperationType.Replace, 
    Path = "/templates/template1",
    Value = new InstallationTemplate { Body = "{\"data\":{\"key3\":\"$(value3)\"}}" }.ToJson()
};
await hub.PatchInstallationAsync(
    "installation-id", 
    new List<PartialUpdateOperation> { addChannel, addTag, replaceTemplate }
);

Delete an Installation

await hub.DeleteinstallationAsync("installation-id");

Keep in mind that CreateOrUpdateInstallationAsync, PatchInstallationAsync and DeleteInstallationAsync are eventually consistent with GetInstallationAsync. In fact operation just goes to the system queue during the call and will be executed in background. Moreover Get is not designed for main runtime scenario but just for debug and troubleshooting purposes, it is tightly throttled by the service.

Azure Notification Hub Registration API

A registration associates the Platform Notification Service (PNS) handle for a device with tags and possibly a template. The PNS handle could be a ChannelURI, device token, or FCM registration ID. Tags are used to route notifications to the correct set of device handles. Templates are used to implement per-registration transformation. The Registration API handles requests for these operations.

Create an Apple Registration

var deviceToken = "device-token";
var tags = new HashSet<string> { "platform_ios", "os_tvos" };
AppleRegistrationDescription created = await hub.CreateAppleNativeRegistrationAsync(deviceToken, tags);

Analogous for Android (FCM), Windows Phone (MPNS), and Kindle Fire (ADM).

Create Template Registrations

var deviceToken = "device-token";
var jsonBody = "{\"aps\": {\"alert\": \"$(message)\"}}";
AppleTemplateRegistrationDescription created = await hub.CreateAppleTemplateRegistrationAsync(deviceToken, jsonBody);

Create registrations using create registrationid+upsert pattern (removes duplicates deriving from lost responses if registration ids are stored on the device):

var deviceToken = "device-token";
var registrationId = await hub.CreateRegistrationIdAsync();
var jsonBody = "{\"aps\": {\"alert\": \"$(message)\"}}";
var reg = new AppleTemplateRegistrationDescription(deviceToken, jsonBody) { RegistrationId = registrationId };
AppleTemplateRegistrationDescription upserted = await hub.CreateOrUpdateRegistrationAsync(reg);

Update a Registration

await hub.UpdateRegistrationAsync(reg);

Delete a Registration

await hub.DeleteRegistrationAsync(registrationId);

Get a Single Registration

AppleRegistrationDescription registration = hub.GetRegistrationAsync(registrationId);

Get Registrations With a Given Tag

This query support $top and continuation tokens.

var registrations = await hub.GetRegistrationsByTagAsync("platform_ios");

Get Registrations By Channel

This query support $top and continuation tokens.

var registrations = await hub.GetRegistrationsByChannelAsync("devicetoken");

Send Notifications

The Notification object is simply a body with headers, some utility methods help in building the native and template notifications objects.

Send an Apple Push Notification

var jsonBody = "{\"aps\":{\"alert\":\"Notification Hub test notification\"}}";
var n = new AppleNotification(jsonBody);
NotificationOutcome outcome = await hub.SendNotificationAsync(n);

Analogous for Android, Windows, Windows Phone, Kindle Fire and Baidu PNS.

Send a Template Notification

var props =  new Dictionary<string, string>
{
    { "prop1", "v1" },
    { "prop2", "v2" }
};
var n = new TemplateNotification(props);
NotificationOutcome outcome = hub.SendNotificationAsync(n);

Send To An Installation ID

Send flow for Installations is the same as for Registrations. We've just introduced an option to target notification to the particular Installation - just use tag "$InstallationId:{desired-id}". For case above it would look like this:

var jsonBody = "{\"aps\":{\"alert\":\"Notification Hub test notification\"}}";
var n = new AppleNotification(jsonBody);
var tags = new List<string> { "$InstallationId:{installation-id}" };
NotificationOutcome outcome = await hub.SendNotificationAsync(n, tags);

Send to a User ID

With the Installation API we now have a new feature that allows you to associate a user ID with an installation and then be able to target it with a send to all devices for that user. To set the user ID for the installation, set the UserId property of the Installation.

var installation = new AppleInstallation("installation-id", "device-token");
installation.UserId = "user1234";

await hub.CreateOrUpdateInstallationAsync(installation);

The user can then be targeted to send a notification with the tag format of $UserId:{USER_ID}, for example like the following:

var jsonPayload = "{\"aps\":{\"alert\":\"Notification Hub test notification\"}}";
var n = new AppleNotification(jsonPayload);
NotificationOutcome outcome = await hub.SendNotificationAsync(n, "$UserId:user1234");

Send To An Installation Template For An Installation

var props = new Dictionary<string, string>
{
    { "value3", "some value" }
};
var n = new TemplateNotification(prop);
NotificationOutcome outcome = await hub.SendNotificationAsync(n, "$InstallationId:{installation-id} && template1");

Scheduled Send Operations

Note: This feature is only available for STANDARD Tier.

Scheduled send operations are similar to a normal send operations, with a scheduledTime parameter which says when notification should be delivered. The Azure Notification Hubs Service accepts any point of time between now + 5 minutes and now + 7 days.

Schedule Apple Native Send Operation

var scheduledDate = DateTimeOffset.UtcNow.AddHours(12);

var jsonPayload = "{\"aps\":{\"alert\":\"Notification Hub test notification\"}}";
var n = new AppleNotification(jsonPayload);

ScheduledNotification outcome = await hub.ScheduleNotificationAsync(n, scheduledDate);

Cancel Scheduled Notification

await hub.CancelNotificationAsync(outcome.ScheduledNotificationId);

Import and Export Registrations

Note: This feature is only available for STANDARD Tier.

Sometimes it is required to perform bulk operation against registrations. Usually it is for integration with another system or just to update the tags. It is strongly not recommended to use Get/Update flow if you are modifying thousands of registrations. Import/Export capability is designed to cover the scenario. You provide an access to some blob container under your storage account as a source of incoming data and location for output.

Submit an Export Job

var job = new NotificationHubJob
{
    JobType = NotificationHubJobType.ExportRegistrations,
    OutputContainerUri = new Uri("container uri with SAS signature"),
};

job = await hub.SubmitNotificationHubJobAsync(job);

Submit an Import Job

var job = new NotificationHubJob
{
    JobType = NotificationHubJobType.ImportCreateRegistrations,
    ImportFileUri = new Uri("input file uri with SAS signature"),
    OutputContainerUri = new Uri("container uri with SAS signature")
};

job = await hub.SubmitNotificationHubJobAsync(job);

Wait for Job Completion

while (true) {
    await Task.Delay(1000);
    job = await hub.GetNotificationHubJobAsync(job.JobId);
    if (job.Status == NotificationHubJobStatus.Completed) {
        break;
    }
}

Get All jobs

var allJobs = await hub.GetNotificationHubJobsAsync()

References

Microsoft Azure Notification Hubs Docs

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.

When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

azure-notificationhubs-dotnet's People

Contributors

aimankhan avatar az-softeq avatar aziztitu avatar brannon avatar dependabot[bot] avatar evgeny-pol avatar evgkarpov avatar igprya avatar itoys avatar jakubholovsky avatar jwargo avatar kirill-pyatunin avatar kmiecikt avatar kostya-zhidovinov avatar kylekampy avatar lovelangy avatar marstr avatar mpodwysocki avatar navba-msft avatar nesterenko-kv avatar olgaakv avatar piyushjo avatar pmngo avatar spelluru avatar stankovski avatar varvusc avatar vlpereva avatar vvildvvolf avatar wesmc7777 avatar zhangeugenia avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

azure-notificationhubs-dotnet's Issues

FCM registration token colon not allowed

I'm getting the following error when calling CreateOrUpdateInstallationAsync:

ArgumentException: The path sb://xxxxxxxxx.servicebus.windows.net/splashnotifdev/installations/xxxxxx:xxxxxxxxxxxxx?api-version=2017-04&" contains character(s) that are not allowed by Service Bus. Entity segments can contain only letters, numbers, periods (.), hyphens (-), and underscores (_)..TrackingId:98f12ac0-c905-4a63-a68d-c77f61cdb1ad_G5,TimeStamp:6/1/2019 3:16:11 PM

Where the installationId obtained from Firebase's onSuccessListener is a token with colon in it.
The token appears to be similar to a GCM token but prefixed with a few characters and a colon, e.g. (rest of the token masked):
dTxbVurMB3E:APA91bFsadfjklasfhjdsajkfdhaslkfhdjklsafhjklasdhlhasklfhjkasfhdjlkasfhdasjkdhf

Note that I am not calling this from Android, but passing the token to a .NET backend which calls the CreateOrUpdateInstallationAsync() method. I've also tried urlencoding the token or replacing : with %3a, which only leads to an Unauthorized error (despite the SAS working correctly, e.g. for Apns registrations).

UnauthorizedAccessException: The remote server returned an error: (401) Unauthorized. Reason: 40104: Invalid authorization token audience..TrackingId:7cf7cb94-9041-486c-8ccd-72e4f1d68d40,TimeStamp:2019-06-01T15:25:41.5055837Z

UnauthorizedAccessException: ExpiredToken after 20min

Hello,
I have an issue with Microsoft.Azure.NotificationHubs v2.0.1
Under heavy usage, after 20min, I systematically get exception "System.UnauthorizedAccessException: ExpiredToken"
After investigation I found an issue in Microsoft.Azure.NotificationHubs.Auth.TokenProvider.TrySetIntoCache : there is a SlidingExpiration even though the token is absolutely expired in 20min ( Microsoft.Azure.NotificationHubs.Auth.SharedAccessSignatureTokenProvider.DefaultTokenTimeout )
So it lacks an AbsoluteExpiration with the same ExpirationDate as the token.

My logs:
EXCEPTION:System.UnauthorizedAccessException: ExpiredToken: .TrackingId:fa5e49c9-330d-4f0e-9bb8-58360f9a4e37_G7,TimeStamp:11/13/2018 4:05:33 PM at Microsoft.Azure.NotificationHubs.NotificationHubClient.SendRequestAsync(HttpRequestMessage request, String trackingId, HttpStatusCode[] successfulResponseStatuses, CancellationToken cancellationToken) at Microsoft.Azure.NotificationHubs.NotificationHubClient.SendRequestAsync(HttpRequestMessage request, String trackingId, HttpStatusCode successfulResponseStatus, CancellationToken cancellationToken) at Microsoft.Azure.NotificationHubs.NotificationHubClient.GetAllEntitiesImplAsync[TEntity](UriBuilder requestUri, String continuationToken, Int32 top, CancellationToken cancellationToken) at NotificationHub.API.BusinessCommands.RegisterMobileDeviceCommand.ExecuteAsync()

A dirty workaround until fix is to disable token caching (using Reflection):
var tokenProviderField = typeof(Microsoft.Azure.NotificationHubs.NotificationHubClient).GetField("_tokenProvider", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); var tokenProvider = tokenProviderField.GetValue(client); var tokenProvider_cacheTokensField = tokenProvider .GetType() //Microsoft.Azure.NotificationHubs.Auth.SharedAccessSignatureTokenProvider .BaseType //Microsoft.Azure.NotificationHubs.Auth.TokenProvider .GetField("_cacheTokens", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); tokenProvider_cacheTokensField.SetValue(tokenProvider, false);

this bug may be related to #9
I will submit a PR.
Thanks

NuGet package version 3.2.0 is not properly signed

NuGet package version 3.2.0 seems to be delay signed and not fully signed as expected. Running our application with the new package results in the error below. Running sn.exe reveals that the assembly is delay signed. Running the same verification on version 3.1.0 results in a valid assembly. Seems to be 3.2.0 specific.

Could not load file or assembly 'Microsoft.Azure.NotificationHubs' or one of its dependencies. Strong name signature could not be verified.  The assembly may have been tampered with, or it was delay signed but not fully signed with the correct private key. (Exception from HRESULT: 0x80131045) 
sn -vf Microsoft.Azure.NotificationHubs.dll

Microsoft (R) .NET Framework Strong Name Utility  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

Microsoft.Azure.NotificationHubs.dll is a delay-signed or test-signed assembly

Unable to send X-WNS-Match notification succesfully

I'm unable to send a WNS notification with X-WNS-Match header to remove a notification from the Action Center. The current NotificationHubClient implementation has not any option to send the HTTP DELETE request required for this scenario.

GetRegistrationsBy* returns Gcm*Registration instead of Fcm

In V3, GcmRegistrationDescription is marked as obsolete, so the SDK takes care of returning the same registration type when creating new Fcm registration.
However, when querying device registrations, GcmRegistrationDescription objects returned as REST responds with GcmRegistrationDescription content.
Shouldn't the SDK fully switch to Fcm and explicitly convert Gcm to Fcm descriptions?

Check if installation exists

Using NotificationHubClient, I want to create an installation when it doesn't exist. But when I run GetInstallation(id) and id doesn't exist, I get an exception:

Microsoft.Azure.NotificationHubs.Messaging.MessagingEntityNotFoundException: 'The remote server returned an error: (404) Not Found. Installation not found.TrackingId.

How can I check if an installation already exists without try/catching the GetInstallation() method?

Outdated examples

The example at https://github.com/Azure/azure-notificationhubs-dotnet/blob/master/Samples/SendPushSample/SendPushSample/Program.cs doesn't work.

The code is based on SDK 3, but the project imports 2.x

The example fails with:

Unhandled Exception: System.ArgumentNullException: Value cannot be null.
Program.cs:line 131

outcomeDetails = await nhClient.GetNotificationOutcomeDetailsAsync(notificationId);

Because notificationId is null.

After debugging the SDK I noticed that the code is looking for a Location header, but inspecting the HTTP response from Azure notification hub, there is no such header.

Request made by the SDK:

image

Response received by the SDK:

image

Any suggestion?

Reformat HTTP mocked data files

As noted in PR #15, we need to have better formatting for our HTTP mocked data. This task should run a standard JSON formatter over each of the .http files.

apns-collapse-id not working

As far as I can see, one of your SDK samples (SendPushSample) provides apns-collapse-id header to APNS. In my case however this doesn't work as expected - notifications don't 'collapse'. Has anyone tested if these headers are passed to APNS and if behavior was correct?

I'm wondering if the type of authentication is important here in Azure Notification Hubs, since I'm using old certificate-based authentication rather than new key-based authentication.

Handle DNS changes

I use the NotificationHubClient as a Singleton in my long-running service. (> 1 month)
When the DNS (IP) for the HUB changes (a few times per year) this is not reflected in the singleton NotificationHubClient (due to "new HttpClient()") and I'll get exceptions in my code and have to restart the whole service to reflect the DNS change.

What is the correct way to solve this in code right now and is there any plans to use the IHttpClientFactory to create the HttpClient instead, which also should solve the problem.

Azure Notification Hub static instance or recreate

Good day, I made a SO question about this, but I have not any official MS response.

SO

What is the correct way to use the c# Azure Notification Hub Client?

We are using this in a very high usage server sending millions of pushes a day.

I would like to know if we should recreate the NotificationHubClient every time or if we should keep a static/singleton instance of it and then reuse that each time?

Currently, we recreate it every time we send a push notification. However, I know from personal experience we have had issues with the .net HTTP client and it not releasing tcp sockets fast enough. I was worried that this library could start having similar issues.

How to set high priority of push notification which is send to NotificationHub

I have successfully implemented Azure Function, which sends push notifications to NotificationHub for Android, iOS and UWP. During the testing I discovered that when Android device is in Doze mode push notification is not delivered on lock screen. It is only delivered when I unlock the phone.

I found out this stackoverflow post, which helped me to fix it with method SendFcmNativeNotificationAsync. I used this code:

string payload = @"{
                    ""data"":{
                        ""notificationtype"":""sap"",
                        ""title"":""value2"",
                    },
                        ""priority"":""high""
                    }";

await hub.SendFcmNativeNotificationAsync(payload);

However my implementation using SendNotificationAsync method which works for all 3 platforms, but not in Doze mode. This is my code to send notification:

Dictionary<string, string> templateParameters = new Dictionary<string, string>();

templateParameters["alert"] = "Test";
templateParameters["title"] = "Whosap";

var notification = new TemplateNotification(templateParameters);
await hub.SendNotificationAsync(notification);

I tried to set header of notification:

var headers = new Dictionary<string, string> { { "android", @"{""priority"": ""high""}" } };
notification.Headers = headers;

But this didn't work. Does anybody know how to set priority in TemplateNotification object and send it with SendNotificationAsync method?

Can I continue using the old v2 SDK after April 2019?

There is a lot of information floating around regarding the impending deprecation of GCM in favor of FCM. What does this mean for NotificationHubs .NET SDK users? We are creating/updating registrations and are sending push notifications. Do we need to switch our backend code to V3 before April 2019? Or is this handled by Azure for us?

"If you have projects that are still using the GCM APIs, you will need to update your client and server code to use FCM before April 11, 2019. But rest assured, your existing GCM tokens will continue to work with FCM so you won't lose the ability to send messages to your existing users." (https://firebase.googleblog.com/2018/04/time-to-upgrade-from-gcm-to-fcm.html)

The Push Notification System handle for the registration is invalid

I have the hub working using "sandbox", then I switch it to "production" mode, I see the client device gets a new registration handle id, but when I test send on azure, get the error
"The Push Notification System handle for the registration is invalid", I was using the variable "testsend" in code to check the outcome object as well, but it does not really say much.
When it is switched to "production" mode, azure hub forwards the message to the production apple push notificaiton server, and my local devices is using the correct endpoint, but use a development certificate. I am not sure what this means, does the devices need to have the app installed with appstore provision profile in order to receive a message from "production" channel?
So the only way for testing is through "testflight"?

Any help will be appreciated.
Marc

Installation + InstallationTemplate and APNS headers

I want to use templates, Installation API and provide apns-collapse-id header to APNS for Apple notifications. Is the code below a proper way of doing so? The docs say InstallationTemplate.Headers property is for MPNS-targeted notifications, so not sure if this would work for Apple (APNS) as well.

var installation = new Installation
{
    InstallationId = "myId",
    Platform = NotificationPlatform.Apns,
    PushChannel = "xxx",
    Templates = new Dictionary<string, InstallationTemplate>
    {
        {
            "hello",
            new InstallationTemplate
            {
                Body = @"{ ""aps"": { ""alert"": ""Test"" } }",
                Headers = new Dictionary<string, string> { { "apns-collapse-id", "myCollapseId" } }
            }
        }
    }
};
await _hub.CreateOrUpdateInstallationAsync(installation);

How do you send a notification to a specific installation template (.NET)?

I am registering installations from my .NET backend server code with multiple templates each. For example:

var installation = new Installation
{
    InstallationId = id,
    PushChannel = token,
    Templates = new Dictionary<string, InstallationTemplate>(),
    Tags = new List<string> { "userId:123456" },
    Platform = NotificationPlatform.Gcm
};

installation.Templates.Add("template1", new InstallationTemplate { Body = "{\"data\":{\"message\":\"$(message)\"}}"});
installation.Templates.Add("template2", new InstallationTemplate { Body = "{\"data\":{\"message2\":\"$(message)\"}}"});

await _client.CreateOrUpdateInstallationAsync(installation);

How do I target a specific template when sending a notification? All I see in the SDK is the following:

await _client.SendTemplateNotificationAsync(
    new Dictionary<string, string>
    {
        { "message",  "Hello world." }
    }, "userId:123456");

The SendTemplateNotificationAsync method does not have any parameters that let me specify which template I am targeting (for example, template2).

Which template will be used? Am I misunderstanding something here?

the push notification system handle for the registration is invalid - iOS

Hello,

I'm not quite sure, but it's been a rough day for me getting this to work since iOS 13.
I'm trying to send a test message via the Notification Hub window from the Server explorer in VS2015. I'm getting this "the push notification system handle for the registration is invalid" error.

I followed the guide and here's what I got.

image

I'll try to run through the guide again. I got it working before all the shebang from iOS13.

thanks

AppleNotification lack support for new requered iOS 13 header apns-push-type

https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns

According to Apples documentation above iOS 13 devices requires a "apns-push-type" header to be present. And leaving it out may cause delayed delivery or total loss of delivery.

So the AppleNotification class should add the below by default.
AppleNotification.Headers["apns-push-type"] = "alert"

C# SDK 2.0.0-preview2 stops working after 1 hour

I am trying out the new 2.0.0-preview2 available on nuget in a ASP.NET Core 2.1 application on netcoreapp2.1. This seems to work fine as a drop in replacement for 1.0.9 without any breaking changes.

In my application, NotificationHubClient is initialized as a properly of a singleton instance. I notice that after ~1 hour of the application running, any NotificationHubClient functions that are invoked no longer work. My application does not throw any errors, but all activity to my Notification Hub ceases (confirmed by looking at metrics in the Azure portal) and I no longer get push notifications to my apps. If I restart the server (causing the singleton instance to new again) things again start working for ~1 hour and then stop again.

Due to the nature of the consistent 1 hour lifetime of things working, I suspect that the NotificationHubClient instance is not renewing it's SAS token or something that has a 1 hour lifetime. To workaround this problem I now keep track of internal 30 minute timer where I new the NotificationHubClient up again every 30 minutes. Doing this resolves the problem.

Using NotificationHubClient from Azure function: System.Net.Sockets.SocketException

Using NotificationHubClient from Azure function (the client is created on every function call) on high load fails with "System.Net.Sockets.SocketException: Cannot assign requested address"
I believe this is because new HttpClient is created instead of using the HttpClientFactory and the ports are getting consumed very quickly (the known issue of using HttpClient inside Azure functions).

Compiling issue with 'Microsoft.Azure.NotificationHubs.CDataMember'

Hi there,

I have an UWP Project, that is using Notificationhub.
When I compile my code in debug mode (x86) everything works fine.
When I try to create a store package the compilation fails for configuration release x86 with error:

"System.Runtime.Serialization.InvalidDataContractException: Type 'Microsoft.Azure.NotificationHubs.CDataMember' does not have a static method 'GenerateSchema' that takes a parameter of type 'System.Xml.Schema.XmlSchemaSet' as specified by the XmlSchemaProviderAttribute attribute."

I am using VS2019 Version 16.4.2
Nuget Package is: Microsoft.Azure.NotificatioHubs Version 3.3.0

What causes this isssue??

Kind regards,

Martin

CreateOrUpdateInstallationAsync would not update push channel

I try to call CreateOrUpdateInstallationAsync in my backend service for install device, however, it would not affect correctly when the update information includes the push channel.

I use the following code to test:

        var existInstallation = await hub.GetInstallationAsync(installation.InstallationId);

        await hub.CreateOrUpdateInstallationAsync(installation);

        var updatedInstallation = await hub.GetInstallationAsync(installation.InstallationId);

        if (existInstallation.PushChannel == updatedInstallation.PushChannel && updatedInstallation.PushChannel != installation.PushChannel)
        {
            throw new Exception("Push channel update failed.");
        }

It should not throw the Exception if the push channel updated correctly.

Additionally, if I delete the installation and then install again, it can set the new push channel.

NotificationHubs not supporting apns-push-type : voip only in Sandbox mode

Given a configured NotificationHub with a .voip
When using test-send facility
And attempting to send the vanilla payload {"aps":{"alert":"Notification Hub test notification"}}'
Then I should see the Outcome The Notification was successfully sent to the Push Notification System

bundleId mode outcome
notVoip Production successfully sent
Voip Production successfully sent
notVoip Sandbox successfully sent
Voip Sandbox The Notification payload is invalid

This is repeatable

Diagnosis

Having bypassed the notification hub and used curl to send the equivalent request directly to https://api.sandbox.push.apple.com:443

     --http2 \
     --header "authorization: bearer $JWT" \
     --header "apns-topic: ${BUNDLEID}" \
     --data '{"aps":{"alert":"Notification Hub test notification"}}' \ 

We got success for a the scenarios

Conclusion

The Notification Hub is interfering with the apns-push-type header

For bundle id ending .voip

A failure can be invoke by setting alert as the apns-push-type
Setting voip as the apns-push-type the issue is fixed.

     --http2 \
     --header "authorization: bearer $JWT" \
     --header "apns-topic: ${BUNDLEID}" \
     --header "apns-push-type: alert" \
     --data '{"aps":{"alert":"Notification Hub test notification"}}' \ 
bundleId apns-push-type outcome
notVoip alert successfully sent
Voip voip successfully sent
Voip alert notification fails

Note:

This behaviour was first noticed in September 2109 around the time of the IOS 13/Xcode 11 release.

Microsoft.Azure.NotificationHubs.Messaging.MessagingException

For the last two days I get lots of Microsoft.Azure.NotificationHubs.Messaging.MessagingExceptions without any modification in my code. I have upgraded Microsoft.Azure.NotificationHubs to the leatest 3.2.1.0 varsion but it didn't help. Never had this kind of exceptions before

Here is a detailed exception message:

The remote server returned an error: (500) InternalServerError. Reason: 50002: Provider Internal Error..TrackingId:427adaf8-eb0a-4a8a-af86-dc5998cc4388,TimeStamp:2019-10-09T13:04:58.7861049Z

Any help would be greatly appriciated

Microsoft.Azure.NotificationHubs.GcmRegistrationDescription; Microsoft.Azure.NotificationHubs.NamespaceManager ; Microsoft.Azure.NotificationHubs.NotificationHubDescription classes are missing in Microsoft.Azure.NotificationHubs 3.0.0 dll

We tried to upgrade to Microsoft.Azure.NotificationHubs 3.0.0 from 1.0.6 but our build is failing, I see Microsoft.Azure.NotificationHubs.GcmRegistrationDescription; Microsoft.Azure.NotificationHubs.NamespaceManager ; .Microsoft.Azure.NotificationHubs.NotificationHubDescription classes are missing in Microsoft.Azure.NotificationHubs 3.00 dll

Is this a proper client SDK for Xamarin apps?

This SDK contains (hopefully) full set of functions supported by Azure Notification Hubs. It's for sure a natural choice for server-side apps, but since it targets .NET Standard, it could also be used on the mobile-client side (Xamarin). Is this a good idea? Of course we're not going to use API to send notifications from there, only to register.

There are other SDKs for Xamarin, but they are just wrappers around native iOS/Android SDKs and seem to be old and not updated anymore:
https://github.com/xamarin/XamarinComponents/tree/master/XPlat/AzureMessaging

It would be great if there was a clear recommendation somewhere.

Remove Task.Delay in mocked tests

As noted in the PR #15, we have time intervals between checks such as the following:

await _hubClient.CreateOrUpdateInstallationAsync(installation);

await Task.Delay(TimeSpan.FromSeconds(1));

Assert.True(await _hubClient.InstallationExistsAsync(installationId));

This is unnecessary if we are testing against mocks, and is only applicable to when running integration tests when the Notification Hubs connection string is specified. Instead, we should have the following which delays only when running non-mocked tests.

Task Sleep(TimeSpan span)
{
    // If mocked then only return an empty task, otherwise sleep
}

apns-topic not working for iOS voip pushes

We need to send both iOS "alert" pushes and "voip" pushes over the same notification hub.

Wer are using SendTemplateNotificationAsync with two different templates.
One for alerts and one for voip pushes.
We have two correct device tokens and we are also adding the required headers to the templates.

For sending voip pushes with token based authentification the "apns-topic" needs to be set to the bundleId + suffix ".voip" and the "apns-push-type" should be "voip".

We tried with TemplateRegistrations and TemplateInstallations

The BundleId in the the notification hub in the portal is configured without the ".voip" suffix.

The "alert" pushes work, but the "voip" pushes return the error "WrongToken".

If we change the BundleId in the portal to bundleId + suffix ".voip", the voip pushes work and the "alerts" stop working.

This looks like the "apns-topic" is not passed to apple or overwritten when calling their api.
When calling directly the apple api via http everything works.

Microsoft.Azure.NotificationHubs version 3.3.0 APNs: Token Authentication Mode not working

Hi,

I am trying to switch from authentication mode "Certificate" to "Token". According to the documentation it should be enough to change the credentials in the azure portal.

After doing that, the "Test Send" of the portal still works as expected: the push notifications arrive on the devices.

But when using the Microsoft.Azure.NotificationHubs SDK, nothing is sent to the client.

When I set the "enableTestSend" flag while creating the NotificationHub Client (NotificationHubClient.CreateClientFromConnectionString("", "", true)), and look at the result of the SendNotificationAsync method, I get a failure for each registered apple device, saying "The Token obtained from the Token Provider is wrong".

Here is my notification body:

{
   "data":{
      "someAdditonalData":"data"
   },
   "aps":{
      "alert":"Notification Text"
   }
}

I set the following headers:

  • apns-priority: 5
  • apns-topic: my.bundle.id
  • apns-collapse-id: 10

Further, the SDK seems to add another header: "ServiceBusNotification-Format: apple"

I don't see what I am missing here. Shouldn't my code be the same, no matter what authentication mode I use?

Thanks in advance.

Best regards

SendTemplateNotificationAsync - removing invalid registration

This issue happens in my integration tests. Note that I am running these tests from my local machine. However they were passing when I was on version 1.x of the nuget package. Since 2.x this has started happening.

(for simplicity I list here only the main methods - do consider that the registration id i pass in there is always the correct one)

I call:

  1. CreateOrUpdateRegistrationAsync
  2. DeleteRegistrationAsync
    this always passes and I never get an exception

I call:

  1. CreateOrUpdateRegistrationAsync
  2. SendTemplateNotificationAsync
  3. DeleteRegistrationAsync
    this never passes and I get MessagingEntityNotFoundException on DeleteRegistrationAsync.

Does SendTemplateNotificationAsync method somehow deletes the invalid registration that is created in CreateOrUpdateRegistrationAsync.
In my theory - it can'f find a device then it removes the registration automatically - but I do not know. Can you please verify this?

How to get the list of NotificationHubs from the connectionstring?

In the old package (before the .net standard) we use to be able to do something like:

var namespacemanager = NamespaceManager.CreateFromConnectionString(connectionString);
namespacemanager.GetNotificationHubs();

I guess those "management" api were remove to the package and put into Microsoft.Azure.Management.NotificationHub. My problem with that package is that I don't see how to simply use the connectionstring.

It's kind of the same story as the one in servicebus here: Azure/azure-service-bus-dotnet#358.
But they finally decided to add back some management capabilities in Microsoft.Azure.ServiceBus using directly the connectionstring

So I guess my question is how could I get the list of NotificationHubs from the namespace connectionstring and if it's not possible yet, is there any plan/timeline to add that back to the .net standard package.

Thanks

hubClient.SendAppleNativeNotificationAsync(json, targets) causes Apple to only try to deliver a notification once.

hubClient.SendAppleNativeNotificationAsync(json, tags)

is the same as doing this

hubClient.SendNotificationAsync(new AppleNotification(json), tags);

What you need to do to get Apple to NOT drop the notification after the first deliver fails is to set a expiry time like this.

notification = new AppleNotification(json);
notification.Expiry = DateTime.UtcNow.AddMonths(1);
hubClient.SendNotificationAsync(notification, tags);

So either the default for AppleNotification.Expiry should be changed from NULL to something like DateTime.UtcNow.AddDays(1) or SendAppleNativeNotificationAsync should be deprecated as using it will cause many of you push requests to fail delivery to the devices.

Invalid Apns token Exception

Hi,

I wrote this code and run successfuly with FCM But same code didnt work Apns I've got this error.

Any idea?

bla bla bla...

` var installation = new Installation()
{
Platform = platform,
PushChannel = appInstallation.PushChannel,
PushChannelExpired = false,
InstallationId = appInstallation.InstallationId, //Sample: e26741c15c284174a3566c52323a8edd
Tags = tags,
Templates = templates

            };
            await _hub.CreateOrUpdateInstallationAsync(installation);`

image

Thank you.

Migrating from GCM to FCM

I've upgraded my nuget package from 1.0.9 to 3.0.2 to migrate from GCM to FCM. Based on the release description, it looks like GCM methods now route through the FCM api. So is there anything in my code I need to change (e.g. can I continue to use SendGcmNativeNotification)?

Exception trying to load Newtonsoft.Json Version 10 when calling CreateOrUpdateInstallationAsync

I'm using version 3.0.1 in my Azure Function project. Every time I call CreateOrUpdateInstallationAsync I get an exception saying that it's trying to load Newtonsoft.Json v10. I have Newtonsoft.Json version 11.0.2 installed (and require it, I can't use a lower version). I'm not sure why I'd be getting this, since the NotificationHubs package says it requires a version of the Json lib >=10.0.3. Here's the full exception details:

Edit1: I have no idea why it's bolding some chunks, tried editing it to remove it, couldn't figure it out
Edit 2: I tried downgrading package versions, and kept getting this exact same exception until I got down to version 1.0.9. This is the latest version I'm able to use without getting an exception.

`System.IO.FileNotFoundException: Could not load file or assembly 'Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The system cannot find the file specified.
File name: 'Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed'
at Microsoft.Azure.NotificationHubs.Installation.ToJson()
at Microsoft.Azure.NotificationHubs.NotificationHubClient.d__53.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at BurnableCloud.Shared.Notifications.d__12.MoveNext()

Pre-bind state information
LOG: DisplayName = Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
(Fully-specified)
LOG: Appbase = file:///C:/Users/myusernamecleverlyremoved/AppData/Local/AzureFunctionsTools/Releases/1.6.0/cli/
LOG: Initial PrivatePath = NULL
Calling assembly : Microsoft.Azure.NotificationHubs, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35.

LOG: This bind starts in LoadFrom load context.
WRN: Native image will not be probed in LoadFrom context. Native image will only be probed in default load context, like with Assembly.Load().
LOG: Using application configuration file: C:\Users\myusernamecleverlyremoved\AppData\Local\AzureFunctionsTools\Releases\1.6.0\cli\func.exe.Config
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: The same bind was seen before, and was failed with hr = 0x80070002.`

Question: Send Notifications

Hi,

Consider following scenario:
An ios device registers with an back-end API and a tag A. the back-end API makes an installation in notification hub with the tag.
An other android device registers with an back-end API and a also tag A. the back-end API makes an installation in notification hub with the tag.

Now a scheduled job is running and wants to send notifications to tag A,

The question is how can the back-end send notifications to all devices with tag A without calling both methods SendApnsNotificationAsync and SendFcmNotificationAsync to get all devices. Because at this moment the back-end has only the tag and the message nothing else, so the back-end does not know which platforms are involved. So in case only one registration would be there the second call lets say SendFcmNotificationAsync will always give an exception (Something like: No registrations found).

System.ArgumentException

Hi,

for the last few days I am constantly getting System.ArgumentException exception

The Apns certificate is expired. .TrackingId:66d9de0f-7f70-4451-b7a8-344003a45da5_G6,TimeStamp:11/26/2019 8:52:24 AM The Apns certificate is expired. 

I double-checked on iTunes Connect and the certificates that are uploaded to Azure are valid (will expire in few months)

Any help on that would be appreciated

NotificationHubConnectionStringBuilder has no ToString method

I expected this to just work (based on my previous experiences with ConnectionStringBuilder types):

using Microsoft.Azure.NotificationHubs;
var builder = new NotificationHubConnectionStringBuilder("Endpoint=sb://my-namespace.servicebus.windows.net/")
{
    SharedAccessKeyName = "DefaultFullSharedAccessSignature",
    SharedAccessKey = "<therealsecret>"
};

var connectionString = builder.ToString();

Expected
Endpoint=sb://my-namespace.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=<therealsecret>

Actual
Microsoft.Azure.NotificationHubs.NotificationHubConnectionStringBuilder

'CreateClientFromConnectionString' Functionality Using "enableTestSend"

I am attempting to diagnose a FCM notification to a single device with a channel scenario which isn't being delivered. I am trying to use 'CreateClientFromConnectionString' with 'enableTestSend' enabled. This the only method that I know of for this type of debugging, but when the notification is sent it crashes the Azure debugging instance and disconnects from VS2019. This event has been consistent since enabling the parameter.

I opened a support case which was assigned to the Azure Service Bus Team, Case 119080124004303. It was recommended that I open an issue here. The recommendation is based on the following exception which the team found:

{"level":1,"method":"System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw","assembly":"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","line":0},{"level":2,"method":"System.Threading.ExecutionContext.RunInternal","assembly":"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","line":0},{"level":3,"method":"System.Threading.ExecutionContext.Run","assembly":"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","line":0},{"level":4,"method":"System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem","assembly":"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","line":0},{"level":5,"method":"System.Threading.ThreadPoolWorkQueue.Dispatch","assembly":"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","line":0}]},{"id":65666079,"outerId":29613747,"typeName":"System.ArgumentNullException","message":"Value cannot be null.\r\nParameter name: notificationId","hasFullStack":true,"parsedStack":[{"level":0,"method":"Microsoft.Azure.NotificationHubs.NotificationHubClient+d__50.MoveNext","assembly":"Microsoft.Azure.NotificationHubs, Version=3.0.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35","line":0},{"level":1,"method":"System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw","assembly":"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","line":0},{"level":2,"method":"System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification","assembly":"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","line":0},{"level":3,"method":"System.Runtime.CompilerServices.TaskAwaiter`1.GetResult","assembly":"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","line":0},{"level":4,"method":"NotificationService.AsynchNotification+d__13.MoveNext","assembly":"WWW, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","fileName":"C:\Projects\IdentityCheckpoint\VS2019\IdentityCheckpoint\WWW\NotificationHandler.cs","line":158}]}],"severityLevel":"Critical"}}}
The thread 0x6c8 has exited with code 0 (0x0).

RegistrationExistsAsync throws MessagingEntityNotFoundException if it can't find registration

Consider following code:

var exists = await _hub.RegistrationExistsAsync(registrationId);
                if (exists)
                    await _hub.DeleteRegistrationAsync(registrationId);

I am making sure the registration exists before I try to delete it - simply to avoid MessagingEntityNotFoundException.

However RegistrationExistsAsync throws "MessagingEntityNotFoundException" - I do not see the point in that. Shouldn't it return "false" if it can't find the registration?

CancellationToken support

As far as I can see, CancellationToken can be used to cancel http calls, but it is simply removed in public overloads. What are the reasons for this? I am ready to do PR to bring it out.

Sending data and notification property to FCM

We are currently using CreateRegistrationAsync works to send a payload that ends up the data property when received by an Android device. Which works fine when the app is in the foreground, but doesn't result in a push notification when the app is in background or stopped.

However, we need the payload to be:

{
  "data" :  { 
      "objectId" : 4,
      "name" : "Joe Smith"
  },
  "notification" : { 
      "title" : "This is a title",
      "body" : "And this is a body"
}

This is to match the specification from Firebase:
https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages

How can I register a template to include both "data" and "notification" keys please? I have tried just adding "notification" in my template, but it ends up being nested under "data" - rather than being a sibling.

TIA ๐Ÿ˜ƒ

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.