C# Send Push Notification Firebase Cloud Messaging - c#

I'm trying to send a notification to Firebase Messaging according to the https://github.com/Firebase/firebase-admin-dotnet package.
I generated a private key in Firebase and added the project.
To send I am doing it as follows.
[HttpPost]
public async Task<dynamic> PostMensagem()
{
var message = new FirebaseAdmin.Messaging.Message()
{
Data = new Dictionary<string, string>()
{
["FirstName"] = "FirstName",
["LastName"] = "LastName"
},
Notification = new FirebaseAdmin.Messaging.Notification
{
Title = "Message Title",
Body = "Message Body"
},
Android = new FirebaseAdmin.Messaging.AndroidConfig()
{
Priority = Priority.Normal,
TimeToLive = TimeSpan.FromHours(1),
RestrictedPackageName = "com.example.test",
},
Topic = "Topic",
};
var result = await FirebaseMessaging.DefaultInstance.SendAsync(message);
Console.WriteLine(result); //projects/myapp/messages/2492588335721724324
return result;
}
In response, I receive a url something like "//projects/myapp/messages/2492588335721724324" but the notification does not reach the cloud and neither does android.
Am I forgetting something? What do I need to do to get notifications sent from my SDK project to appear in Firebase Cloud Messaging?

Related

Alexa.NET cannot create a reminder : Invalid Bearer Token

I want to create push notifications to my Alexa Devide. Due the push notification program is closed I am trying to create reminders. The final idea is to create an Azure Function with this code and being called when a TFS Build faild.
I'm using Alexa.NET and Alexa.NET.Reminders from a console application, already have and Alexa Skill with all the permissions granted, in the Alexa portal and in the mobile app.
Everything seems to work nice until I try to read the reminders in my account, when get an exception "Invalid Bearer Token"
this is the code:
[Fact]
public async Task SendNotificationTest()
{
var clientId = "xxxx";
var clientSecret = "yyyy";
var alexaClient = clientId;
var alexaSecret = clientSecret;
var accessToken = new Alexa.NET.AccessTokenClient(Alexa.NET.AccessTokenClient.ApiDomainBaseAddress);
var token = await accessToken.Send(alexaClient, alexaSecret);
var reminder = new Reminder
{
RequestTime = DateTime.UtcNow,
Trigger = new RelativeTrigger(12 * 60 * 60),
AlertInformation = new AlertInformation(new[] { new SpokenContent("test", "en-GB") }),
PushNotification = PushNotification.Disabled
};
var total = JsonConvert.SerializeObject(reminder);
var client = new RemindersClient("https://api.eu.amazonalexa.com", token.Token);
var alertList = await client.Get();
foreach (var alertInformation in alertList.Alerts)
{
Console.WriteLine(alertInformation.ToString());
}
try
{
var response = await client.Create(reminder);
}
catch (Exception ex)
{
var x = ex.Message;
}
}
Are there any examples to get the access token?
Am I missing a step in the process?
Thanks in advance.
N.B. The reminders client requires that you have a skill with reminders persmission enabled, and the user must have given your skill reminders permission (even if its your development account)
Creating a reminder
using Alexa.NET.Response
using Alexa.NET.Reminders
....
var reminder = new Reminder
{
RequestTime = DateTime.UtcNow,
Trigger = new RelativeTrigger(12 * 60 * 60),
AlertInformation = new AlertInformation(new[] { new SpokenContent("it's a test", "en-GB") }),
PushNotification = PushNotification.Disabled
};
var client = new RemindersClient(skillRequest);
var alertDetail = await client.Create(reminder);
Console.WriteLine(alertDetail.AlertToken);
Retrieving Current Reminders
// Single reminders can be retrieved with client.Get(alertToken)
var alertList = await client.Get();
foreach(var alertInformation in alertList.Alerts)
{
//Your logic here
}
Deleting a Reminder
await client.Delete(alertToken);

YouTrack REST API - Create new priority

I I’m looking for a way to create a new priority value with the REST API.
In the documentation I found the following endpoint:
/rest/admin/customfield/bundle/{bundleName}/{fieldValue}?{description}&{colorIndex}
Calling this endpoint returns a 415 status code with the content:
{"value":"Unsupported Media Type"}
Here is my code:
var connection = YouTrackConnectionFactory.GetConnection();
var client = await connection.GetAuthenticatedHttpClient();
var priorityValue = "SomeNewPrio";
var enumerationName = "Priorities";
var queryString = new Dictionary<String, String>
{
{ "bundleName", enumerationName },
{ "fieldValue", priorityValue },
{ "description", WebUtility.UrlEncode( "Automatically created priority" ) },
{ "colorIndex", "9" }
};
var response = await client.PutAsync( $"/rest/admin/customfield/bundle/{enumerationName}/{priorityValue}", new FormUrlEncodedContent( queryString ) );
response.EnsureSuccessStatusCode();
Is there something wrong with my data or is there another endpoint I should be using?

