I am trying to call this code
string accessToken = #".."; //valid token with right scopes
public string EventsUrl = #"https://outlook.office.com/api/v2.0/me/events";
// generate body
var postBody = JsonBody(invite);
using (var client = new HttpClient())
{
using (var request = new HttpRequestMessage(HttpMethod.Post, EventsUrl))
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var content = new StringContent(postBody, Encoding.UTF8, "application/json");
request.Content = content;
var response = await client.SendAsync(request);
return (response.IsSuccessStatusCode);
}
}
The method that create JsonBody is,
public string JsonBody(User user, Session session){
var invite = new EventInvite
{
Attendees = new Attendee[1]
};
invite.Attendees[0] = new Attendee
{
Type = "Required",
EmailAddress = new Emailaddress { Name = user.GetName(), Address = user.GetEmail() }
};
invite.Start = new Start { DateTime = session.DateTime_Start };
invite.End = new End { DateTime = session.DateTime_Start.AddMinutes(15) };
invite.Subject = session.Name;
invite.Body = new Body { ContentType = "HTML", Content = $"Some Content" };
return JsonConvert.SerializeObject(eventInvite);
}
I am getting a Bad Request as response. Is there any alternative to build an Event? I want this code to be very thin as this is accessed in non UI based application
What is the best way to create Calendar Event?
The fix involves setting up the Timezone in the Start and End
string timeZone="Singapore Standard Time";
invite.Start = new Start { DateTime = session.DateTime_Start, TimeZone = timeZone };
invite.End = new End { DateTime = session.DateTime_Start.AddMinutes(60), TimeZone = timeZone };
var postBody = JsonConvert.SerializeObject(invite, Formatting.Indented);
Related
I am inserting calendar events into our domain users O365 calendars with Microsoft Graph API. I need to determine if the event exists, but my research has only shown how to use the GraphClient.Me.Events scenario to search. I don't believe this would work as we have global access to all calendars (Calendars.ReadWrite) within our domain.
Is there any way to search for the event in the applicable domain users calendar before sync?
var scopes = new string[] { "https://graph.microsoft.com/.default" };
var confidentialClient = ConfidentialClientApplicationBuilder.Create(clientId).WithTenantId(tenantId).WithClientSecret(clientSecret).Build();
var authResult = await confidentialClient.AcquireTokenForClient(scopes).ExecuteAsync();
using (HttpClient c = new HttpClient())
{
string url = "https://graph.microsoft.com/v1.0/users/" + userEmail + " /calendar/events";
ToOutlookCalendar createOutlookEvent = CreateEvent();
HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(createOutlookEvent), Encoding.UTF8, "application/json");
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url);
request.Content = httpContent;
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
var response = await c.SendAsync(request);
var responseString = await response.Content.ReadAsStringAsync();
}
The calendar event is currently very simple for testing
public static ToOutlookCalendar CreateEvent()
{
ToOutlookCalendar outlookEvent = new ToOutlookCalendar
{
Subject = "Code test migration appt",
Body = new Body
{
ContentType = "HTML",
Content = "Testing API with application client authorization"
},
Start = new End
{
DateTime = "2020-06-22T12:30:00",TimeZone = System.TimeZone.CurrentTimeZone.StandardName
},
End = new End
{
DateTime = "2020-06-22T14:00:00",TimeZone = System.TimeZone.CurrentTimeZone.StandardName
},
Location = new LocationName
{
DisplayName = "Sample Location"
}
};
return outlookEvent;
}
Assuming you're targeting the default calendar for the user, yes.
the /me path segment is an alias to the upn or userId, so something like:
"https://graph.microsoft.com/v1.0/users/" + userEmail + "/calendar/events?$filter=subject eq '" + knownTitle + "'"
Should work just fine if you're using an app only token with sufficent permissions
I am using rest end point and don't get folder id on creation. It should be in response but not there.
Folder is getting created successfully.
url: https://www.googleapis.com/drive/v3/files
public static async void CreateFolder(string accessToken, string brandFolderName)
{
var gDriveItems = await GetFoldersByBrand(accessToken,brandFolderName);
if (gDriveItems.Any(x=>x.Name.ToLower() == brandFolderName.ToLower()))
{
return;
}
var request = new HttpRequestMessage(HttpMethod.Post, "drive/v3/files");
request.Headers.Add("Authorization", "Bearer "+ accessToken);
request.Headers.Add("Accept","application/json");
JsonObject jsonFolderObject = new JsonObject();
jsonFolderObject.Add("name", brandFolderName);
jsonFolderObject.Add("mimeType", "application/vnd.google-apps.folder");
var data = JsonConvert.SerializeObject(jsonFolderObject);
request.Content = new StringContent(data, Encoding.UTF8, "application/json");
var responce = await _httpClient.SendAsync(request);
var mm = responce.Content.ReadAsStringAsync();
responce.EnsureSuccessStatusCode();
}
For reference, here's my code to add a new folder.
I use Google.Apis.Drive.v3
service is an instance of DriveService with the relevant scope to create a folder/file.
This will give me the Id of the new folder in the result
private static async Task<File> CreateRankingsFolder(DriveService service,
string driveId,
string parentId,
string folderName = "YOURFOLDERNAME")
{
File result = null;
try
{
File body = new File();
body.Name = folderName;
body.MimeType = "application/vnd.google-apps.folder";
body.DriveId = driveId;
if (!string.IsNullOrEmpty(parentId))
{
var _parents = new List<string>()
{
parentId
};
body.Parents = _parents;
}
// service is an authorized Drive API service instance
var req = service.Files.Create(body);
result = await req.ExecuteAsync();
}
catch(Exception e)
{
}
return result;
}
I am attempting to upgrade to newest APNS connectivity functionality but when I submit a request I get a http 400 bad request result with no reason. What am I missing / doing wrong?
Method for sending below:
public async void SendAsync(string deviceToken, string p8privateKey, string p8privateKeyId, string teamId)
{
var path = $"/3/device/{deviceToken}";
var obj = new
{
aps = new
{
alert = "test00001"
}
};
var json = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
var request = new HttpRequestMessage(HttpMethod.Post, new Uri("https://api.development.push.apple.com:443" + path))
{
Version = new Version(2, 0)
};
string jwToken = CreateJwtToken(p8privateKey, p8privateKeyId, teamId);
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", jwToken);
request.Headers.TryAddWithoutValidation(":method", "POST");
request.Headers.TryAddWithoutValidation(":path", path);
request.Headers.Add("apns-topic", "com.the-app");
request.Content = new StringContent(json);
string sReq = JsonConvert.SerializeObject(request);
string jsonContent = request.Content.ReadAsStringAsync().Result;
WinHttpHandler handler = new WinHttpHandler();
HttpClient http = new HttpClient(handler);
var t = await http.SendAsync(request);
}
Here are the other used methods:
private static string CreateJwtToken(string p8privateKeyId, string p8privateKey, string teamId)
{
var header = JsonHelper.Serialize(new { alg = "ES256", kid = p8privateKeyId });
var payload = JsonHelper.Serialize(new { iss = teamId, iat = ToEpoch(DateTime.UtcNow) });
var key = CngKey.Import(Convert.FromBase64String(p8privateKey), CngKeyBlobFormat.Pkcs8PrivateBlob);
using (var dsa = new ECDsaCng(key))
{
dsa.HashAlgorithm = CngAlgorithm.Sha256;
var headerBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(header));
var payloadBasae64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(payload));
var unsignedJwtData = $"{headerBase64}.{payloadBasae64}";
var signature = dsa.SignData(Encoding.UTF8.GetBytes(unsignedJwtData));
return $"{unsignedJwtData}.{Convert.ToBase64String(signature)}";
}
}
private static int ToEpoch(DateTime time)
{
var span = DateTime.UtcNow - new DateTime(1970, 1, 1);
return Convert.ToInt32(span.TotalSeconds);
}
I have limited to the payload to what I think is the bear minimum requirements. I am new to jwt/http2 and APNS.
I could very well be missing something simple.
I'm trying to create a web app (hosted on Azure) for clients to be able to submit work items to our team services page. Basically a support ticket page so they don't have to call to explain their backlog all the time.
Below is the class and method i've made to create work items, following Microsoft's sample code, with some obvious changes for privacy reasons. This method is triggered by a button click, and so far I cannot get it to create any work items.
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using Newtonsoft.Json;
namespace customapp
{
public class CreateWorkItem
{
public void CreateWorkItemMethod()
{
string personalAccessToken = "xxxxxxxxx";
string credentials = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "xxx", personalAccessToken)));
Object[] patchDocument = new Object[1];
patchDocument[0] = new { op = "add", path = "/fields/System.Title", value = "Test" };
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
var patchValue = new StringContent(JsonConvert.SerializeObject(patchDocument), Encoding.UTF8, "application/json-patch+json");
var method = new HttpMethod("PATCH");
var request = new HttpRequestMessage(method, "https://example.visualstudio.com/exampleproject/_apis/wit/workitems/$Support&20Ticket?api-version=1.0") { Content = patchValue };
var response = client.SendAsync(request).Result;
if (response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsStringAsync().Result;
}
}}}}
In the url for the PATCH I am using the team project's ID (in place of /exampleproject you see below). Our site is set up to have an overall project, let's call it ""Master", and inside is a team project for each client, for example "ClientProject". So basically I want to create a "Support Ticket" work item in Master->ClientProject->Backlog/Board.
Using Master\\areapath instead (not Master\areapath).
Sample body:
[
{
"op": "add",
"path": "/fields/System.Title",
"value": "PBIAPI2"
},
{
"op": "add",
"path": "/fields/System.AreaPath",
"value": "Scrum2015\\SharedArea"
}
]
On the other hand, it’s better to create work item by using VSTS/TFS API with Microsoft Team Foundation Server Extended Client package.
Simple sample code:
var u = new Uri("https://[account].visualstudio.com");
VssCredentials c = new VssCredentials(new Microsoft.VisualStudio.Services.Common.VssBasicCredential(string.Empty, "[personal access token]"));
var connection = new VssConnection(u, c);
var workitemClient = connection.GetClient<WorkItemTrackingHttpClient>();
var workitemtype = "Product Backlog Item";
string teamProjectName = "Scrum2015";
var document = new Microsoft.VisualStudio.Services.WebApi.Patch.Json.JsonPatchDocument();
document.Add(
new Microsoft.VisualStudio.Services.WebApi.Patch.Json.JsonPatchOperation()
{
Path = "/fields/Microsoft.VSTS.Common.Discipline",
Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
Value = "development"
});
document.Add(
new Microsoft.VisualStudio.Services.WebApi.Patch.Json.JsonPatchOperation()
{
Path = "/fields/System.Title",
Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
Value = string.Format("{0} {1}", "RESTAPI", 6)
});
document.Add(new Microsoft.VisualStudio.Services.WebApi.Patch.Json.JsonPatchOperation()
{
Path = "/fields/System.AreaPath",
Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
Value =string.Format("{0}\\{1}",teamProjectName, "SharedArea")
});
document.Add(
new Microsoft.VisualStudio.Services.WebApi.Patch.Json.JsonPatchOperation()
{
Path = "/fields/System.AssignedTo",
Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
Value = "[user account]"
});
document.Add(
new Microsoft.VisualStudio.Services.WebApi.Patch.Json.JsonPatchOperation()
{
Path = "/fields/System.Description",
Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
Value = "destest"
});
var workitem= workitemClient.CreateWorkItemAsync(document, teamProjectName, workitemtype).Result;
The method must be POST and Uri correct for consume the Api tfs is :
https://dev.azure.com/{organization}/{proyect}/_apis/wit/workitems/${type}?api-version=5.0
Check in :
https://learn.microsoft.com/en-us/rest/api/azure/devops/wit/work%20items/create?view=azure-devops-rest-5.0
The next code function for me.
static void Main(string[] args)
{
CreateWorkItem();
}
public static void CreateWorkItem()
{
string _tokenAccess = "************"; //Click in security and get Token and give full access https://azure.microsoft.com/en-us/services/devops/
string type = "Bug";
string organization = "type your organization";
string proyect = "type your proyect";
string _UrlServiceCreate = $"https://dev.azure.com/{organization}/{proyect}/_apis/wit/workitems/${type}?api-version=5.0";
dynamic WorkItem = new List<dynamic>() {
new
{
op = "add",
path = "/fields/System.Title",
value = "Sample Bug test"
}
};
var WorkItemValue = new StringContent(JsonConvert.SerializeObject(WorkItem), Encoding.UTF8, "application/json-patch+json");
var JsonResultWorkItemCreated = HttpPost(_UrlServiceCreate, _tokenAccess, WorkItemValue);
}
public static string HttpPost(string urlService, string token, StringContent postValue)
{
try
{
string request = string.Empty;
using (HttpClient httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", token))));
using (HttpRequestMessage httpRequestMessage = new HttpRequestMessage(new HttpMethod("POST"), urlService) { Content = postValue })
{
var httpResponseMessage = httpClient.SendAsync(httpRequestMessage).Result;
if (httpResponseMessage.IsSuccessStatusCode)
request = httpResponseMessage.Content.ReadAsStringAsync().Result;
}
}
return request;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
I'm trying to use the below code but for some reason I'm getting an invalid or expired token it seemed to work once but never again.
Any ideas? (consumerKey and consumerSecret are constants generated in the class.)
public ActionResult Index()
{
string twitterAccount = System.Configuration.ConfigurationManager.AppSettings["twitterAccount"];
JsonDeserializer jsonDeserializer = new JsonDeserializer();
var model = new TwitterVM.LandingModel();
var qs = GetToken();
string oauthToken = qs["oauth_token"];
string oauthTokenSecret = qs["oauth_token_secret"];
RestClient client = new RestClient("https://api.twitter.com/1.1")
{
Authenticator = OAuth1Authenticator.ForProtectedResource(consumerKey, consumerSecret, oauthToken, oauthTokenSecret)
};
RestRequest request = new RestRequest("statuses/user_timeline", Method.GET);
request.Parameters.Add(new Parameter()
{
Name = "screen_name",
Value = twitterAccount,
Type = ParameterType.GetOrPost
});
request.Parameters.Add(new Parameter()
{
Name = "count",
Value = 10,
Type = ParameterType.GetOrPost
});
request.Parameters.Add(new Parameter()
{
Name = "include_rts",
Value = true,
Type = ParameterType.GetOrPost
});
request.Parameters.Add(new Parameter()
{
Name = "include_entities",
Value = true,
Type = ParameterType.GetOrPost
});
IRestResponse response = client.Execute(request);
model.Tweets =
jsonDeserializer.Deserialize<List<TwitterVM.Tweet>>(response);
return View(model);
}
private NameValueCollection GetToken()
{
RestClient client = new RestClient("https://api.twitter.com") { Authenticator = OAuth1Authenticator.ForRequestToken(consumerKey, consumerSecret) };
//Do the auth shit...
RestRequest request = new RestRequest("oauth/request_token", Method.POST);
IRestResponse response = client.Execute(request);
return HttpUtility.ParseQueryString(response.Content);
}
Using Twitter's OAuth2 API (https://api.twitter.com/oauth2/token)
See https://dev.twitter.com/oauth/application-only for details....
var client = await CreateHttpClient("....", "....");
//don't dispose this client and use for subsequent API calls
var screenName = "....";
var count = 10;
var include_rts = true;
var url = $"https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name={screenName}&include_rts={include_rts}&count={count}";
var json = await client.GetStringAsync(url);
public static async Task<HttpClient> CreateHttpClient(string consumerKey, string consumerSecret)
{
var bearerToken = Convert.ToBase64String(Encoding.UTF8.GetBytes(consumerKey + ":" + consumerSecret));
string url = "https://api.twitter.com/oauth2/token";
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "Basic " + bearerToken);
var resp = await client.PostAsync(url, new StringContent("grant_type=client_credentials", Encoding.UTF8, "application/x-www-form-urlencoded")).ConfigureAwait(false);
resp.EnsureSuccessStatusCode();
var result = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
var jObj = new JavaScriptSerializer().Deserialize<Dictionary<string,string>>(result);
if (jObj["token_type"] != "bearer") throw new Exception("Invalid Response From Twitter/OAuth");
client.DefaultRequestHeaders.Remove("Authorization");
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "Bearer " + jObj["access_token"]);
return client;
}