Desk.com and RestSharp (oAuth) - c#

This feels like it should be easy but...it's not. It definitely doesn't help that there's no library for Desk.com, and the documentation is (in my opinion) extremely thin and lacking.
Anyway, I'm trying to use RestSharp to do something simple: grab recent cases. I'm using the Single Access Token method as we don't need to interact as any of our users.
Here's the code:
var client = new RestClient();
client.Authenticator = RestSharp.Authenticators.OAuth1Authenticator.ForProtectedResource("key","secret","token","token secret");
client.BaseUrl = "http://xxx.desk.com/api/v1/";
var request = new RestRequest();
request.Method = Method.GET;
request.Resource = "cases.json?count=10&status=new";
request.RequestFormat = DataFormat.Json;
var result = client.Execute(request);
Result always just says the auth request was invalid and is unauthorized. Tried a bunch of different combinations, looked through the tests that are part of the RestSharp library, and read every meager word of the Desk.com documentation. Just not sure what to try next.

You may have figured this out already, but you get that unauthorized message when you try to add the querystring to the RestRequest's Resource.
I was having the same problem. Daniel's "account/verify_credentials.json" worked for me too, so that's when I started to wonder if it had something to do with the querystring.
var request = new RestRequest();
request.Method = Method.GET;
request.Resource = "cases.json";
request.RequestFormat = DataFormat.Json;
request.AddParameter("count", 10);
request.AddParameter("status", "new");

I just wanted to say, that after following a lot of examples on making the Desk API work with C#, yours was actually the only one that did work.
I did not test with the resource you specified above, but used your code together with the "account/verify_credentials.json" resource. It returns an OK response for me, so your code works. So, first of all...thank you :)
Second (sorry if I am stating the obvious), I assume that you do not use the ("key", "secret", "token", "token secret") parameters as you specified them here, but use valid ones. You most probably do, but mayyybe there is a small chance that you may have found and copied that piece of code from somewhere else, and perhaps missed filling in your info.
EDIT: Since my first answer, I have put together a small (really small) SDK that can be used to connect to and work with the API in C#. You can grab the source code here: http://danielsaidi.github.com/desk-csharp-sdk/
Hope you get it to work.

Related

Deleting an Azure Devops Test Case with c#

Azure Devops test case work items cannot be simply deleted online. They need to be "permanently deleted". And the code for deleting work items programatically does not work for test cases:
workItemTrackingClient.DeleteWorkItemAsync(witID, true).SyncResult();
The MSFT documentation says to use their Rest API - but their documentation doesn't really explain how to do it - they simply show "delete" and a url. I tried to use that url in a DELETE method rest call. (I use Restsharp for its clear syntax usually), as follows:
string adoURLBase = #"https://dev.azure.com/{OrgName}/";
string urlToUse = adoURLBase +
"ProjectName}/_apis/test/testcases/{workItemId}?api-version=7.0";
RestClient client = new RestClient(urlToUse);
RestRequest request = new RestRequest(adoURLBase, Method.Delete);
request.AddHeader("cache-control", "no-cache");
request.AddHeader("Accept", "application/json");
request.AddHeader("Authorization", "Basic " + personalAccessToken);
RestResponse response = client.Execute(request);
This failed, with a StatusCode: NotFound, and the content message: "The provided HTTP Verb is not supported on this controller.".
FYI - I also tried using the full URL ("urlToUse" above) in the "new RestRequest" instantiation. Same response. And I tried adding trhe parameter "destroy=true" as noted in MSFT's documentation. Same response.
The MSFT documentation I am looking at is at:
https://learn.microsoft.com/en-us/rest/api/azure/devops/wit/work-items/delete?view=azure-devops-rest-7.0&tabs=HTTP
Appreciate any help.
You may use DeleteTestCaseAsync method of Microsoft.TeamFoundationServer.Client
using Microsoft.VisualStudio.Services.TestManagement.TestPlanning.WebApi;
.............
TestPlanHttpClient TestPlanClient = Connection.GetClient<TestPlanHttpClient>();
TestPlanClient.DeleteTestCaseAsync("YOUR_TEAM_PROJECT", TESTCASE_ID).Wait();
or use Test Cases - Delete REST API method