How to store & retrieve Bot Data in Azure Table storage with directLine channel?

I'm using Microsoft Bot Framework with directLine channel. My Bot is a part of company's customer portal from where I fetch some user information and store it in BotState using stateClient as shown below
public ActionResult Index()
{
var userId = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
GetTokenViaBootStrap().Wait();
var botCred = new MicrosoftAppCredentials(
ConfigurationManager.AppSettings["MicrosoftAppId"],
ConfigurationManager.AppSettings["MicrosoftAppPassword"]);
var stateClient = new StateClient(botCred);
BotState botState = new BotState(stateClient);
BotData botData = new BotData(eTag: "*");
botData.SetProperty<string>("UserName", result.UserInfo.GivenName + " " + result.UserInfo.FamilyName);
botData.SetProperty<string>("Email", result.UserInfo.DisplayableId);
botData.SetProperty<string>("GraphAccessToken", UserAccessToken);
botData.SetProperty<string>("TokenExpiryTime", result.ExpiresOn.ToString());
stateClient.BotState.SetUserDataAsync("directline", userId, botData).Wait();
var UserData = new UserInformationModel
{
UserId = userId,
UserName = result.UserInfo.GivenName + " " + result.UserInfo.FamilyName
};
return View(UserData);
}
As its a directLine channel, I'm connecting my bot using secret in javascript as shown below:
BotChat.App({
bot: { id: 'my_bot_id', name: 'my_bot_id' },
resize: 'detect',
sendTyping: true, // defaults to false. set to true to send 'typing' activities to bot (and other users) when user is typing
user: { id: UserData.UserId},
directLine: {
secret: "my_bot_secret"
}
}, document.getElementById('my_bot_id'));
I'm accessing user information data in Node js Bot captured in MVC site as shown below:
function sessionUserCapture(session) {
switch (session.message.address.channelId) {
case 'skypeforbusiness':
// some code
break;
case 'directline':
userName= session.userData.UserName;
userEmail= session.userData.Email;
//some code
break;
case 'slack':
// some code
}
}
I referred Microsoft's Save state data from Manage state data for above code and then I used userData available in the session to access this data in my Node.JS Bot.
As the StateClient is Deprecated, I referred this to replace stateclient with Azure Table storage. However, I'm not able to understand how can I store the above data in the Table Storage.
Can anyone suggest any article which I can refer to solve this issue?
My Bot is in NodeJs and the I'm using directLine channel in a C# MVC application.
One option is to use the Microsoft Azure Storage Client Library for .NET, as explained in the answer here: How to retrieve Saved Conversation Data in Azure (Tablelogger) Just make sure to follow the exact same PartitionKey strategy as is followed by the TableBotDataStore class, and serialize the data field correctly.
--
Edit:
I tested this out, and it does in fact work as expected.
public class WebChatController : Controller
{
public ActionResult Index()
{
var connectionString = ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString;
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
CloudTable table = tableClient.GetTableReference("BotStore");
string userId = Guid.NewGuid().ToString();
TableQuery<BotDataRow> query = new TableQuery<BotDataRow>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, userId));
var dataRow = table.ExecuteQuery(query).FirstOrDefault();
if(dataRow != null)
{
dataRow.Data = Newtonsoft.Json.JsonConvert.SerializeObject(new
{
UserName = "This user's name",
Email = "whatever#email.com",
GraphAccessToken = "token",
TokenExpiryTime = DateTime.Now.AddHours(1)
});
dataRow.Timestamp = DateTimeOffset.UtcNow;
table.Execute(TableOperation.Replace(dataRow));
}
else
{
var row = new BotDataRow(userId, "userData");
row.Data = Newtonsoft.Json.JsonConvert.SerializeObject(new
{
UserName = "This user's name",
Email = "whatever#email.com",
GraphAccessToken = "token",
TokenExpiryTime = DateTime.Now.AddHours(1)
});
row.Timestamp = DateTimeOffset.UtcNow;
table.Execute(TableOperation.Insert(row));
}
var vm = new WebChatModel();
vm.UserId = userId;
return View(vm);
}
public class BotDataRow : TableEntity
{
public BotDataRow(string partitionKey, string rowKey)
{
this.PartitionKey = partitionKey;
this.RowKey = rowKey;
}
public BotDataRow() { }
public bool IsCompressed { get; set; }
public string Data { get; set; }
}
}
In the node bot:
'use strict';
const builder = require('botbuilder');
const restify = require('restify');
var azure = require('botbuilder-azure');
var tableName = 'BotStore';
var azureTableClient = new azure.AzureTableClient(tableName,'accountname','accountkey');
var tableStorage = new azure.AzureBotStorage({ gzipData: false }, azureTableClient);
const connector = new builder.ChatConnector({
appId: process.env.MicrosoftAppId,
appPassword: process.env.MicrosoftAppPassword
});
const server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3979, () => {
console.log(`${server.name} listening to ${server.url}`);
});
server.post('/api/messages', connector.listen());
var bot = new builder.UniversalBot(connector)
.set('storage', tableStorage);;
bot.dialog('/',
[
function (session){
var data = session.userData;
}
]);
The code you are using is using the deprecated default state and will not work. In order to accomplish what you would like it depends on where you are in your code. The deciding factor is if you have access to the context object or not.
For example if you are in the MessagesController you will not have access to the context object and your code might look like this:
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
if (activity.Type == ActivityTypes.Message)
{
var message = activity as IMessageActivity;
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
{
var botDataStore = scope.Resolve<IBotDataStore<BotData>>();
var key = Address.FromActivity(message);
var userData = await botDataStore.LoadAsync(key, BotStoreType.BotUserData, CancellationToken.None);
userData.SetProperty("key 1", "value1");
userData.SetProperty("key 2", "value2");
await botDataStore.SaveAsync(key, BotStoreType.BotUserData, userData, CancellationToken.None);
await botDataStore.FlushAsync(key, CancellationToken.None);
}
await Conversation.SendAsync(activity, () => new Dialogs.RootDialog());
}
}
then to get the data:
userData.GetProperty<string>("key 1");
The other situation would be if you did have access to the context object like in a Dialog for example, your code might look like this:
context.UserData.SetValue("key 1", "value1");
context.UserData.SetValue("key 2", "value2");
then to get the data:
context.UserData.GetValue<string>("key 1");
Have you configured your bot to connect to Azure Table Storage in Global.asax.cs, instead of the deprecated default state?
I have written a blog post with full details on how to move your bot's state to Azure Table Storage which you should review
here
protected void Application_Start()
{
Conversation.UpdateContainer(
builder =>
{
builder.RegisterModule(new AzureModule(Assembly.GetExecutingAssembly()));
// Using Azure Table for storage
var store = new TableBotDataStore(ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString);
builder.Register(c => store)
.Keyed<IBotDataStore<BotData>>(AzureModule.Key_DataStore)
.AsSelf()
.SingleInstance();
});
GlobalConfiguration.Configure(WebApiConfig.Register);
}

