I am trying to make a POST call to findMeetingTimes using Microsoft Graph in C#
https://graph.microsoft.com/v1.0/users/{userid}/findMeetingTimes
To get user profile data, I have followings:
IUserProfile IUserAuthentication.GetProfileData(string accessToken)
{
MicrosoftUserProfile profile = new MicrosoftUserProfile();
try
{
string url = "https://graph.microsoft.com/v1.0/me";
Dictionary<string, string> headers = new Dictionary<string, string>();
headers.Add("Authorization", "Bearer " + accessToken);
WebRequests webReq = new WebRequests();
string response = webReq.GetRequest(url, headers);
profile = JsonConvert.DeserializeObject<MicrosoftUserProfile>(response);
}
catch (Exception)
{
throw;
}
return profile;
}
public string GetRequest(string url, IDictionary<string, string> headers)
{
string returned = "";
try
{
System.Net.WebRequest webRequest = System.Net.WebRequest.Create(url);
webRequest.Method = "GET";
if (headers.Count > 0)
{
foreach (var item in headers)
{
webRequest.Headers.Add(item.Key, item.Value);
}
}
System.Net.WebResponse resp = webRequest.GetResponse();
System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream());
returned = sr.ReadToEnd().Trim();
}
catch (Exception)
{
throw;
}
return returned;
}
The best suggestion for you is to use the Microsoft Graph Client Library directly but not to use the HttpClient. After installing the library and then
just use the following code:
graphClient.Me.FindMeetingTimes().Request().PostAsync()
This is a simple and efficient way to make your code more readable.
Of course, you can write your own logic by imitating the following code:
// 1. Create request message with the URL for the trending API.
string requestUrl = "https://graph.microsoft.com/V1.0/me/findMeetingTimes";
HttpRequestMessage hrm = new HttpRequestMessage(HttpMethod.Post, requestUrl);
// 2. Authenticate (add access token) our HttpRequestMessage
graphClient.AuthenticationProvider.AuthenticateRequestAsync(hrm).GetAwaiter().GetResult();
// 3. Send the request and get the response.
HttpResponseMessage response = graphClient.HttpProvider.PostAsync(hrm).Result;
// 4. Get the response.
var content = response.Content.ReadAsStringAsync().Result;
JObject responseBody = JObject.Parse(content);
// 4. Get the array of objects from the 'value' key.
JToken arrayOfObjects = responseBody.GetValue("value");
Related
I'm getting code 400 only in C# and when I use post man I get 200!
It has the same properties.
I initally created the classes as JSONProperty attributes and still after decentralize I get code 400.
Found on fiddler innder exception -
message=parameters : The property 'Changedby' does not exist on type 'XXXXX.AzureAd.XXX.Types.NewDescriptionEntry'. Make sure to only use property names that are defined by the type.
The JSON in the debugging mode in C# after creating the classes - JSON mode.
// Serialize our concrete class into a JSON String
var stringPayload = await Task.Run(() =>
JsonConvert.SerializeObject(payload_transferIncident));
// build the URL we'll hit
var url = string.Format("https://XXXXXX", "YYYYY", id, "XXXX");
//create the request
var req = HttpWebRequest.CreateHttp(url);
//add in the cert we'll authenticate with
req.ClientCertificates.Add(IcmIncidentOperation.GetCert("XXXXXX"));
req.ContentType = "application/json";
req.Method = "POST";
if (req == null)
throw new ApplicationException(string.Format("Could not create the httprequest from the url:{0}", url));
try
{
using (var streamWriter = new StreamWriter(req.GetRequestStream()))
{
streamWriter.Write(stringPayload);
}
var httpResponse = (HttpWebResponse)req.GetResponse();
}
catch (Exception ex)
{
Console.WriteLine(ex);
var httpResponse = (HttpWebResponse)req.GetResponse();
}
Try this way using HttpRequest POST METHOD
try
{
var baseAddress = new Uri("Your base url");
using (var httpClient = new HttpClient
{
BaseAddress = baseAddress
})
{
var json =Newtonsoft.Json.JsonConvert.SerializeObject( payload);
using (var content = new StringContent( json, System.Text.Encoding.Default, "application/json"))
{
try
{
using (var response = await httpClient.PostAsync("end-point url method", content))
{
result = await response.Content.ReadAsStringAsync();
}
}
catch(Exception ex)
{
return ex.Message;
}
}
}
}
catch (Exception ex)
{
result = ex.Message;
}
I need to postAsync with header and content together. In order to get access to a website through Console Application in C#. I have my headers as an HttpHeader object with variable name header and my content named newContent as a string object with __Token, return, Email and Password. Now what I want to do is add newContent to header and then use postAsync(url, header+content) to make my POST request.
public async static void DownloadPage(string url)
{
CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
using (HttpClient client = new HttpClient(handler))
{
using (HttpResponseMessage response = client.GetAsync(url).Result)
{
//statusCode
CheckStatusCode(response);
//header
HttpHeaders headers = response.Headers;
//content
HttpContent content = response.Content;
//getRequestVerificationToken&createCollection
string newcontent = CreateCollection(content);
using(HttpResponseMessage response2 = client.PostAsync(url,))
}
}
}
public static string GenerateQueryString(NameValueCollection collection)
{
var array = (from key in collection.AllKeys
from value in collection.GetValues(key)
select string.Format("{0}={1}", WebUtility.UrlEncode(key), WebUtility.UrlEncode(value))).ToArray();
return string.Join("&", array);
}
public static void CheckStatusCode(HttpResponseMessage response)
{
if (response.StatusCode != HttpStatusCode.OK)
throw new Exception(String.Format(
"Server error (HTTP {0}: {1}).",
response.StatusCode,
response.ReasonPhrase));
else
Console.WriteLine("200");
}
public static string CreateCollection(HttpContent content)
{
var myContent = content.ReadAsStringAsync().Result;
HtmlNode.ElementsFlags.Remove("form");
string html = myContent;
var doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html);
var input = doc.DocumentNode.SelectSingleNode("//*[#name='__Token']");
var token = input.Attributes["value"].Value;
//add all necessary component to collection
NameValueCollection collection = new NameValueCollection();
collection.Add("__Token", token);
collection.Add("return", "");
collection.Add("Email", "11111111#hotmail.com");
collection.Add("Password", "1234");
var newCollection = GenerateQueryString(collection);
return newCollection;
}
I did the very same thing yesterday. I created a seperate class for my Console App and put the HttpClient stuff in there.
In Main:
_httpCode = theClient.Post(_response, theClient.auth_bearer_token);
In the class:
public long Post_RedeemVoucher(Response _response, string token)
{
string client_URL_voucher_redeem = "https://myurl";
string body = "mypostBody";
Task<Response> content = Post(null, client_URL_voucher_redeem, token, body);
if (content.Exception == null)
{
return 200;
}
else
return -1;
}
Then the call itself:
async Task<Response> Post(string headers, string URL, string token, string body)
{
Response _response = new Response();
try
{
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, URL);
request.Content = new StringContent(body);
using (HttpResponseMessage response = await client.SendAsync(request))
{
if (!response.IsSuccessStatusCode)
{
_response.error = response.ReasonPhrase;
_response.statusCode = response.StatusCode;
return _response;
}
_response.statusCode = response.StatusCode;
_response.httpCode = (long)response.StatusCode;
using (HttpContent content = response.Content)
{
_response.JSON = await content.ReadAsStringAsync().ConfigureAwait(false);
return _response;
}
}
}
}
catch (Exception ex)
{
_response.ex = ex;
return _response;
}
}
I hope this points you in he right direction!
How about iterating over your Headers and adding them to the Content object:
var content = new StringContent(requestString, Encoding.UTF8);
// Iterate over current headers, as you can't set `Headers` property, only `.Add()` to the object.
foreach (var header in httpHeaders) {
content.Headers.Add(header.Key, header.Value.ToString());
}
response = client.PostAsync(Url, content).Result;
Now, they're sent in one method.
If you are still looking into this you can also add headers at the request level as well as the HttpClient level. This works for me:
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, URL);
request.Content = new StringContent(body);
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
I've written below C# code to login to JIRA Rest API:
var url = new Uri("http://localhost:8090/rest/auth/latest/session?os_username=tempusername&os_password=temppwd");
var request = WebRequest.Create(url) as HttpWebRequest;
if (null == request)
{
return "";
}
request.Method = "POST";
request.ContentType = "application/json";
request.ContentLength = 200;
request.KeepAlive = false;
using (var response = request.GetResponse() as HttpWebResponse)
{
}
When I execute this, application just goes on running without returning any response. Please suggest if this is the right way of calling JIRA Login using REST API
For basic authentication you need to send in the username and password in a base64-encoding. Guidelines can be found in the API examples on atlassians developer page:
https://developer.atlassian.com/display/JIRADEV/JIRA+REST+API+Example+-+Basic+Authentication
, if you are doing it in C# you need to send the encoded data in the header in the following format:
"Authorization: Basic [ENCODED CREDENTIALS]"
Here is a simple example:
public enum JiraResource
{
project
}
protected string RunQuery(
JiraResource resource,
string argument = null,
string data = null,
string method = "GET")
{
string url = string.Format("{0}{1}/", m_BaseUrl, resource.ToString());
if (argument != null)
{
url = string.Format("{0}{1}/", url, argument);
}
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.ContentType = "application/json";
request.Method = method;
if (data != null)
{
using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
{
writer.Write(data);
}
}
string base64Credentials = GetEncodedCredentials();
request.Headers.Add("Authorization", "Basic " + base64Credentials);
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
string result = string.Empty;
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
result = reader.ReadToEnd();
}
return result;
}
private string GetEncodedCredentials()
{
string mergedCredentials = string.Format("{0}:{1}", m_Username, m_Password);
byte[] byteCredentials = UTF8Encoding.UTF8.GetBytes(mergedCredentials);
return Convert.ToBase64String(byteCredentials);
}
(JiraResource is just an enum I use to decide which part of the API to use)
I hope this will help!
Here is a simpler solution which works as required:
var mergedCredentials = string.Format("{0}:{1}", username, password);
var byteCredentials = Encoding.UTF8.GetBytes(mergedCredentials);
var encodedCredentials = Convert.ToBase64String(byteCredentials);
using (WebClient webClient = new WebClient())
{
webClient.Headers.Set("Authorization", "Basic " + encodedCredentials);
return webClient.DownloadString(url);
}
If you don't want to encode your credentials in every request here is how to do it using cookies.
When requesting the cookie you don't need to add any authorization on the headers. This method will accept a JSON string with the user name and password and the URL. It will return the cookie values.
public async Task<JiraCookie> GetCookieAsync(string myJsonUserNamePassword, string JiraCookieEndpointUrl)
{
using (var client = new HttpClient())
{
var response = await client.PostAsync(
JiraCookieEndpointUrl,
new StringContent(myJsonUserNamePassword, Encoding.UTF8, "application/json"));
var json = response.Content.ReadAsStringAsync().Result;
var jiraCookie= JsonConvert.DeserializeObject<JiraCookie>(json);
return jArr;
}
}
public class JiraCookie
{
public Session session { get; set; }
}
public class Session
{
public string name { get; set; }
public string value { get; set; }
}
When I call it using url: http://[baseJiraUrl]/rest/auth/1/session it returns the following JSON response:
{
"session" : -{
"name" : JSESSIONID,
"value" : cookieValue
}
Keep in mind the URL above is valid in the version of JIRA I'm using and may vary depending on which version you're using. Read the JIRA API documentation for the correct URL for the version you are using. I'm using the following:
https://docs.atlassian.com/software/jira/docs/api/REST/7.6.1/#auth/1/session
Remember you'll have to store your cookie and use it on every subsequent request.
Check out this answer on how add cookies to your HttpClient request: How do I set a cookie on HttpClient's HttpRequestMessage.
Once you're done with the cookie (logging out) simply send a delete http request with the same URL as the post.
I tweaked the RunQuery code so that it will run today (Apr 2018). The encrypt/decrypt referenced below is from the following link (I converted it to an extension method and threw values into environment).
https://stackoverflow.com/questions/10168240/encrypting-decrypting-a-string-in-c-sharp
I successfully execute the code from LinqPad - thus the Dump() command after RunQuery
private string _baseUrl = "https://xxxxxx.atlassian.net";
private string _username = "YourLogin";
void Main()
{
RunQuery(JiraResource.project).JsonToXml().Dump();
}
public enum JiraResource { project }
private const string restApiVersion = "/rest/api/2/";
protected string RunQuery( JiraResource resource, string argument = null, string data = null, string method = "GET")
{
string url = $"{_baseUrl}{restApiVersion}{resource}";
if (argument != null) url = $"{url}{argument}/";
var request = WebRequest.Create(url) as HttpWebRequest;
request.ContentType = "application/json";
request.Method = method;
if (data != null)
{
using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
{
writer.Write(data);
}
}
string base64Credentials = GetEncodedCredentials();
request.Headers.Add("Authorization", "Basic " + base64Credentials);
var response = request.GetResponse() as HttpWebResponse;
string result = string.Empty;
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
result = reader.ReadToEnd();
}
return result;
}
private string GetEncodedCredentials()
{
var encryptedPassword = Environment.GetEnvironmentVariable("PassEncrypted");
var encryptionSalt = Environment.GetEnvironmentVariable("PassSalt");
var password = encryptedPassword.Decrypt(encryptionSalt);
var mergedCredentials = $"{_username}:{password}";
var byteCredentials = UTF8Encoding.UTF8.GetBytes(mergedCredentials);
return Convert.ToBase64String(byteCredentials);
}
public static class MyExtensions
{
public static XElement JsonToXml(this string jsonData, bool isAddingHeader = true)
{
var data = isAddingHeader
? "{\"record\":" + jsonData + "}"
: jsonData;
data = data // Complains if xml element name starts numeric
.Replace("16x16", "n16x16")
.Replace("24x24", "n24x24")
.Replace("32x32", "n32x32")
.Replace("48x48", "n48x48");
var result = JsonConvert.DeserializeXmlNode(data, "data");
var xmlResult = XElement.Parse(result.OuterXml);
return xmlResult;
}
}
For posting multipart content in Rest I use Tiny.RestClient.
var client = new TinyRestClient(new HttpClient(), "http://localhost:8090");
var strResult = await client.PostRequest("rest/auth/latest/session).
WithBasicAuthentication("username", "password")
ExecuteAsStringAsync();
static void Main(string[] args)
{
using (WebClient wc = new WebClient())
{
wc.Headers.Add("Authorization", "Basic " + GetEncodedCredentials());
string tasks = wc.DownloadString("yourjiraurl/search?jql=task=bug");
var taskdetails = JsonConvert.DeserializeObject<TaskDetails>(tasks);
}
}
static string GetEncodedCredentials()
{
string mergedCredentials = string.Format("{0}:{1}", "UserName", "Password");
byte[] byteCredentials = UTF8Encoding.UTF8.GetBytes(mergedCredentials);
return Convert.ToBase64String(byteCredentials);
}
I'm receiving a 400 Bad Request error message when posting a pin on Pinterest. It works using Postman, but doesn't work programmatically. Using C#, has anyone been able to successfully post a pin on Pinterest without using the pinsharp wrapper?
private void postPinterest(string messages, string id, string usertoken, string image, string boardname, string username)
{
string link = null;
boardname = boardname.Replace(" ", "-");
string board = username + "/" + boardname;
string url = "https://api.pinterest.com/v1/pins?access_token=" + usertoken;
StringBuilder sb = new StringBuilder();
if (!string.IsNullOrEmpty(board))
sb.Append("&board=" + HttpUtility.UrlEncode(board));
if (!string.IsNullOrEmpty(messages))
sb.Append("¬e=" + HttpUtility.UrlEncode(messages));
if (!string.IsNullOrEmpty(link))
sb.Append("&image_url=" + HttpUtility.UrlEncode(link));
string postdata = sb.ToString().Substring(1);
PostData(url, postdata);
}
private object PostData(string url, string postdata)
{
object json=null;
try
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
// req.Accept = "application/json";
using (var stream = req.GetRequestStream())
{
byte[] bindata = Encoding.ASCII.GetBytes(postdata);
stream.Write(bindata, 0, bindata.Length);
}
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
string response = new StreamReader(resp.GetResponseStream()).ReadToEnd();
json = JsonConvert.DeserializeObject<dynamic>(response);
return json;
}
catch (WebException wex)
{
if (wex.Response != null)
{
using (var errorResponse = (HttpWebResponse)wex.Response)
{
using (var reader = new StreamReader(errorResponse.GetResponseStream()))
{
string error = reader.ReadToEnd();
return json;
}
}
}
}
return json;
}
EDIT:
It doesn't work using the JSON format or x-www-form-urlencoded format.
I changed the content type to application/x-www-form-urlencoded and now I'm receiving the error message below. I receive 400 Bad Request error using JSON format:
"{\n \"message\": \"405: Method Not Allowed\",\n \"type\": \"http\"\n}"
The problem is the the parameter that you are posting.
In the Api i could find board as a parameter but both note and image comes under field parameter which specifies the return type JSON.
As per documentation on this page you can post in this format
https://api.pinterest.com/v1/boards/anapinskywalker/wanderlust/pins/?
access_token=abcde&
limit=2&
fields=id,link,counts,note
So I tried the following and its getting response
https://api.pinterest.com/v1/boards/?access_token="YourTokenWithoutQuotes"&fields=id%2Ccreator
Would suggest you to first test the Api you are hitting putting a breakpoint inside the PostData function and check if the passed url is in the correct format and compare it with Pininterest API Explorer.
As you might have already received authorization code and access token so I am assuming your post function should be working fine.
public string postPinterest(string access_token,string boardname,string note,string image_url)
{
public string pinSharesEndPoint = "https://api.pinterest.com/v1/pins/?access_token={0}";
var requestUrl = String.Format(pinSharesEndPoint, accessToken);
var message = new
{
board = boardname,
note = note,
image_url = image_url
};
var requestJson = new JavaScriptSerializer().Serialize(message);
var client = new WebClient();
var requestHeaders = new NameValueCollection
{
{"Content-Type", "application/json" },
{"x-li-format", "json" }
};
client.Headers.Add(requestHeaders);
var responseJson = client.UploadString(requestUrl, "POST", requestJson);
var response = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(responseJson);
return response;
}
I am trying to access to some rest services of a specific web server for my WP8 app and I canĀ“t do it well. For example, this is the code that I use when I try to login the user. I have to pass a string that represents a Json object ("parameters") with the username and the password and the response will be a json object too. I can't find the way to pass this pasameters in the rest request.
This is the code;
public void login(string user, string passwrd)
{
mLoginData.setUserName(user);
mLoginData.setPasswd(passwrd);
string serviceURL = mBaseURL + "/service/user/login/";
string parameters = "{\"username\":\"" + mLoginData.getUserName() + "\",\"password\":\"" + mLoginData.getPasswd() + "\"}";
//MessageBox.Show(parameters);
//MessageBox.Show(serviceURL);
//build the REST request
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(serviceURL);
request.ContentType = "application/json";
request.Method = "POST";
//async request launchs "Gotresponse(...) when it has finished.
request.BeginGetResponse(new AsyncCallback(GotResponse), request);
}
private void GotResponse(IAsyncResult ar)
{
try
{
string data;
// State of request is asynchronous
HttpWebRequest myHttpWebRequest = (HttpWebRequest)ar.AsyncState;
using (HttpWebResponse response = (HttpWebResponse)myHttpWebRequest.EndGetResponse(ar))
{
// Read the response into a Stream object.
Stream responseStream = response.GetResponseStream();
using (var reader = new StreamReader(responseStream))
{
data = reader.ReadToEnd();
}
responseStream.Close();
}
}
catch (Exception e)
{
string exception = e.ToString();
throw;
}
}
I tried too with the webClient and the httpClient classes too but without any result.
Thanks and sorry for my bad english.
I solved it with the HttpClient class. This is the code.
public async void login(string user, string passwrd)
{
string serviceURL = "";
string parameters = "";
HttpClient restClient = new HttpClient();
restClient.BaseAddress = new Uri(mBaseURL);
restClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, serviceURL);
req.Content = new StringContent(parameters, Encoding.UTF8, "application/json");
HttpResponseMessage response = null;
string responseBodyAsText = "";
try
{
response = await restClient.SendAsync(req);
response.EnsureSuccessStatusCode();
responseBodyAsText = await response.Content.ReadAsStringAsync();
}
catch (HttpRequestException e)
{
string ex = e.Message;
}
if (response.IsSuccessStatusCode==true)
{
dynamic data = JObject.Parse(responseBodyAsText);
}
else
{
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
MessageBox.Show("User or password were incorrect");
}
else
{
MessageBox.Show("NNetwork connection error");
}
}
}
I wasn't setting the header values of the request correctly.
I hope this can help someone.