How do I properly represent an Event object for Microsoft Graph? - asp.net

I'm currently trying to create events on a users Outlook Calendar using the Microsoft Graph API with ASP .NET MVC. Unfortunately the documentation for creating the events does not include samples. I've found and tried to modify the sample for sending emails ( here: https://github.com/microsoftgraph/aspnet-connect-rest-sample ). I was able to send an initial events totally blank to my calendar. When attempting to send the event object itself I am met with the status response BAD REQUEST. If anyone could help, it'd be greatly appreciated.

For a reference of how you might construct the Event object, you can take a look how the official Microsoft Graph SDK has constructed this object: see the latest source here on GitHub.
For an example of making this REST call without using the SDK, you can reference UserSnippets#CreateEventAsync() - an excerpt is pasted below. While the below example doesn't use native objects for serialization, it hopefully conveys the essence of how it might work.
HttpClient client = new HttpClient();
var token = await AuthenticationHelper.GetTokenHelperAsync();
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
// Endpoint for the current user's events
Uri eventsEndpoint = new Uri(serviceEndpoint + "me/events");
// Build contents of post body and convert to StringContent object.
// Using line breaks for readability.
// Specifying the round-trip format specifier ("o") to the DateTimeOffset.ToString() method
// so that the datetime string can be converted into an Edm.DateTimeOffset object:
// https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx#Roundtrip
string postBody = "{'Subject':'Weekly Sync'," + "'Location':{'DisplayName':'Water Cooler'}," + "'Attendees':[{'Type':'Required','EmailAddress': {'Address':'mara#fabrikam.com'} }]," + "'Start': {'DateTime': '" + new DateTime(2014, 12, 1, 9, 30, 0).ToString("o") + "', 'TimeZone':'UTC'}," + "'End': {'DateTime': '" + new DateTime(2014, 12, 1, 10, 0, 0).ToString("o") + "', 'TimeZone':'UTC'}," + "'Body':{'Content': 'Status updates, blocking issues, and next steps.', 'ContentType':'Text'}}";
var createBody = new StringContent(postBody, System.Text.Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync(eventsEndpoint, createBody);
if (response.IsSuccessStatusCode) {
string responseContent = await response.Content.ReadAsStringAsync();
jResult = JObject.Parse(responseContent);
createdEventId = (string) jResult["id"];
Debug.WriteLine("Created event: " + createdEventId);
} else {
// some appropriate error handling here
}
For an example of what the transmitted JSON might look like:
{
"subject": "Weekly Sync",
"location": {
"displayName": "Water Cooler"
},
"attendees": [
{
"type": "Required",
"emailAddress": {
"address": "mara#fabrikam.com"
}
}
],
"start": {
"dateTime": "2016-02-02T17:45:00.0000000",
"timeZone": "UTC"
},
"end": {
"dateTime": "2016-02-02T18:00:00.0000000",
"timeZone": "UTC"
},
"body": {
"content": "Status updates, blocking issues,and nextsteps.",
"contentType": "Text"
}
}
Additional help:
There's a helpful Graph Explorer Sandbox available for you to test requests in your browser

Related

Firebase Dynamic Link pass custom parameters to iOS and android

I have a custom function in python to build the dynamic link:
def generate_dynamic_link(link, title=None, image=None, description=None, short=True, timeout=10):
api_url = FIREBASE_DYNAMIC_LINK_API_URL
domain = DYNAMIC_LINK_DOMAIN
apn = APP_APN
isi = APP_ISI
ibi = APP_IBI
payload = {
"dynamicLinkInfo": {
"domainUriPrefix": domain,
"link": link,
"androidInfo": {
"androidPackageName": apn,
},
"iosInfo": {
"iosBundleId": ibi,
"iosAppStoreId": isi
},
"socialMetaTagInfo": {
"socialTitle": title,
"socialDescription": description,
"socialImageLink": image
}
},
"suffix": {
"option": "SHORT" if short else "UNGUESSABLE"
}
response = requests.post(api_url, json=payload, timeout=timeout)
data = response.json()
if not response.ok:
raise Exception(data)
return data['shortLink']
I want to pass two parameters to the android and ios app. How can I Do that?
Example:
?type=user&username=testuser
I wrote my first Medium article about this (it’s not a great tutorial) but it shows how to do this. You are correct with how you pass data using ?yourDataHere at the end of your link.
https://augustkimo.medium.com/simple-flutter-sharing-and-deeplinking-open-apps-from-a-url-be56613bdbe6
Then you can handle the deep links by calling the function below. Pretty much you can get the link used to open the app, then get the data from that URL/link string
//ADD THIS FUNCTION TO HANDLE DEEP LINKS
Future<Null> initUniLinks()async{
try{
Uri initialLink = await getInitialUri();
print(initialLink);
var dataFromLink = initialLink.toString().split(‘?’)[1];
print(dataFromLink);
} on PlatformException {
print('platfrom exception unilink');
}
}

Adding Conversion events to a cloud message using Firebase Admin SDK

I am able to send Push notifications using the code below but I am also required to associate "Conversion events" with the notification. This can be done through the console but I couldn't find how to do it with SDK.
var message = new Message()
{
Data = new Dictionary<string, string>()
{
{ "test1", "6165" },
{ "test2", "161" },
},
Notification =
{
Body = "",
Title = ""
},
Topic = topic,
};
// Send a message to the devices subscribed to the provided topic.
Task<string> response = FirebaseMessaging.DefaultInstance.SendAsync(message, true);
// Response is a message ID string.
response.Wait();
Console.WriteLine("Successfully sent message: " + response);

Actions on Google - Receiving 200, but no notification

I am using a webhook and c# to fulfill my logic within an Action.
I have subscribed to two intents, and have captured the "UpdateUserId".
Here is the notification payload
{
"customPushMessage": {
"target": {
"userId": "ABwppHFW6M9ASVqbKFBigM8N0mgssCJmPlwarmgzil_Nk_YsdZ1evzTAggEh0aEsctjOIYg2uHc8n7KfzNuHLuJoirXW",
"intent": "NotificationIntent",
"argument": {
"rawText": "Notification Argument Raw Text",
"textValue": "Notification Argument Text Value",
"name": "Notification Argument"
},
"locale": "en-US"
},
"userNotification": {
"title": "Notification Title",
"text": "Notification Text"
}
}
}
I am sending my notification using the following code blocks
private static async Task<string> GetAccessTokenFromJsonKeyAsync(string jsonKeyFilePath, params string[] scopes)
{
using (var stream = new FileStream(jsonKeyFilePath, FileMode.Open, FileAccess.Read))
{
return await GoogleCredential
.FromStream(stream) // Loads key file
.CreateScoped(scopes) // Gathers scopes requested
.UnderlyingCredential // Gets the credentials
.GetAccessTokenForRequestAsync(); // Gets the Access Token
}
}
public async Task<HttpResponseMessage> SendNotificationMessage(ProactiveMessage proactiveMessage)
{
try
{
var accessToken = await GetAccessTokenFromJsonKeyAsync("key.json", "https://www.googleapis.com/auth/actions.fulfillment.conversation");
var serialized = JsonConvert.SerializeObject(proactiveMessage);
var payload = "{\"customPushMessage\": " + serialized + "}";
// Wrap our JSON inside a StringContent which then can be used by the HttpClient class
var httpContent = new StringContent(payload, Encoding.UTF8, "application/json");
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var httpResponseMessage = await _httpClient.PostAsync($"{_hostUrl}", httpContent);
Console.WriteLine(httpResponseMessage.IsSuccessStatusCode ? "Successfully sent notification message." : $"Failed to send notification message with {httpResponseMessage.StatusCode}.");
return httpResponseMessage;
}
catch (Exception ex)
{
Debug.WriteLine($"Google Assistant Service: Failed to send notification message with exception: {ex.Message}");
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
}
The method returns a 200 Response. However, a notification never shows up on my phone.
I am not sure what my next steps for debugging are.
Since notifications are stil not public, is this a common issue?
I had the same issue. I received 200 status code but no notifications arrived at the target device.
I tried it again in approximately 2 days and it worked with no problems and have been working ever since.
The only explanation I could come up with is that there is some configuration running in the background.

How to read Media from Attachment using REST API

I have created an Attachment with image:
{
"_rid": "xD4vALTE7QBAAwAAAAAAAA==",
"Attachments": [
{
"contentType": "image/jpeg",
"id": "10b91d7d-2e5e-466e-a896-3ee54baff4dc",
"media": "/media/xD4vALTE7QBAAwAAAAAAALobDgYB",
"_rid": "xD4vALTE7QBAAwAAAAAAALobDgY=",
"_self": "dbs/xD4vAA==/colls/xD4vALTE7QA=/docs/xD4vALTE7QBAAwAAAAAAAA==/attachments/xD4vALTE7QBAAwAAAAAAALobDgY=",
"_etag": "\"00000d37-0000-0000-0000-5a09602a0000\"",
"_ts": 1510563882
}
],
"_count": 1
}
What is the url to the Media object?
When I use the Cosmos .NET SDK method DocumentClient.ReadMediaAsync(string mediaLink) where mediaLink is /media/xD4vALTE7QBAAwAAAAAAALobDgY= then I can get the Media stream and display the image. But this only works when connecting to Cosmos Db Emulator, when doing the same on the Azure Cosmos DB instance, then I get this error:
Unknown server error occurred when processing this request. ActivityId: 53508de6-2456-4213-947e-4361a8118574, Microsoft.Azure.Documents.Common/1.17.99.1, documentdb-dotnet-sdk/1.19.0 Host/32-bit MicrosoftWindowsNT/6.2.9200.0
The Attachment creation with Medial upload works.
I was thinking to try to query the CosmosDB using the Postman, but I cannot figure out the url to get the Media object.
The url to the Media object is: https://[YOUR-DOCDB-HOST]/media/xD4vALTE7QBAAwAAAAAAALobDgYB
I call this as a GET request in Postman with the following Pre-Request Script:
// store our master key for documentdb
var mastKey = [YOUR-DOCUMENTDB-KEY-HERE];
console.log("mastKey = " + mastKey);
// store our date as RFC1123 format for the request
var today = new Date();
var UTCstring = today.toUTCString();
postman.setEnvironmentVariable("RFC1123time", UTCstring);
// define resourceId/Type now so we can assign based on the amount of levels
var resourceId = "[YOUR-RID-HERE]"; // _rid in attachment document
var resType = "media";
// assign our verb
var verb = request.method.toLowerCase();
// assign our RFC 1123 date
var date = UTCstring.toLowerCase();
// parse our master key out as base64 encoding
var key = CryptoJS.enc.Base64.parse(mastKey);
console.log("key = " + key);
// build up the request text for the signature so can sign it along with the key
var text = (verb || "").toLowerCase() + "\n" +
(resType || "").toLowerCase() + "\n" +
(resourceId || "").toLowerCase() + "\n" +
(date || "").toLowerCase() + "\n" +
"" + "\n";
console.log("text = " + text);
// create the signature from build up request text
var signature = CryptoJS.HmacSHA256(text, key);
console.log("sig = " + signature);
// back to base 64 bits
var base64Bits = CryptoJS.enc.Base64.stringify(signature);
console.log("base64bits = " + base64Bits);
// format our authentication token and URI encode it.
var MasterToken = "master";
var TokenVersion = "1.0";
auth = encodeURIComponent("type=" + MasterToken + "&ver=" + TokenVersion + "&sig=" + base64Bits);
console.log("auth = " + auth);
// set our auth token enviornmental variable.
postman.setEnvironmentVariable("authToken", auth);
There are two variables: [YOUR-DOCUMENTDB-KEY-HERE] and [YOUR-RID-HERE]. The kicker is, you need to query attachment meta data first to get the _rid value to use in the token when requesting the media.
The authToken and RFC1123time postman variables are used in the Authorization header:

Calendar API v3 reminder in event is always default

I am developing calendar api client and I have problem with reminder - they do not work...
I create event like this:
Event gEvent = new Event()
{
Summary = "Reminder test",
Location = "Reminder test",
Start = new EventDateTime()
{
DateTime = new DateTime(2014, 12, 14, 21, 0, 0),
},
End = new EventDateTime()
{
DateTime = new DateTime(2014, 12, 14, 22, 0, 0),
},
Reminders = new Event.RemindersData()
{
UseDefault = false,
Overrides = new List<EventReminder>()
{
new EventReminder()
{
Method = "email",
Minutes = 15
},
new EventReminder()
{
Method = "email",
Minutes = 30
},
new EventReminder()
{
Method = "email",
Minutes = 45
},
}
}
};
Event simpleEvent = calService.Events.Insert(gEvent, strCalendarID).Execute();
This code works and in my google calendar GUI is really created my event, but if I click on editing event - I can not see my reminders, there are only default reminders.
Why? What I am doing wrong?
Thanks for all answers
Today I attempted send request from code with JSON. My method look like this:
private static void CreateSimpleEvent(string strAccessToken, string strCalendarID, string strApiKey)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(string.Format("https://www.googleapis.com/calendar/v3/calendars/{0}/events?sendNotifications=false&fields=reminders&key={1}", strCalendarID, strApiKey));
request.Method = "POST";
request.ContentType = "application/json";
request.UserAgent = "TestCalendarApi2";
request.Headers.Add("Authorization", "Bearer " + strAccessToken);
string strJson = #"{
'end': {
'dateTime': '2014-12-19T15:30:00.000Z',
'timeZone': 'Europe/Prague'
},
'start': {
'dateTime': '2014-12-19T14:30:00.000Z',
'timeZone': 'Europe/Prague'
},
'reminders': {
'useDefault': false,
'overrides': [
{
'method': 'email',
'minutes': 13
}
]
}
}";
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(strJson);
streamWriter.Flush();
streamWriter.Close();
var httpResponse = (HttpWebResponse)request.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
}
}
Method proceeded OK and in google calendar was created event, but reminders are still missing when I use AccessToken from ServiceAccountCredential object :(. When I use AccessToken generated in Apis explorer (https://developers.google.com/apis-explorer/#p/calendar/v3/) - reminders are working.
Problem is, that in Apis explorer I must turn on OAuth2 and after that I must grand acess...
Is there any way, how to grand access from code?
Thanks for all answers.
The problem with reminders while using a service account to manage events in Google Calendar is that the service account is practically a virtual user with its own Google Calendar. The event reminders are set per user, so you would be only able to see the reminders if you'd manage to log in to Google Calendar as your service account. The users who share the calendar with the service account only see the event details but they have to set their own reminders.
Same issue here, event inserted without any reminders.
Sending same request via API explorer successfully inserted event with reminders.
My JSON data:
{
"end":{
"dateTime":"2015-01-19T01:20:00.000",
"timeZone":"Europe\/Minsk"
},
"reminders":{
"useDefault":false,
"overrides":[
{
"method":"sms",
"minutes":"30"
},
{
"method":"email",
"minutes":"60"
}
]
},
"start":{
"dateTime":"2015-01-19T01:15:00.000",
"timeZone":"Europe\/Minsk"
},
"summary":"New event",
"start_date":"2015-01-19 01:15",
"end_date":"2015-01-19 01:20"
}

Resources