I am a newbie of Microsoft bot.
My company have their own communication application, and i wanna connect my bot with communication application, my client can use my bot on my campany's communication application. I read about it need to use Direct Line to do it. But i really don't know how to do it.
Does anybody help me ?or give me some suggestions? or any example of that.
Thank you so much.
Please refer documentation about direct line approach for Bot framework.
What you have to do is use https://directline.botframework.com/api/conversations as your endpoint and call those API as shown in the documentation.
Example :- I just tried with ASP.MVC application. I created a text box and button for submit message to bot.
First enable direct link in your bot application. Then remember that secret.
Following code sample shows you how to connect your chat app or your company app with bot you built using bot frame work.
First you need to authorize your access to direct link API.
client = new HttpClient();
client.BaseAddress = new Uri("https://directline.botframework.com/api/conversations/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("BotConnector", "[Your Secret Key Here]");
response = await client.GetAsync("/api/tokens/");
if (response.IsSuccessStatusCode)
If you are success with previous response you can start a new Conversation
Model -
public class Conversation
{
public string conversationId { get; set; }
public string token { get; set; }
public string eTag { get; set; }
}
Code inside controller -
var conversation = new Conversation();
response = await client.PostAsJsonAsync("/api/conversations/",conversation);
if (response.IsSuccessStatusCode)
If you success with this response you will get conversationId and a token to start messaging.
Then pass your message to bot via following code,
Conversation ConversationInfo = response.Content.ReadAsAsync(typeof(Conversation)).Result as Conversation;
string conversationUrl = ConversationInfo.conversationId+"/messages/";
Message msg = new Message() { text = message };
response = await client.PostAsJsonAsync(conversationUrl,msg);
if (response.IsSuccessStatusCode)
If you get a success response, that means you have already sent your message to the bot. Now you need to get the reply message from BOT
To get the message from bot,
response = await client.GetAsync(conversationUrl);
if (response.IsSuccessStatusCode){
MessageSet BotMessage = response.Content.ReadAsAsync(typeof(MessageSet)).Result as MessageSet;
ViewBag.Messages = BotMessage;
IsReplyReceived = true;
}
Here you get a Message set, That means the message you sent and the reply from the Bot. You can now display it in your chat window.
Message Model -
public class MessageSet
{
public Message[] messages { get; set; }
public string watermark { get; set; }
public string eTag { get; set; }
}
public class Message
{
public string id { get; set; }
public string conversationId { get; set; }
public DateTime created { get; set; }
public string from { get; set; }
public string text { get; set; }
public string channelData { get; set; }
public string[] images { get; set; }
public Attachment[] attachments { get; set; }
public string eTag { get; set; }
}
public class Attachment
{
public string url { get; set; }
public string contentType { get; set; }
}
Using those API calls you can easily connect any of your custom chat applications with bot framework. Below is the full code inside one method for you to get idea about how you can archive your goal.
private async Task<bool> PostMessage(string message)
{
bool IsReplyReceived = false;
client = new HttpClient();
client.BaseAddress = new Uri("https://directline.botframework.com/api/conversations/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("BotConnector", "[Your Secret Code Here]");
response = await client.GetAsync("/api/tokens/");
if (response.IsSuccessStatusCode)
{
var conversation = new Conversation();
response = await client.PostAsJsonAsync("/api/conversations/", conversation);
if (response.IsSuccessStatusCode)
{
Conversation ConversationInfo = response.Content.ReadAsAsync(typeof(Conversation)).Result as Conversation;
string conversationUrl = ConversationInfo.conversationId+"/messages/";
Message msg = new Message() { text = message };
response = await client.PostAsJsonAsync(conversationUrl,msg);
if (response.IsSuccessStatusCode)
{
response = await client.GetAsync(conversationUrl);
if (response.IsSuccessStatusCode)
{
MessageSet BotMessage = response.Content.ReadAsAsync(typeof(MessageSet)).Result as MessageSet;
ViewBag.Messages = BotMessage;
IsReplyReceived = true;
}
}
}
}
return IsReplyReceived;
}
Thanks Cheers with you bot.
Related
We have a SharePoint list that contains a large PDF attachment and have set up an Azure Webhook to notify an Azure Function App of a change to the SharePoint list and would like to have the ability to check for and parse a PDF attachment.
I am fairly still new to this type of development, but have found an example that I followed, and our test currently seems to be triggering an event in our Azure Function and can see that the trigger is successful:
Monitor Invocation:
The code that I've implemented is pretty much verbatim from the above link example and it appears that most of the functionality is currently simply writing out log information, however I've not been able to find many examples of detailed implementation scenarios using SharePoint Lists to get an attachment from a SharePoint List.
Should we be getting our attachment data after reading in the request into a StreamReader object here?
var content = await new StreamReader(req.Body).ReadToEndAsync();
Full Code Context:
#r "Newtonsoft.Json"
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
public static async Task<IActionResult> Run(HttpRequest req,
ICollector<string> outputQueueItem, ILogger log)
{
log.LogInformation($"Webhook was triggered!");
// Grab the validationToken URL parameter
string validationToken = req.Query["validationtoken"];
// If a validation token is present, we need to respond within 5 seconds by
// returning the given validation token. This only happens when a new
// webhook is being added
if (validationToken != null)
{
log.LogInformation($"Validation token {validationToken} received");
return (ActionResult)new OkObjectResult(validationToken);
}
log.LogInformation($"SharePoint triggered our webhook...great :-)");
//Is the attachment available via the content variable?
var content = await new StreamReader(req.Body).ReadToEndAsync();
log.LogInformation($"Received following payload: {content}");
var notifications = JsonConvert.DeserializeObject<ResponseModel<NotificationModel>>(content).Value;
log.LogInformation($"Found {notifications.Count} notifications");
if (notifications.Count > 0)
{
log.LogInformation($"Processing notifications...");
foreach(var notification in notifications)
{
// add message to the queue
string message = JsonConvert.SerializeObject(notification);
log.LogInformation($"Before adding a message to the queue. Message content: {message}");
outputQueueItem.Add(message);
log.LogInformation($"Message added :-)");
}
}
// if we get here we assume the request was well received
return (ActionResult)new OkObjectResult($"Added to queue");
}
// supporting classes
public class ResponseModel<T>
{
[JsonProperty(PropertyName = "value")]
public List<T> Value { get; set; }
}
public class NotificationModel
{
[JsonProperty(PropertyName = "subscriptionId")]
public string SubscriptionId { get; set; }
[JsonProperty(PropertyName = "clientState")]
public string ClientState { get; set; }
[JsonProperty(PropertyName = "expirationDateTime")]
public DateTime ExpirationDateTime { get; set; }
[JsonProperty(PropertyName = "resource")]
public string Resource { get; set; }
[JsonProperty(PropertyName = "tenantId")]
public string TenantId { get; set; }
[JsonProperty(PropertyName = "siteUrl")]
public string SiteUrl { get; set; }
[JsonProperty(PropertyName = "webId")]
public string WebId { get; set; }
}
public class SubscriptionModel
{
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string Id { get; set; }
[JsonProperty(PropertyName = "clientState", NullValueHandling = NullValueHandling.Ignore)]
public string ClientState { get; set; }
[JsonProperty(PropertyName = "expirationDateTime")]
public DateTime ExpirationDateTime { get; set; }
[JsonProperty(PropertyName = "notificationUrl")]
public string NotificationUrl {get;set;}
[JsonProperty(PropertyName = "resource", NullValueHandling = NullValueHandling.Ignore)]
public string Resource { get; set; }
}
I thought that I would try to debug this integration remotely since the code is running in the Azure Portal in order to set up watches and look into the HTTPRequest and StreamReader objects, however that's presented a whole new set of challenges and we've been unsuccessful there as well.
Thanks in advance.
What you've done here is fine, assuming you end up with an item placed on a queue. The real heavy lifting though will happen with the function that picks up the item off the queue. The json you send to the queue only notes that a change occurred; your queue receiver is going to have to authenticate and call back into SharePoint to fetch the data and do what it needs to do.
Read the reference implementation section of the documentation you linked for a better explanation of the webhooks architecture.
I will add that developing Azure functions directly in the portal is going to be a nightmare for anything but trivial applications. And your application is not trivial. The ngrok based approach in the Get Started section is good advice and really the only way to debug webhooks. Good luck!
I found the following document: CosmosDB grant permission to multiple resources?
The answer there states that after the resource token broker gets the Permissions feed of the user and sends it back to client:
FeedResponse<Permission> permFeed = await client.ReadPermissionFeedAsync(UriFactory.CreateUserUri("dbid", " userId"));
List<Permission> permList = permFeed.ToList();
The client app can then initialize an instance of the DocumentClient class and pass the list (provided that it will deserialize the Json to List<Permission>).
var jsonString = await response.Content.ReadAsStringAsync();
var permissions = JsonConvert.DeserializeObject<List<Permission>>(jsonString);
var client = new DocumentClient(new Uri(EndpointUri), permisions);
The problem that I have is that the Permission class has a Token property that has only a getter and no setter exists. The following source code is from Microsoft.Azure.Documents namespace.
namespace Microsoft.Azure.Documents
{
public class Permission : Resource
{
[JsonProperty(PropertyName = "resource")]
public string ResourceLink { get; set; }
[JsonProperty(PropertyName = "resourcePartitionKey")]
public PartitionKey ResourcePartitionKey { get; set; }
[JsonConverter(typeof (StringEnumConverter))]
[JsonProperty(PropertyName = "permissionMode")]
public PermissionMode PermissionMode { get; set; }
[JsonProperty(PropertyName = "_token")]
public string Token { get; } <------------------------------------- HERE
}
}
As such, trying to serialize the Token field, the value copied is null.
Anyone has any solution for that?
I have developed an app with Xamarin Forms and implemented push notification using Azure Notification Hub.
I followed this tutorial from Microsoft site :
https://learn.microsoft.com/en-us/azure/notification-hubs/notification-hubs-backend-service-xamarin-forms
I receive the notification when send it to all ,The problem is when I use the 'Tag' in order to send it to specific user(I register this user with certain tag when he log in the application.)
This is not working and I don't even have an idea how to check where is the problem.
I tried to check out weather the tag is not assigned correctly or not assigned at all but it's not possible to check it.
What should I do?
How can I see all the tags I have in system and who is registered to the tag?
Maybe I didn't understood it correctly but I don't create the Tag before the user register ,I just add it to the Tags List when the user is registered to the system.
public class DeviceInstallation
{
[Required]
public string InstallationId { get; set; }
[Required]
public string Platform { get; set; }
[Required]
public string PushChannel { get; set; }
public IList<string> Tags { get; set; } = Array.Empty<string>(); //Generate tag when register device and add it to list
}
public async Task RegisterDeviceAsync(params string[] tags)
{
var deviceInstallation = DeviceInstallationService?.GetDeviceInstallation(tags);
if (deviceInstallation == null)
throw new Exception($"Unable to get device installation information.");
if (string.IsNullOrWhiteSpace(deviceInstallation.InstallationId))
throw new Exception($"No {nameof(deviceInstallation.InstallationId)} value for {nameof(DeviceInstallation)}");
if (string.IsNullOrWhiteSpace(deviceInstallation.Platform))
throw new Exception($"No {nameof(deviceInstallation.Platform)} value for {nameof(DeviceInstallation)}");
if (string.IsNullOrWhiteSpace(deviceInstallation.PushChannel))
throw new Exception($"No {nameof(deviceInstallation.PushChannel)} value for {nameof(DeviceInstallation)}");
await SendAsync<DeviceInstallation>(HttpMethod.Put, RequestUrl, deviceInstallation)
.ConfigureAwait(false);
var serializedTags = JsonConvert.SerializeObject(tags);
await SecureStorage.SetAsync(CachedTagsKey, serializedTags);
}
The following code is in the server:
public async Task<bool> CreateOrUpdateInstallationAsync(DeviceInstallation deviceInstallation, CancellationToken token)
{
if (string.IsNullOrWhiteSpace(deviceInstallation?.InstallationId) ||
string.IsNullOrWhiteSpace(deviceInstallation?.Platform) ||
string.IsNullOrWhiteSpace(deviceInstallation?.PushChannel))
return false;
var installation = new Installation()
{
InstallationId = deviceInstallation.InstallationId,
PushChannel = deviceInstallation.PushChannel,
Tags = deviceInstallation.Tags
};
if (_installationPlatform.TryGetValue(deviceInstallation.Platform, out var platform))
installation.Platform = platform;
else
return false;
try
{
await _hub.CreateOrUpdateInstallationAsync(installation, token);
}
catch
{
return false;
}
return true;
}
I used this HTTP-Get request to get a Bearer token for the translation:
https://api.cognitive.microsoft.com/sts/v1.0/issueToken?Subscription-Key=1fo8xxx
Using the returned Bearer I wanted to translate a short text using this API endpoint:
https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&to=de
In the header I put this:
Content-Type: application/json; charset=UTF-8.
And in the body I put this:
[
{"Text":"I would really like to drive your car around the block a few times."}
]
I am using Postman, so in the authorization tab I selected Bearer and inserted in the field next to it this:
Bearer <result from the first API call>
If I send the reqeuest I get this result:
{"error":{"code":401000,"message":"The request is not authorized because credentials are missing or invalid."}}
In case someone ever stumbles upon this, after hours of trial and error I found out you need to pass the Ocp-Apim-Subscription-Region param in the header.
Here is an example in python that I was able to run successfully.
import json
import requests
def translate(text, source_language, dest_language):
if not <Secret Key>:
return 'Error: the translation service is not configured.'
headers = {'Ocp-Apim-Subscription-Key': <Secret Key>,
'Ocp-Apim-Subscription-Region': <region>,
'Content-type': 'application/json'}
url = 'https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&from={}&to={}' \
.format(source_language, dest_language)
body = [{'text': text}]
request = requests.post(url, headers=headers, json=body)
if request.status_code != 200:
return 'Error: the translation service failed.'
return json.loads(request.content.decode('utf-8-sig'))
The list of regions and other examples can be found here:
https://learn.microsoft.com/en-us/azure/cognitive-services/translator/reference/v3-0-reference
Don't be fooled by the curl example that is not using the region..
Your request needs the "OCP-Apim-Subscription-Key" header. Take a look on the official example:
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
// Install Newtonsoft.Json with NuGet
using Newtonsoft.Json;
/// <summary>
/// The C# classes that represents the JSON returned by the Translator Text API.
/// </summary>
public class TranslationResult
{
public DetectedLanguage DetectedLanguage { get; set; }
public TextResult SourceText { get; set; }
public Translation[] Translations { get; set; }
}
public class DetectedLanguage
{
public string Language { get; set; }
public float Score { get; set; }
}
public class TextResult
{
public string Text { get; set; }
public string Script { get; set; }
}
public class Translation
{
public string Text { get; set; }
public TextResult Transliteration { get; set; }
public string To { get; set; }
public Alignment Alignment { get; set; }
public SentenceLength SentLen { get; set; }
}
public class Alignment
{
public string Proj { get; set; }
}
public class SentenceLength
{
public int[] SrcSentLen { get; set; }
public int[] TransSentLen { get; set; }
}
private const string key_var = "TRANSLATOR_TEXT_SUBSCRIPTION_KEY";
private static readonly string subscriptionKey = Environment.GetEnvironmentVariable(key_var);
private const string endpoint_var = "TRANSLATOR_TEXT_ENDPOINT";
private static readonly string endpoint = Environment.GetEnvironmentVariable(endpoint_var);
static Program()
{
if (null == subscriptionKey)
{
throw new Exception("Please set/export the environment variable: " + key_var);
}
if (null == endpoint)
{
throw new Exception("Please set/export the environment variable: " + endpoint_var);
}
using (var client = new HttpClient())
using (var request = new HttpRequestMessage())
{
// Build the request.
// Set the method to Post.
request.Method = HttpMethod.Post;
// Construct the URI and add headers.
request.RequestUri = new Uri(endpoint + route);
request.Content = new StringContent(requestBody, Encoding.UTF8, "application/json");
request.Headers.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
// Send the request and get response.
HttpResponseMessage response = await client.SendAsync(request).ConfigureAwait(false);
// Read response as a string.
string result = await response.Content.ReadAsStringAsync();
// Deserialize the response using the classes created earlier.
TranslationResult[] deserializedOutput = JsonConvert.DeserializeObject<TranslationResult[]>(result);
// Iterate over the deserialized results.
foreach (TranslationResult o in deserializedOutput)
{
// Print the detected input language and confidence score.
Console.WriteLine("Detected input language: {0}\nConfidence score: {1}\n", o.DetectedLanguage.Language, o.DetectedLanguage.Score);
// Iterate over the results and print each translation.
foreach (Translation t in o.Translations)
{
Console.WriteLine("Translated to {0}: {1}", t.To, t.Text);
}
}
}
Console.Read();
}
https://learn.microsoft.com/en-us/azure/cognitive-services/translator/quickstart-translate?pivots=programming-language-csharp
Microsoft provides a service to analyze text data called Text Analytics Cognitive Service.
Is it possible to use this service with local database? i.e. not in Azure
I work with some large databases and as for me it can be interesting to use it for:
Language detection
Key phrase extraction
Named Entity recognition
Sentiment analysis
Once you pull your data that you would like to detect its language
from your local database, you just need to fetch it then just pass in
below method. It would analysis your value in response.
API Access Keys:
private static readonly string endpointKey = "YourEndPonitKey";
private static readonly string endpoint = "https://YourServiceURL.cognitiveservices.azure.com/text/analytics/v2.1/languages";
Code Snippet:
public async Task<object> DetectLanguageAsync(string InputFromDbOrUser)
{
try
{
DetectedLanguageResponseModel ObjDitectedLanguageResponse = new DetectedLanguageResponseModel();
//Create laguage detection request param
RequestModel objRequestModel = new RequestModel();
objRequestModel.id = "1";
objRequestModel.text = InputFromDbOrUser;
//Made Document List
List<RequestModel> Objdocuments = new List<RequestModel>();
Objdocuments.Add(objRequestModel);
//Bind Request Model
LanguageDetection objRequestList = new LanguageDetection();
objRequestList.documents = Objdocuments;
// Bind and Serialize Request Object
var serializedObject = JsonConvert.SerializeObject(objRequestList);
// Call Language Detection API
using (var client = new HttpClient())
using (var request = new HttpRequestMessage())
{
request.Method = HttpMethod.Post;
request.RequestUri = new Uri(endpoint);
request.Content = new StringContent(serializedObject, Encoding.UTF8, "application/json");
request.Headers.Add("Ocp-Apim-Subscription-Key", endpointKey);
var response = await client.SendAsync(request);
//Check status code and retrive response
if (response.IsSuccessStatusCode)
{
ResponseModel objResponse = JsonConvert.DeserializeObject<ResponseModel>(await response.Content.ReadAsStringAsync());
//Check Response List
foreach (var item in objResponse.documents)
{
//Checkings Empty Response and Return to Caller
if (objResponse.documents != null)
{
ObjDitectedLanguageResponse.Language = objResponse.documents[0].detectedLanguages[0].name;
return ObjDitectedLanguageResponse;
}
else
{
return "Sorry, I am not able to find a related topic! Would you like me to Bing Search?";
}
}
}
else
{
var result_string = await response.Content.ReadAsStringAsync();
return result_string;
}
}
return ObjDitectedLanguageResponse;
}
catch (Exception ex)
{
throw new NotImplementedException(ex.Message, ex.InnerException);
}
}
Class Used:
public class DetectedLanguage
{
public string name { get; set; }
public string iso6391Name { get; set; }
}
public class DetectedLanguageResponseModel
{
public dynamic Language { get; set; }
}
public class LanguageDetection
{
public List<RequestModel> documents { get; set; }
}
public class RequestModel
{
public string id { get; set; }
public string text { get; set; }
}
public class ResponseDocument
{
public string id { get; set; }
public List<DetectedLanguage> detectedLanguages { get; set; }
}
public class ResponseModel
{
public List<ResponseDocument> documents { get; set; }
public List<object> errors { get; set; }
}
Note: The current limit is 5,120 characters for each document; if you need to analyze larger documents, you can break them up into
smaller chunks for more you could refer official document
Hope that would help. If you need more implementation assistance please have a look on here