Fire TriggeredSends from ExactTarget's API using HttpClient REST

I've read along the way that Salesforce (I'm extremely new to this 3rd party platform) has a FUEL SDK which one can use instead of the version (using HttpClient -- REST instead of SOAP).
Please correct me if using FUEL SDK is the only way to go about requesting Salesforce's endpoints. Currently I am attempting to hit ExactTargets's API endpoints using HttpClient. These are the tutorials I've been basing my code off of:
https://developer.salesforce.com/docs/atlas.en-us.mc-apis.meta/mc-apis/messageDefinitionSends.htm
https://developer.salesforce.com/docs/atlas.en-us.mc-getting-started.meta/mc-getting-started/get-access-token.htm
Wanted Result:
To be able to request a Triggered Send email based off a template inside of ExactTarget.
Problem:
The Salesforce endpoint continuously returns a 404. I am able to receive the authorization token successfully. The GetAccessToken method is omitted for brevity
https://www.exacttargetapis.com/messaging/v1/messageDefinitionSends/key:MyExternalKey/send
I do not understand why the 2nd POST request to //www.exacttargetapis.com/..... returns a 404 but the authorization works. This leads me to believe that I do not have to use the FUEL SDK to accomplish triggering a welcome email.
Code:
private const string requestTokenUrl = "https://auth.exacttargetapis.com/v1/requestToken";
private const string messagingSendUrl = "https://www.exacttargetapis.com/messaging/v1/messageDefinitionSends";
private string exactTargetClientId = ConfigurationManager.AppSettings["ExactTargetClientId"];
private string exactTargetClientSecret = ConfigurationManager.AppSettings["ExactTargetClientSecret"];
private string TriggerEmail(User model, string dbName)
{
var etExternalKeyAppSetting = ConfigurationManager.AppSettings.AllKeys.FirstOrDefault(x => x.Equals(dbName));
if (etExternalKeyAppSetting != null)
{
string etExternalKey = ConfigurationManager.AppSettings[etExternalKeyAppSetting];
HttpClient client = new HttpClient
{
BaseAddress = new Uri(string.Format(#"{0}/key:{1}/send", messagingSendUrl, etExternalKey)),
DefaultRequestHeaders =
{
Authorization = new AuthenticationHeaderValue("Bearer", this.GetAccessToken())
}
};
try
{
var postData = this.CreateExactTargetPostData(model.Email, etExternalKey);
var response = client.PostAsync(client.BaseAddress
, new StringContent(JsonConvert.SerializeObject(postData).ToString()
, Encoding.UTF8
, "application/json")).Result;
// get triggered email response
if (response.IsSuccessStatusCode)
{
dynamic result = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result);
}
}
catch (Exception ex)
{
string message = ex.Message;
}
}
return "testing";
}
private object CreateExactTargetPostData(string email, string extKey)
{
var fromData = new
{
Address = ConfigurationManager.AppSettings["AwsSenderEmail"],
Name = "Test"
};
var subscriberAttributes = new { };
var contactAttributes = new
{
SubscriberAttributes = subscriberAttributes
};
var toData = new
{
Address = email,
//SubscriberKey = extKey,
//ContactAttributes = contactAttributes
};
var postData = new
{
From = fromData,
To = toData
};
return postData;
}
I have also tried using Advanced REST Client using the following:
URL:
https://www.exacttargetapis.com/messaging/v1/messageDefinitionSends/key:MyExternalKey/send
POST
Raw Headers:
Content-Type: application/json
Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Raw Payload:
{
"From": {
"Address": "code#exacttarget.com",
"Name": "Code#"
},
"To": {
"Address": "example#example.com",
"SubscriberKey": "example#example.com",
"ContactAttributes": {
"SubscriberAttributes": {
"Region": "West",
"City": "Indianapolis",
"State": "IN"
}
}
},
"OPTIONS": {
"RequestType": "ASYNC"
}
}
Issue was my App in the AppCenter was pointing to the incorrect login for MarketingCloud =(

Error : The security token included in the request is invalid - Windows Phone Using AWS SNS

I am using below code to register the device(Windows Phone) in AWS SNS as an endpoint in the application
CognitoAWSCredentials cognitoProvider = new CognitoAWSCredentials(UserId,
IdentitypoolID,
UnAuthRoleARN,
AuthRoleARN,
Region);
AmazonSimpleNotificationServiceClient sns = new AmazonSimpleNotificationServiceClient(cognitoProvider.GetCredentials().AccessKey.ToString(),
cognitoProvider.GetCredentials().SecretKey.ToString(), REgion); //provide credentials here
var channelOperation = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
CreatePlatformEndpointRequest epReq = new CreatePlatformEndpointRequest();
epReq.PlatformApplicationArn = ApplicationArn;
epReq.Token = channelOperation.Uri.ToString();
CreatePlatformEndpointResponse epRes = await sns.CreatePlatformEndpointAsync(epReq);
CreateTopicRequest tpReq = new CreateTopicRequest();
SubscribeResponse subsResp = await sns.SubscribeAsync(new SubscribeRequest()
{
TopicArn = TopicArn,
Protocol = "application",
Endpoint = epRes.EndpointArn
});
While create an endpoint it throws an error The security token included in the request is invalid while execute below code
CreatePlatformEndpointResponse epRes = await sns.CreatePlatformEndpointAsync(epReq);
Please help me to achieve this. Thanks in advance
Use the below code to register a windows phone device in AWS SNS Application. I can create endpoint using the below code.
private async void Push()
{
CognitoAWSCredentials cognitoProvider = new CognitoAWSCredentials(UserId,
IdentitypoolID,
UnAuthRoleARN,
AuthRoleARN,
Region);
using (var sns = new AmazonSimpleNotificationServiceClient(credentials, RegionEndpoint.USEast1))
{
var channelOperation = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
CreatePlatformEndpointRequest epReq = new CreatePlatformEndpointRequest();
epReq.PlatformApplicationArn = "PlatformApplicationARN";
epReq.Token = channelOperation.Uri.ToString();
CreatePlatformEndpointResponse epRes = await sns.CreatePlatformEndpointAsync(epReq);
CreateTopicRequest tpReq = new CreateTopicRequest();
SubscribeResponse subsResp = await sns.SubscribeAsync(new SubscribeRequest()
{
TopicArn = "TopicARN",
Protocol = "application",
Endpoint = epRes.EndpointArn
});
channelOperation.PushNotificationReceived += ChannelOperation_PushNotificationReceived;
}
}

Categories