How is the http-request finding the correct address with just a keyword C#

Our client is failing on one of our stations and is having issues connecting, so I look up the code and I see this:
var request = new HttpRequestMessage(HttpMethod.Post, "rpcapi")
{
Content = new StringContent(json, Encoding.UTF8, "application/json")
};
var options = isFileDownload
? HttpCompletionOption.ResponseHeadersRead
: HttpCompletionOption.ResponseContentRead;
return await _client.SendAsync(request, options, cancellationToken);
Now what confuses me is this line var request = new HttpRequestMessage(HttpMethod.Post, "rpcapi") because I know the address to our backend is not just "rpcapi", but a rather long address.
So how does this work (mind you the same code is working on other stations)? Does the program somehow know what to switch that "rpcapi" for and if so how and where can I find that code?
My best guess is that "rpcapi" is an alias for the rest of your path. Since I didn't know it was possible to alias a path before helping to find an answer for your question, I think your (backend)application knows what your path will be. You most certainly will have a basepath defined somewhere in your application, which might help you find an answer to your question. This should be somewhere in your api project.
This link might help: What's the difference between HttpRequest.Path and HttpRequest.PathBase in ASP.NET Core?

ADFS v4.0 and /userinfo endpoint giving 405

Integrating older ASP.NET server-side application into ADFS for authentication, which means I pretty much had to write everything from scratch. have everything working (/authorize, /token) up until the /userinfo call.
My code, in a nutshell -
HttpClient client = new HttpClient();
var req = new HttpRequestMessage {
RequestUri = new Url("https://<server_ip>/adfs/oauth2/userinfo"),
Method = HttpMethod.Get,
};
req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.AccessToken);
req.Headers.UserAgent.Clear();
req.Headers.UserAgent.Add(new ProductInfoHeaderValue("OldApp", "11.3.0"));
var result = await client.SendAsync(req);
The result is a HTTP error 405 - Method Not Allowed. Doing searches online, I see this as a common issue when the trailing "/" is left off the url, but I get the same result with a trailing slash.
After poking around, there are a lot of examples that use newer libraries and such that I can't use, sadly. None mention usage of the /userinfo, and I'm thinking that the issue isn't necessarily in how I'm calling the URL, but configuration of the 'Application Group' in ADFS.
Okay - I found the issue, and will document it here in case others come across the same thing..
While I am not sure why /userinfo is giving a 405 - the URL I was using is wrong, despite it being listed in the Endpoints folder. There shouldn't be any "oauth2" in the URL. The correct code (and URL) is:
var req = new HttpRequestMessage {
RequestUri = new Url("https://<server_ip>/adfs/userinfo"),
Method = HttpMethod.Get,
};
req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.AccessToken);
req.Headers.UserAgent.Clear();
req.Headers.UserAgent.Add(new ProductInfoHeaderValue("OldApp", "11.3.0"));
var result = await client.SendAsync(req);
Also something to keep in mind - this has been stated elsewhere, but not as clearly as here, I hope:
The /userinfo will ONLY give you the NameIdentifier ("sub") claim. (As far as I can see.) No matter what scope you pass it. You will get all your information (that should normally be in the /userinfo call) in the "id_token" parameter from you /token call, encoded as JWT.
Personally I was led to do the same thing as you, the only solution was to download the ADAL library (You will find the link below) and debug the code in order to re-produce the same HTTP stream from ADAL.
You can create a new project so that you can integrate ADAL, for debugging or else intercepting the HTTP stream
Link ADAL

RestSharp PUT request parameters

