Notification Hub with localized messages - azure

i just came up with a new problem but the same context azure. now i am trying to implement Multilinqual(localized) push notifications so i am following this localized push notification so this link inculde lot of work of making categories i just wanted to omit them so i am trying to use direct code for subscribing the toast notification on the basis of tag given in Bachend clien app that generate toast notification...here is Backend client app code..
NotificationHubClient hub = NotificationHubClient.CreateClientFromConnectionString("Endpoint=sb://samplenotificationhub-ns.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=", "samplenotificationhub");
var notification = new Dictionary<string, string>() {
{"News_English", "World News in English!"},
{"News_French", "World News in French!"},
{"News_Mandarin", "World News in Mandarin!"}};
await hub.SendTemplateNotificationAsync(notification, "World");
first i tried it on my previously working sample app that can receive Push notification on the basis of tags also so i just tried to update its code to get template based toaste notification but unfortunately i am not getting anything..here is the code..
private void AcquirePushChannel()
{
CurrentChannel = HttpNotificationChannel.Find("mychannel");
if (CurrentChannel == null)
{
CurrentChannel = new HttpNotificationChannel("mychannel");
CurrentChannel.Open();
CurrentChannel.BindToShellToast();
CurrentChannel.BindToShellTile();
}
CurrentChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(async (o, args) =>
{
var tags = new HashSet<string>();
tags.Add("World");
var hub = new NotificationHub("samplenotificationhub", "Endpoint=sb://samplenotificationhub-ns.servicebus.windows.net/;SharedAccessKeyName=DefaultListenSharedAccessSignature;SharedAccessKey=");
var template = String.Format(#"<toast><visual><binding template=""ToastText01""><text id=""1"">$(News_English)</text></binding></visual></toast>");
await hub.RegisterTemplateAsync(args.ChannelUri.ToString(),template,"hello", tags);
// await hub.RegisterNativeAsync(args.ChannelUri.ToString(),tags);
});
}
so if you know anything about it..please guide me any kind of help or suggetion is appreciated..

Hello Friends I again able to solve my problem so the mistake i am doing here is i am following the link blindly as it is for Windows store apps and i wanted to implemented the same for windows phone 8 so what i am doing wrong is using the same Tamplate that is used in windows store apps for windows phone 8 too. so what i understand is this if wanted to target the multiple platforms from a notification hub then your client app that send the toast notification has the same notification for all but all your platform will handle it differently Like for windows 8 the tamplate i am using will work but windows phone this template will work.
string toast = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<wp:Notification xmlns:wp=\"WPNotification\">" +
"<wp:Toast>" +
"<wp:Text1>Hello Windows phone</wp:Text1>" +
"</wp:Toast> " +
"</wp:Notification>";
so different platform will have different platform.hope it help somebody else too.

Related

Send the message to personal chat instead of group chat using ms teams chatbot

I would like to post a message to personal chat instead of group chat while message post from group chat how to achieve this ?.
Is there is any methods available related to this issue ?.
As the others have noted in this thread, you need to use something called "Proactive Messaging". I see you're using node.js though, so here is a better sample than the C# or Java people have posted already: https://github.com/pnp/teams-dev-samples/tree/main/samples/bot-proactive-messaging . I put both a dotnet as well as a node.js version in the sample, and there are some links at the bottom of the page to read more about the topic. Here is also a link to a video session where I talk more about the concept: https://www.youtube.com/watch?v=mM7-fYdcJhw&t=1398s
It is important to know that proactive messaging will only work if you have a "context" with the user already, which basically means they have to have installed your app already. It is possible to pre-install it on their behalf though. You need to use Graph to do this, and you can read more about it here: https://learn.microsoft.com/en-us/graph/api/userteamwork-post-installedapps?view=graph-rest-1.0&tabs=http .
You can post a proactive personal message to a user:
Please find below sample code:
Also, before running this code, make sure that the user has installed the bot app in the personal scope or is a member of a Team which has the bot installed.
Reference docs:
https://learn.microsoft.com/en-us/java/api/com.microsoft.cognitiveservices.speech.transcription.conversation.createconversationasync?view=azure-java-stable
using Microsoft.Bot.Builder;
using Microsoft.Bot.Connector;
using Microsoft.Bot.Connector.Authentication;
using Microsoft.Bot.Schema;
using Microsoft.Bot.Schema.Teams;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Teams.Bot.Conversations
{
class Program
{
public static async Task Main(string[] args)
{
//Teams internal id
string teamInternalId = "19:96391bb270744e218c04dc8f571d3d8b#thread.skype";
//The Bot Service Url needs to be dynamically stored and fetched from the Team. Recommendation is to store the serviceUrl from the bot Payload and later re-use it to send proactive messages.
string serviceUrl = "https://smba.trafficmanager.net/emea/";
//the upn of the user who should recieve the personal message
string mentionUserPrincipalName = "user#tenant.onmicrosoft.com";
//Office 365/Azure AD tenant id for the
string tenantId = "<tenant-GUID>";
//From the Bot Channel Registration
string botClientID = "<client-id>";
string botClientSecret = "<client-secret>";
var connectorClient = new ConnectorClient(new Uri(serviceUrl), new MicrosoftAppCredentials(botClientID, botClientSecret));
var user = await ((Microsoft.Bot.Connector.Conversations)connectorClient.Conversations).GetConversationMemberAsync(mentionUserPrincipalName, teamInternalId, default);
var personalMessageActivity = MessageFactory.Text($"Personal message from the Bot!");
var conversationParameters = new ConversationParameters()
{
ChannelData = new TeamsChannelData
{
Tenant = new TenantInfo
{
Id = tenantId,
}
},
Members = new List<ChannelAccount>() { user }
};
var response = await connectorClient.Conversations.CreateConversationAsync(conversationParameters);
await connectorClient.Conversations.SendToConversationAsync(response.Id, personalMessageActivity);
}
}
}

ChatBot retrieve data from SharePoint On Premise Issue

I've developed a chatbot that communicates with SharePoint on Premise,
When I run the chatbot in Emulator its work.
But When I run at Web that hosted outside of SharePoint, it does not work.
Herewith my screenshot of Error On Azure, From the result of Error is starting from XMLReader and SyndicationFeed
Success in Local Emulator
Herewith my Souce Code.
private async Task ProcessRSSAsync(ITurnContext<IMessageActivity> turnContext, LuisResult luisResult, string intent, CancellationToken cancellationToken)
{
var questionluis = turnContext.Activity.Text;
await turnContext.SendActivityAsync("intent recognize" + intent);
var intentresut = intent;
await turnContext.SendActivityAsync("Get LUIS Entity");
await turnContext.SendActivityAsync(string.Join("\t", luisResult.Entities.Select((entityObj) => entityObj.Entity)));
var entityfound = string.Join("\t", luisResult.Entities.Select((entityObj) => entityObj.Entity));
string spxurl = #"https://intra.aspac.com/sites/sg/daw/_layouts/15/srchrss.aspx?k=*%20ListId:7BC0F2C3-6366-48B8-B88A-8738BE1F9C31";
await turnContext.SendActivityAsync("Intent: " + intent.ToString() + " Entity: " + entityfound.ToString());
////---------------------------------------------------------------------------------------------
//22112019
try
{
//#ES09122019
var credentials = new NetworkCredential("email#example.com", "Pa$$w0rd", "sg.kworld.com");
var handler = new HttpClientHandler { Credentials = credentials, UseDefaultCredentials = false };
var client = new HttpClient(handler);
client.BaseAddress = new Uri("https://intra.aspac.com/sites/sg/daw/");
HttpResponseMessage resp = client.GetAsync("_layouts/15/srchrss.aspx?k=" + entityfound + "*%20ListId:7BC0F2C3-6366-48B8-B88A-8738BE1F9C31").Result;
string respString = resp.Content.ReadAsStringAsync().Result;
if (resp.StatusCode == HttpStatusCode.OK)
{
await turnContext.SendActivityAsync("Connected");
//Success 06122019 .
try
{
string spurl = #"https://intra.aspac.com/sites/sg/daw/_layouts/15/srchrss.aspx?k=*%20ListId:7BC0F2C3-6366-48B8-B88A-8738BE1F9C31";
XmlSecureResolver resolver = new XmlSecureResolver(new XmlUrlResolver(), spurl);
resolver.Credentials = new NetworkCredential("email#example.com.sg", "Pa$$w0rd", "sg.kworld.com");
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse;
settings.ValidationType = ValidationType.DTD;
settings.XmlResolver = resolver;
XmlReader reader = XmlReader.Create(spurl, settings);
SyndicationFeed feed = SyndicationFeed.Load(reader);
reader.Close();
var attachments = new List<Attachment>();
foreach (SyndicationItem item in feed.Items)
{
//Get Title,Description,URL
String title = item.Title.Text;
String description = item.Summary.Text;
String link = item.Links.FirstOrDefault().Uri.ToString();
//Hero Card
var heroCard = new HeroCard(
title: item.Title.Text,
// subtitle: description,
buttons: new CardAction[]
{
new CardAction(ActionTypes.OpenUrl,"Learn More",value:link)
}
).ToAttachment();
attachments.Add(heroCard);
}
var reply = MessageFactory.Carousel(attachments);
await turnContext.SendActivityAsync(reply);
await ProcessCosmoDBStorageLUISAsync(turnContext, questionluis, intent, entityfound, respString, cancellationToken);
}
catch (Exception ex)
{
await turnContext.SendActivityAsync(ex.ToString());
}
}
}
catch (Exception ex)
{
await turnContext.SendActivityAsync("Sorry,Currently Server Under Maintenace");
await turnContext.SendActivityAsync(ex.ToString());
}
}
any solution for this and suggestion?
ok, I think I finally understand this better, so hopefully can put a useful reply together. Would be much easier if we had a shared whiteboard :-)
Basically, in terms of hosting a bot on the Microsoft Bot Framework Services, you need to have a registration in Azure. However, there are two different options, and both are VERY different in terms of hosting. When you "create" the resource in Azure, and search for "Bot", you'll see two options - "Web App Bot" and "Bot Channels Registration":
"Bot Channels Registration" means JUST registering your bot in Azure, but HOSTING it elsewhere.
"Web App Bot" - INCLUDES the "Bot Channels Registration" but ALSO adds hosting using an Azure Web Application (so it's a Bot registration PLUS hosting)
From the screenshot you posted, I can see you've selected (2) above, and so your bot is running inside Azure, and therefore can't connect to your on premises resource (SharePoint).
As a result, I'd suggest one of two options:
Create an Azure Application Proxy - this is basically a small gateway so that your bot HOSTED in Azure can securely talk to your on-premises SharePoint. There is in fact a specific use case for SharePoint in particular.
Delete and re-create your Azure Bot entry to instead be just a "Bot Channels Registration", and then in the "Settings" screen you can call a bot hosted at any "https" endpoint. You can then have your bot run on the local network, but it will need a live "https" address (not -that- hard to do, but you have to involve your IT team to get a live web address, like "whatever.aspac.com", and you'll need an SSL/TLS certificate so that it can run httpS instead of just http.
Which option you choose might depend on the skills and resources on your team, as well as in the organisation. For instance, the company might have Azure Application Proxy configured already, in which case that saves a lot of work. It might have a wildcard certificate, which would make option (2) easier, etc.
Either way, I hope that helped, but feel free to ask more if anything is still unclear.
i had a similar problem using a on premise database. as you are deploying your bot externally, the bot needs resources that are available on the internet, and not contained internally. It will work fine using the bot emulator because it has access to what your machine has.
Saying that, azure has developed some actions which you can use to help this problem. If you look at application proxys, that may be able to help you out.
i think thats what you mean... anyway!

Test Azure hosted WebApi locally to send Push Notifications to all devices

I apologize if my question is silly, but I am new to WebApi. I have followed a tutorial and published a WebApi to Azure. I also have created a Xamarin Mobile App and all the framework in Azure to be able to send Push Notifications to both Android and iOS. I have a notification hub set up, app service, web service that hosts the web api etc. Testing with Azure using the Push tab to send notifications individually to both ios and android works perfectly.
I posted the code of the web api. How can I use the web api locally on my computer to send a notification to both platforms (ios and android) please?
[RoutePrefix("sanotifications")]
public class SANotifController : ApiController
{
[HttpPost]
[Route("")]
public async Task<IHttpActionResult> SendNotificationAsync ([FromBody] string message)
{
//Get the settings for the server project
HttpConfiguration config = this.Configuration;
try
{
await InternalSendNotificationAsync(message, null);
}
catch (Exception ex)
{
//write the failure result to the logs
config.Services.GetTraceWriter().Error(ex.Message, null, "Push.SendAsync Error");
return BadRequest(ex.Message);
}
return Ok();
}
[HttpPost]
[Route("{installationid}")]
public async Task<IHttpActionResult> SendNotificationAsync(string installationId, [FromBody] string message)
{
//get the settings for the server project
HttpConfiguration config = this.Configuration;
try
{
await SendNotificationAsync(message, installationId);
}
catch (Exception ex)
{
//write the failure to the logs
config.Services.GetTraceWriter().Error(ex.Message, null, "Push.SendAsync Error");
return BadRequest(ex.Message);
}
return Ok();
}
async Task<NotificationOutcome> InternalSendNotificationAsync (string message, string installationId)
{
//Get the settings for the server project
HttpConfiguration config = this.Configuration;
//use code below if web api is already published to Azure to get existing setup
//does not work locally
var settings = config.GetMobileAppSettingsProvider().GetMobileAppSettings();
/*
//Get the Notification Hubs credentials for the Mobile App
string notificationHubName = settings.NotificationHubName;
string notificationHubConnection = settings.Connections[MobileAppSettingsKeys.NotificationHubConnectionString].ConnectionString;
*/
//the name of the Notification Hub from the overview page.
// works locally
string notificationHubName = "sa1hub";
//use "DefaultFullSharedAccessSignature" from the portal's Access Policies
string notificationHubConnection = "Endpoint=sb://sahub.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=71S2#QEWF##$";
// create a new notification hub client
var hub = NotificationHubClient.CreateClientFromConnectionString(
notificationHubConnection,
notificationHubName,
// Don't use this in RELEASE builds. The number of devices is limited.
// If TRUE, the send method will return the devices a message was
// delivered to.
enableTestSend: true);
// use a template compatible with both devices
// send the message so that all template registrations that contain "messageParam"
// will receive the notification. This includes APNS, GCM, WNS and MPNS template registrations.
var templateParams = new Dictionary<string, string>
{
["messageParam"] = message
};
// send the push notification and log the results
NotificationOutcome result = null;
if (string.IsNullOrWhiteSpace(installationId))
{
result = await hub.SendTemplateNotificationAsync(templateParams).ConfigureAwait(false);
}
else
{
result = await hub.SendTemplateNotificationAsync(templateParams, "$InstallationId:{" + installationId + "}").ConfigureAwait(false);
}
// Write the success result to the logs.
config.Services.GetTraceWriter().Info(result.State.ToString());
return result;
}
}
}
In Xamarin there are two way to send push notification from server to client. Even on Microsoft forum it's very clear step mention to Implementation.
Use of Azure Hub notification we can send easily notification on Cross mobile Platform or Native
Azure Push Notification
Another App Center Push notification Implementation.
Xamarin App Center Push Notification
To send push notification for IOS devices you have to communicate with APNS and for Android we need GCM. Azure works like an intermediate between our app and these services. So if you would like to send notification without Azure I prefer
Firebase Cloud Messaging. it is google product and allows us to send cross platform push notifications for both IOS and Android.
We can host our WebAPI in our windows local IIS and which should be configured for Firebase.
Example app for xamarin : FirebasePushNotificationPlugin

iOS not receiving pending push after turn on device or Internet from Azure Notification Hub

I have a Notification Hub in Azure to send PUSH to Android and iOS devices. Everything is working well in Android. In iOS I have this problem:
I turn off the WiFi or I turn off the device
I send chat messages to my app (push notifications) and also messages to that device from WhatsApp.
I turn on the WiFi or turn on the device after a few minutes
I receive all the WhatsApp messages notifications but no one of the notification to my App. If the device and Internet is on, I receive the notifications without problem.
My question is: Anyone has experienced something like that or know how to fix it?
At least I should have to receive the last push, right?
I'm sending the push to a tag. I can see the Device registered in the hub either when WiFi or iPhone are off.
When sending notification ensure that you set the expiration. Default value is zero. Hence, APNs treats the notification as if it expires immediately and does not store the notification or attempt to redeliver it.
https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html
apns-expiration
If this value is nonzero, APNs stores the notification
and tries to deliver it at least once, repeating the attempt as needed
if it is unable to deliver the notification the first time. If the
value is 0, APNs treats the notification as if it expires immediately
and does not store the notification or attempt to redeliver it.
If you are using template notifications, here is how you do it.
AppleTemplateRegistrationDescription registration = new AppleTemplateRegistrationDescription(parameters.registrationID)
{ BodyTemplate = new CDataMember("{\"aps\":{\"alert\":\"$(body)\",\"payload\":\"$(payload)\",\"deeplinking\":\"$(deeplinking)\",\"category\":\"$(category)\",\"image\":\"$(image)\"}}"),
Tags = itags,
Expiry = "$(APNS_Expiry)"
};
As part of send, you can pass the expiry value.
var notification = new TemplateNotification(new Dictionary<string, string>()
{
{"APNS_Expiry", DateTime.UtcNow.AddMinutes(10).ToString("o") }, //Timestamp
{"body", NotificationText},
{"payload", NotificationText},
{"deeplinking", payload},
});
var Responsehub = hub.SendNotificationAsync(notification);
If you are using native notifications,
// Native notification
var notification = new AppleNotification(#"
{
""aps"": {
""alert"":""New notification!""
}
}");
notification.Expiry = DateTime.UtcNow.AddMinutes(2);
await notificationHubClient.SendNotificationAsync(notification);
If you are using template notifications, here is how you do it.
AppleTemplateRegistrationDescription registration = new AppleTemplateRegistrationDescription(parameters.registrationID)
{ BodyTemplate = new CDataMember("{\"aps\":{\"alert\":\"$(body)\",\"payload\":\"$(payload)\",\"deeplinking\":\"$(deeplinking)\",\"category\":\"$(category)\",\"image\":\"$(image)\"}}"),
Tags = itags,
Expiry = "$(APNS_Expiry)"
};
As part of send, you can pass the expiry value.
var notification = new TemplateNotification(new Dictionary<string, string>()
{
{"APNS_Expiry", DateTime.UtcNow.AddMinutes(10).ToString("o") }, //Timestamp
{"body", NotificationText},
{"payload", NotificationText},
{"deeplinking", payload},
});
var Responsehub = hub.SendNotificationAsync(notification);
If you are using native notifications,
// Native notification
var notification = new AppleNotification(#"
{
""aps"": {
""alert"":""New notification!""
}
}");
notification.Expiry = DateTime.UtcNow.AddMinutes(2);
await notificationHubClient.SendNotificationAsync(notification);

push notification in windows phone 8

Hello friends i am following this Push notification link and able to implement it . it is working but i tried to change the CurrentChannel name from MyPushChannel to Channeltest then it is not able to create new channel and throwing exception of invalidOperation type will you guys please explain me why it is happening here is the code..
private void AcquirePushChannel()
{
CurrentChannel = HttpNotificationChannel.Find("Channeltest");
if (CurrentChannel == null)
{
CurrentChannel = new HttpNotificationChannel("Channeltest");
CurrentChannel.Open(); // exception comming here
CurrentChannel.BindToShellTile();
}
}
In Windows Phone, you have a restriction per application of one push channel. If you want to change the name, uninstall the app from the device/emulator and make the deployment again. It should work.

Resources