Changing issue status to Done via Jira REST API, Atlassian.Net SDK - c#

I'm working with Jira REST APIs with visual studio (c#) with help of Atlassian.NET SDK and trying to build such model:
search for ticket with Project, issue summary and status;
If issue is found, then I want to change its status from “To Do” to “Done”;
If there are no issues found, then do nothing.
Search functionality works good, the problem is with changing its status. Here’s my code:
static async System.Threading.Tasks.Task Main(string[] args)
{
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072; //TLS 1.2
try
{
// Connection to JIRA using REST client
var jira = Jira.CreateRestClient("https://XXX.atlassian.net", "user", "token");
// LINQ syntax for retrieving issues
var issue = (from i in jira.Issues.Queryable
where i.Project == "QA" && i.Summary == "Summary" && i.Status == "To Do"
orderby i.Created
select i).First();
await issue.SaveChangesAsync();
string ticketid = issue.Key.Value;
string ticketsummary = issue.Summary;
string ticketkey = issue.JiraIdentifier;
//Updating found issue
var closeticket = await jira.Issues.GetIssueAsync(ticketid);
closeticket.Status = "Done";
await closeticket.SaveChangesAsync();
}
catch (Exception ex) { /*Result: SUCCESS [no issues found]*/ }
}
With this code I’m trying to search in project “QA”, where issue summary is “Summary” and status is “To Do”. Then I want to close its Status from “To Do” to “Done”. But I’m getting error on line closeticket.Status = "Done"; with text:
Error CS0200 Property or indexer 'Issue.Status' cannot be assigned to -- it is read only
Please give me some suggestions or I’m about to hang myself…
Thank you in advance.
EDIT:
I forgot to mention that I also tried to do the status changing case with help of httpclient. But there's a problem, when I connect to issue transitions, it returns error with statuscode 404.
var handler = new HttpClientHandler();
handler.AllowAutoRedirect = true;
handler.Proxy = new WebProxy("https://XXX.atlassian.net", true, null, CredentialCache.DefaultNetworkCredentials);
// need to pass a valid username + password to JIRA
var jiraCredentials = UTF8Encoding.UTF8.GetBytes("user:token");
var httpClient = new HttpClient(handler);
httpClient.MaxResponseContentBufferSize = int.MaxValue;
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(jiraCredentials));
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string transitionURL = "https://XXX.atlassian.net" + "/rest/api/2/issue/" + "QA-10" + "/transitions?expand=transitions.fields";
string jsonString = "{ \"update\":{},\"transition\": { \"id\": \"" + "31" + "\"}, \"fields\": { } }";
var sContent = new StringContent(jsonString, Encoding.UTF8, "application/json");
var httpClientt = new HttpClient();
HttpResponseMessage transitionResponse = httpClientt.PostAsync(transitionURL, sContent).Result;
httpClient.Dispose();

After a deep research, I have finally reached the right way which is http request.
If there's anybody suffering with problem, here's a code:
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), "https://XXX.atlassian.net/rest/api/2/issue/TST-4/transitions?expand=transitions.fields"))
{
var base64authorization = Convert.ToBase64String(Encoding.ASCII.GetBytes("user:token"));
request.Headers.TryAddWithoutValidation("Authorization", $"Basic {base64authorization}");
request.Content = new StringContent("{\"transition\":{\"id\":\"31\"}}");
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await httpClient.SendAsync(request);
}
}

Related

How to send parameters on O365 Power Automate HTTP Request connector

I've been troubleshooting this for days now but still no luck.
I'm trying to send parameters to an API link provided by Microsoft O365 Power Automate, this API requires a customer number, company code, and posting date and in return, it will send me a table with the list of items that have the same customer number, company code, and posting date. When I'm doing testing in Postman the sends status code 200, but when using VS and my code it always returns a status code 400.
SoaController.cs
[HttpPost]
public async Task<IActionResult> Index(string company, string customer, string asof)
{
using (var client = new HttpClient())
{
SoaParams soaParams = new SoaParams
{
Posting_Date = asof,
Company_Code = company,
Customer_Number = customer
};
var SoaJson = JsonConvert.SerializeObject(soaParams);
var buffer = Encoding.UTF8.GetBytes(SoaJson);
var byteContent = new ByteArrayContent(buffer);
byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
client.BaseAddress = new Uri(SD.ApiUri);
var response = await client.PostAsync(SD.ApiUri, byteContent);
if (response.IsSuccessStatusCode)
{
return RedirectToAction(nameof(Success), Json(response));
}
else
{
return RedirectToAction(nameof(Failed), Json(response));
}
}
}
The below image shows that the parameters needed are correct.
But it's SuccessStatusCode always returns false
I use a code provided by PostMan that look like this:
public List<BapiOpenItemDto> GetResponse(SoaParams soaParams, string uri)
{
var SoaJson = JsonConvert.SerializeObject(soaParams);
var client = new RestClient(uri);
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.OnBeforeDeserialization = resp => { resp.ContentType = "application/json"; };
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "[\r\n" + SoaJson + "\r\n]\r\n", ParameterType.RequestBody);
IRestResponse<List<BapiOpenItemDto>> response = client.Execute<List<BapiOpenItemDto>>(request);
return response.Data;
}
and its working now.