I'm having issues figuring out how to create a put request using RestSharp.
I need to pass an integer followed by a JSON body in the same request.
So far I have this:
for (var i = 0; i < ReorderedTasks.Count; i++) {
var reorderedTasksJson = new JavaScriptSerializer().Serialize(ReorderedTasks[i]);
var request = new RestRequest("api/task/5/{ID}/", Method.PUT);
request.AddParameter("ID", ReorderedTasks[i].ID.ToString(), ParameterType.UrlSegment);
request.AddParameter("application/json; charset=utf-8", reorderedTasksJson, ParameterType.RequestBody);
client.Execute(request);
}
I've tested out the JSON ad requestBody on POST and it works fine. I think my issue is with the first parameter I'm trying to pass ReorderedTasks[i].ID , I'm not sure if I'm handling the passing of this correctly.
I've initialised client at the beginning of my class.
Problem is the DB isn't updating and I need to isolate the problem. Is the above the correct way in dealing with my two parameters needing passed?
I suggest to put ReorderedTasks[i].ID.ToString() directly to url path.
var request = new RestRequest($"api/task/5/{ReorderedTasks[i].ID.ToString()}/", Method.PUT);
It will help to reduce possible problems with http request format.
I'll add it here, so someone will benefit from it.
If your endpoint URL have parameters like ?param=value&param2=value that you want to pass along with request RestSharp's AddParameter(string, string) won't work with PUT method (but it works just fine with GET or if endpoint doesn't have URL parameters, so it is deceiving)
Use AddParameter(string, string, ParameterType.QueryString) in order to PUT Method work correctly.
Well it depends on what does the webApi expect..
You could use Fiddler to inspect what being sent through the wire and what response You are getting (http://www.telerik.com/fiddler)
Also - here are some sample's how other users use RestSharp
How do I use PUT in RestSharp?

Converting PHP array to C# when calling API

I've looked at several related examples on SO and tried a number of methods to get this to work, but I become more confused with each attempt.
I'm trying to search through the Wordpress.org plugin repository API and get a list of plugins from the search results.
The endpoint is: http://api.wordpress.org/plugins/info/1.0/
The two important bits of data to pass are "action" and "search." The action I'm interested in at the moment is "query_plugins", and passing a search string along in the request.
This is a PHP equivalent:
$payload = array(
'action' => 'query_plugins',
'request' => serialize(
(object)array(
'search ' => 'search-phrase',
)
)
);
$body = wp_remote_post( 'http://api.wordpress.org/plugins/info/1.0/', array( 'body' => $payload) );
The only real documentation I've been able to find is from this blog post (which is where I got the above sample code): https://dd32.id.au/projects/wordpressorg-plugin-information-api-docs/
I'm using RestSharp to build the request, with code along these lines:
var client = new RestClient("http://api.wordpress.org/");
var request = new RestRequest("plugins/info/1.0", Method.POST);
request.AddParameter("XXX", "XXX");
var response = client.Execute(request);
var content = response.Content;
the "request.AddParameter("XXX", "XXX"); above is where I'm stuck. I need to build the PHP array equivalent in C# (and serialize it properly?) so that the API will accept the request. I've tried several variants and combinations, from everything as primitive as:
request.AddParameter("action", "query_plugins");
request.AddParameter("search", "keyword");
// and variants such as request.AddParameter("request", "[{ search: keyword }]);
Which I knew wouldn't work (but took a stab with anyway), to using a Dictionary() with the action and search parameters, and attempting to serialize it in several ways (most recent involved JsonConvert.SerializeObject).
At this point I don't know which tree I should be barking up, I have a feeling I'm not even in the right vicinity. I'm not even sure if I should be serializing to JSON, XML, or just a byte-stream (as I understand that's what the PHP serialize() method does, if I'm not mistaken), and I'm not sure the best approach to package all of the data I need to send off in the request.
This seems to work. Instead of POST, use GET
See the working sample here..
https://dotnetfiddle.net/rvL9eC
var client = new RestClient("http://api.wordpress.org/");
var request = new RestRequest("plugins/info/1.0", Method.GET);
request.AddParameter("action", "query_plugins");
request.AddParameter("search", "oauth");
var response = client.Execute(request);
var content = response.Content;

Categories

Resources