External Login using Custom API

I have 2 projects one Web API that have a simple /Token api that returns a token for the logged in user
and the second project is .NET Core that will use the URL/Token method in the login form.
Here is the code on the method that is used to login in the second project
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
var requestBody = new { grant_type = "password", username = Input.Email, password = Input.Password };
var data = Newtonsoft.Json.JsonConvert.SerializeObject(requestBody);
using (var client = new HttpClient())
using (var req = new HttpRequestMessage(HttpMethod.Get, "http://localhost:49470/Token"))
{
req.Content = new StringContent("{\"grant_type\":\"password\",\"username\":" + Input.Email + ",\"password\":" + Input.Password + "}", Encoding.UTF8, "application/json");
using (var rep = await client.SendAsync(req))
{
rep.EnsureSuccessStatusCode();
var content = await rep.Content.ReadAsStringAsync();
}
}
}
}
Error i'm facing:
The problem that i'm facing i always get a 400 (Bad Request) Error, ps: i'm new in .netcore
I've solved it, the problem was the api\Token body didn't accept the structure of the json parsed string
Simply i've used
var response = client.PostAsync("http://localhost:49470/Token", new StringContent("grant_type=password&username=" + Input.Email + "&password=" + Input.Password, Encoding.UTF8, "application/json")).Result;

write a http post request to bot framework running on localhost

I have a bot running on http://localhost:3978/api/messages.
Instead of debugging it using an emulator, can I go about using a http post request to the messaging endpoint of the bot?
If so, how do I go about doing it?
I am using c# microsoft bot framework, and I am new to this application.
I do not want to use any channels or DirectLine api, just using Httpclient.
You can do this with C# using code similar to below. Note that you would have to construct an Activity to send by setting the appropriate properties for your needs, which is not included in this code.
//make a call to get an auth token
string token;
using (var client = new WebClient())
{
var values = new NameValueCollection();
values["grant_type"] = "client_credentials";
values["client_id"] = "YOUR APP ID";
values["client_secret"] = "NcOXRwb51joibEfzUuNE04u";
values["scope"] = "YOUR APP ID/.default";
var response =
client.UploadValues("https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token", values);
var responseString = Encoding.Default.GetString(response);
var result = JsonConvert.DeserializeObject<ResponseObject>(responseString);
token = result.access_token;
}
//you will need to adjust this value for your project.
//this example for a proxy project so the service url here is
//just an arbitrary endpoint I was using to send activities to
activity.ServiceUrl = "http://localhost:4643/api/return";
var jsonActivityAltered = JsonConvert.SerializeObject(activity);
using (var client = new WebClient())
{
client.Headers.Add("Content-Type", "application/json");
client.Headers.Add("Authorization", $"Bearer {token}");
try
{
var btmResponse = client.UploadString("http://localhost:3971/api/messages", jsonActivityAltered);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
Have you tried using something like postman? (it's free and easy to use)
https://www.getpostman.com/
You can also write scripts in postman
otherwise you can just go to the endpoint of your API in the browser
http://localhost:3978/api/
I see you mentioned you wanted to make a console application.
You could do that. I'd suggest using postman though.
Here is an example of sending a file as well as some querystring data and Authentication using a Bearer token.
Sorry it may not be exact. Had to do a bit of copy pasting/deleting from some code examples if have
using (HttpClient client = new HttpClient())
{
JObject jsonModel = new JObject();
client.BaseAddress = new Uri("http://localhost:3978/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AuthToken);
using (var multipartFormDataContent = new MultipartFormDataContent())
{
var values = new[]
{
new KeyValuePair<string, string>("firstname", lastname),
new KeyValuePair<string, string>("lastname", lastname),
new KeyValuePair<string, string>("payloadFile", FileName)
};
foreach (var keyValuePair in values)
{
multipartFormDataContent.Add(new StringContent(keyValuePair.Value),
String.Format("\"{0}\"", keyValuePair.Key));
}
ByteArrayContent fileContent = new ByteArrayContent(File.ReadAllBytes(HttpContext.Current.Server.MapPath("~/uploads/output/" + FileName)));
string FullxmlString = File.ReadAllText(Path.Combine(HttpContext.Current.Server.MapPath("~/uploads/output/" + FileName)));
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("payloadFile") { FileName = "payloadFile" };
multipartFormDataContent.Add(fileContent);
HttpResponseMessage response = client.PostAsync("api/message", multipartFormDataContent).Result;
string returnString = response.Content.ToString();
using (HttpContent content = response.Content)
{
string res = "";
Task<string> result = content.ReadAsStringAsync();
res = result.Result;
}
}
}

Paypal Rest Api With RestSharp not working in xamarin android

I have got error with RestSharp component when i am call Paypal Rest API.
I have the following code using Xamarin for Android.
public async Task<PayPalGetTokenResponse> GetAccessToken()
{
var restRequest = new RestRequest("/oauth2/token", Method.POST);
// Add headers
restRequest.AddHeader("Accept", "application/json");
restRequest.AddHeader("Accept-Language", "en_US");
// Make Authorization header
restClient.Authenticator = new HttpBasicAuthenticator(Config.ApiClientId, Config.ApiSecret);
// add data to send
restRequest.AddParameter("grant_type", "client_credentials");
var response = restClient.Execute<PayPalGetTokenResponse>(restRequest);
response.Data.DisplayError = CheckResponseStatus(response, HttpStatusCode.OK);
return response.Data;
}
But got error :"Error: SecureChannelFailure (The authentication or decryption has failed.)"
I have Also use ModernHttpClient but got same error
public async Task<PayPalGetTokenResponse> GetAccessToken()
{
string clientId = Config.ApiClientId;
string secret = Config.ApiSecret;
string oAuthCredentials = Convert.ToBase64String(Encoding.Default.GetBytes(clientId + ":" + secret));
string uriString = Config.ApiUrl+"/oauth2/token";
PayPalGetTokenResponse result;
HttpClient client = new HttpClient(new NativeMessageHandler());
var h_request = new HttpRequestMessage(HttpMethod.Post, uriString);
h_request.Headers.Authorization = new AuthenticationHeaderValue("Basic", oAuthCredentials);
h_request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
h_request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue("en_US"));
h_request.Content = new StringContent("grant_type=client_credentials", UTF8Encoding.UTF8);
try
{
HttpResponseMessage response = await client.SendAsync(h_request);
//if call failed ErrorResponse created...simple class with response properties
if (!response.IsSuccessStatusCode)
{
var error = await response.Content.ReadAsStringAsync();
var errResp = JsonConvert.DeserializeObject<string>(error);
//throw new PayPalException { error_name = errResp.name, details = errResp.details, message = errResp.message };
}
var success = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<PayPalGetTokenResponse>(success);
}
catch (Exception)
{
throw new HttpRequestException("Request to PayPal Service failed.");
}
return result;
}
Have you tried to force to modern day SSL protocol?
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
This works for me:
if (ServicePointManager.SecurityProtocol != SecurityProtocolType.Tls12)
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var client = new RestClient(payPalURL) {
Encoding = Encoding.UTF8
};
var authRequest = new RestRequest("oauth2/token", Method.POST) {
RequestFormat = DataFormat.Json
};
client.Authenticator = new HttpBasicAuthenticator(clientId, secret);
authRequest.AddParameter("grant_type","client_credentials");
var authResponse = client.Execute(authRequest);

Using a token to search on Twitter with OAuth2

Before Twitter switched to OAuth2, I was using the following query:
string atomTweetSearchURL = string.Format("http://search.twitter.com/search.atom?q={0}", searchText);
This no longer works, so now I'm trying to switch to OAuth2. I manage to successfully retrieve a token, but once I've got this, I seem to be unable to actually perform the search. Here's the latest incarnation of what I've tried:
var searchUrl = string.Format("https://api.twitter.com/1.1/search/tweets.json?q={0}&access_token={1}&token_type={2}", srchStr, twitAuthResponse.access_token, twitAuthResponse.token_type);
WebRequest srchRequest = WebRequest.Create(searchUrl);
using (var response2 = await srchRequest.GetResponseAsync())
{
Stream stream = response2.GetResponseStream();
using (StreamReader sr = new StreamReader(stream))
{
string jsonResponse = await sr.ReadToEndAsync();
}
}
This gives me a 400 - bad request.
I've also tried building the request like this:
System.Net.Http.HttpClient srchRequest = new System.Net.Http.HttpClient();
string authHdr = string.Format(srchHeaderFormat, twitAuthResponse.token_type, twitAuthResponse.access_token);
srchRequest.DefaultRequestHeaders.Add("Authorization", authHdr);
There's a massive quantity of articles out there detailing how to do this, but none of them seem to work correctly with WinRT. Can anyone point me in the right direction?
EDIT
Here's my code to get the token:
var oAuthConsumerKey = key;
var oAuthConsumerSecret = secret;
var oAuthUri = new Uri("https://api.twitter.com/oauth2/token");
var authHeaderFormat = "Basic {0}";
var authHeader = string.Format(authHeaderFormat,
Convert.ToBase64String(Encoding.UTF8.GetBytes(Uri.EscapeDataString(oAuthConsumerKey)
+ ":" +
Uri.EscapeDataString((oAuthConsumerSecret)))
));
var req = new HttpClient();
req.DefaultRequestHeaders.Add("Authorization", authHeader);
HttpRequestMessage msg = new HttpRequestMessage(new HttpMethod("POST"), oAuthUri);
msg.Content = new HttpStringContent("grant_type=client_credentials");
msg.Content.Headers.ContentType = new Windows.Web.Http.Headers.HttpMediaTypeHeaderValue("application/x-www-form-urlencoded");
HttpResponseMessage response = await req.SendRequestAsync(msg);
TwitAuthenticateResponse twitAuthResponse;
using (response)
{
string objectText = await response.Content.ReadAsStringAsync();
twitAuthResponse = JSonSerialiserHelper.Deserialize<TwitAuthenticateResponse>(objectText);
}
With the 1.1 API you don't pass the access token as part of the url, you need to include it as the Authorization header as "Bearer access_token" so you were almost there!
EDIT
To do this in the Windows.Web.Http namespace the following works:
private static async Task SearchTweets(AuthenticationResponse twitAuthResponse)
{
string srchStr = "tweet";
var client = new HttpClient();
var searchUrl = string.Format("https://api.twitter.com/1.1/search/tweets.json?q={0}", srchStr);
var uri = new Uri(searchUrl);
client.DefaultRequestHeaders.Authorization = new HttpCredentialsHeaderValue("Bearer", twitAuthResponse.AccessToken);
var response2 = await client.GetAsync(uri);
string content = await response2.Content.ReadAsStringAsync();
}
Or with System.Net.Http use the following:
This code will run the search for srchStr using the access token you already acquired as you showed in the first example:
var client = new HttpClient();
var searchUrl = string.Format("https://api.twitter.com/1.1/search/tweets.json?q={0}", srchStr);
var uri = new Uri(searchUrl);
client.DefaultRequestHeaders.Add("Authorization", string.Format("Bearer {0}", twitAuthResponse.access_token));
HttpResponseMessage response = await client.GetAsync(uri);
Task<string> content = response.Content.ReadAsStringAsync();
EDIT
This is a strange one, I tested your code and you're right it does throw an exception when attempting to add the Auth header, however the code I had used for grabbing the Access Token is almost identical but uses the System.Net.Http methods rather than the Windows.Web.Http ones that you use and it works, so I'll provide my code here, maybe this is a bug in the framework, or someone else can provide some more insight! This also uses the JSON.NET library which can be found on NuGet.
private static async Task SearchTweets(AuthenticationResponse twitAuthResponse)
{
string srchStr = "tweet";
var client = new HttpClient();
var searchUrl = string.Format("https://api.twitter.com/1.1/search/tweets.json?q={0}", srchStr);
var uri = new Uri(searchUrl);
client.DefaultRequestHeaders.Add("Authorization", string.Format("Bearer {0}", twitAuthResponse.AccessToken));
HttpResponseMessage response2 = await client.GetAsync(uri);
string content = await response2.Content.ReadAsStringAsync();
}
private async void GetAuthenticationToken()
{
var client = new HttpClient();
var uri = new Uri("https://api.twitter.com/oauth2/token");
var encodedConsumerKey = WebUtility.UrlEncode(TwitterConsumerKey);
var encodedConsumerSecret = WebUtility.UrlEncode(TwitterConsumerSecret);
var combinedKeys = String.Format("{0}:{1}", encodedConsumerKey, encodedConsumerSecret);
var utfBytes = System.Text.Encoding.UTF8.GetBytes(combinedKeys);
var encodedString = Convert.ToBase64String(utfBytes);
client.DefaultRequestHeaders.Add("Authorization", string.Format("Basic {0}", encodedString));
var data = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("grant_type", "client_credentials")
};
var postData = new FormUrlEncodedContent(data);
var response = await client.PostAsync(uri, postData);
AuthenticationResponse authenticationResponse;
using (response)
{
if (response.StatusCode != System.Net.HttpStatusCode.OK)
throw new Exception("Did not work!");
var content = await response.Content.ReadAsStringAsync();
authenticationResponse = JsonConvert.DeserializeObject<AuthenticationResponse>(content);
if (authenticationResponse.TokenType != "bearer")
throw new Exception("wrong result type");
}
await SearchTweets(authenticationResponse);
}
}
class AuthenticationResponse
{
[JsonProperty("token_type")]
public string TokenType { get; set; }
[JsonProperty("access_token")]
public string AccessToken { get; set; }
}

Categories

Resources