I'm trying to write a plugin for TFS 2015 (its important). I read a couple of manuals. the examples all turns out simply, but it is more difficult with a real plugin. my problem: i cant send any get/post request from my tfs server to same server. I always get the same response: 401 Unauthorized. I looked at examples that sending Ajax requests (https://github.com/ALM-Rangers/Work-Item-Details-Widget-Extension/blob/master/src/scripts/menu.js) and add auth token to request, but i get same error 401.
my code:
VSS.require(["VSS/Authentication/Services"], function(Services) {
var authTokenManager = Services.authTokenManager;
VSS.getAccessToken().then(function(token) {
var header = authTokenManager.getAuthorizationHeader(token);
$.ajaxSetup({
headers: { 'Authorization': header }
});
$.ajax({
url: "http://myTFSServ:8080/tfs/_api/_common/GetCollectionJumpList?__v=5&navigationContextPackage=%7B%22Action%22%3A%22index%22%2C%22Area%22%3A%22%22%2C%22Level%22%3A8%2C%22Controller%22%3A%22workItems%22%7D&selectedHostId=6e60eeec-39b3-4902-a864-172cd27dea91&api-version=3.0-preview.2",
type: "GET",
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function(c) {
debugger;
// do something...;
},
error: function(e) {
debugger;
var error = e;
}
});
});
});
how can i send any valid get/post request from my tfs server to same server??
Related
I am trying to add records to CRM using Javascript but getting:
401 Unauthorized Error.
My question is how to get the token and use it inside the JavaScript function.
$(document).ready(function() {
$("#Save").click(function() {
var ProductDetails = new Object();
ProductDetails.ProductName = $("#txt_productName").val();
ProductDetails.ProductDetail = $("#txt_desc").val();
$.ajax({
url: "https://mycrm.dynamics.com/api/data/v9.1/Products",
type: "Post",
dataType: 'JSON',
data: ProductDetails,
contentType: 'application/x-www-form-urlencoded',
success: function(data) {
alert('Updated Successfully');
},
error: function(request, status, error) {
alert(request.status);
}
});
});
});
You need add Authorization information in Http Header. Here is an example if you use JWT.
$(document).ready(function() {
$("#Save").click(function() {
var ProductDetails = new Object();
ProductDetails.ProductName = $("#txt_productName").val();
ProductDetails.ProductDetail = $("#txt_desc").val();
$.ajax({
url: "https://mycrm.dynamics.com/api/data/v9.1/Products",
type: "Post",
headers: {
'Accept':'application/json',
'Content-Type':'application/json',
'Authorization':'Bearer your token here'
},
dataType: 'JSON',
data: ProductDetails,
contentType: 'application/x-www-form-urlencoded',
success: function(data) {
alert('Updated Successfully');
},
error: function(request, status, error) {
alert(request.status);
}
});
});
});
You have to add a header with the bearer token like this:
$.ajax({
(...)
headers: {
"Authorization": "Bearer " + token
},
(...)
In order to get a token you have to register an application in Azure Active Directory first, in the same tenant as your Dynamics 365 instance. Check this link if you need a thorough step by step guide to do it.
After registering you application in AAD you also have to add some code to do the authentication with Azure and getting the token. ADAL.js does this job for you, but keep in mind that it prompts the user to manually add his username and password in a office 365 popup. This is called interactive authentication and as far as I know it can't be avoided.
For a full HTML + JS working example click here.
My question is very simple and I thought creating this program would only take a couple hours. However now I have been working on it all day trying to figure out what I could be doing wrong.
All I am trying to do is post messages to slack using their postMessage api. I have been able to send messages succesfully using slacks testing methods.
This is the url that is outputted by the test
https://slack.com/api/chat.postMessage?token=xoxp-xxxxxx-xxxxxxxx-xxxxxxxx-xxxxxxxxxxx&channel=XXXXXXXX&text=Just%20need%20the%20url&as_user=jheuman&pretty=1
I then decided to try it out locally using this html file served from my file system
<!DOCTYPE html>
<html>
<head>
<title>Testing Slack API</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<button onClick="test()">Test</button>
<button onClick="test2()">Authorization Test</button>
<script>
function test() {
var apiUrl = "https://slack.com/api/chat.postMessage";
var token = "xoxp-xxxxx...";//my token has been omitted for security;
var channel = "#general";
var text = "Testing slack api";
var user = "jheuman";
var actualToken = "Bearer " + token;
$.ajax({
headers: {
'Authorization':actualToken,
'Content-Type':'application/json'
},
data: JSON.stringify({
"channel": channel,
"text": text,
"as_user": user
}),
dataType: 'json',
processData: false,
type: 'POST',
url: apiUrl
})
.done(function(data) {
console.log(JSON.stringify(data));
})
.fail(function(response) {
console.log(JSON.stringify(response));
});
};
function test2() {
var apiUrl = "https://slack.com/api/auth.test";
var token = "xoxp-xxxxx..."; //my token has been omitted for security
var channel = "#general";
var text = "Testing slack api";
var user = "jheuman";
var actualToken = "Bearer" + token;
$.ajax({
headers: {
'Authorization':actualToken
},
type: 'POST',
url: apiUrl,
})
.done(function(data) {
console.log(JSON.stringify(data));
})
.fail(function(response) {
console.log(JSON.stringify(response));
});
};
</script>
But when I click either button I get the following error:
Failed to load https://slack.com/api/chat.postMessage: Request header field
Authorization is not allowed by Access-Control-Allow-Headers in preflight
response.
So per a friends Suggestion I tried it out on a server. I used Web Server For Chrome to serve it up on port 8887. First without setting cors headers and then with setting cors headers. Both to no avail. I received the same error.
As you can see I also tried the auth.test call but I receive the same error.
Slack specifically states that they prefer an authorization header and that the api can handle json data.
Other things I have tried:
Having no header field with token in data:
data: JSON.stringify({
'token':actualToken,
'channel': channel,
'text': text,
'as_user': user
}),
dataType: 'json',
processData: false,
type: 'POST',
url: apiUrl
Errors received:
{"ok":false,"error":"invalid_form_data"}
Having no header field with token in data without 'Bearer':
data: JSON.stringify({
'token':token,
'channel': channel,
'text': text,
'as_user': user
}),
dataType: 'json',
processData: false,
type: 'POST',
url: apiUrl
Errors received:
{"ok":false,"error":"invalid_form_data"}
Things I have looked into but don't think will effect outcome
The type of token
So how do I get this post request to work?
I am not set on jquery or ajax, it is just what I have used in the past so if you have a different request library to use I'm all ears.
If you need more information I will try to give it to you
Since configuring CORS correctly for sending data with content-type application/json can be tricky, I would suggest to send the request as application/x-www-form-urlencoded which is the default for AJAX.
Example:
var apiUrl = "https://slack.com/api/chat.postMessage";
var token = MY_TOKEN;
var channel = "general";
var text = "Testing slack api";
var user = "jheuman";
$.ajax({
data: {
"token": token,
"channel": channel,
"text": text,
"as_user": user
},
dataType: 'text',
type: 'POST',
url: apiUrl,
error: function(xhr,status,error){
console.log("error: " + error);
},
success: function(data) {
console.log("result: " + data);
}
});
In case you get CORS errors, you can add crossDomain: true
This solution is tested and works when run in a normal browser.
You need to reply to that CORS preflight with the appropriate CORS headers to make this work. One of which is indeed Access-Control-Allow-Headers. That header needs to contain the same values the Access-Control-Request-Headers header contained (or more).
https://fetch.spec.whatwg.org/#http-cors-protocol explains this setup in more detail.
headers: {
'Authorization':actualToken,
'Content-Type':'application/json',
'Access-Control-Allow-Headers':'x-requested-with'
},
I have an API setup using Django Rest Framework. It works fine when accessing via cURL or HTTPie or even the browsable API. The API has token authentication so initially you have to supply credentials which will return a token. Using HTTPie (or even curl) you would do this:
http POST http://127.0.0.1:8000/api/v1/api-token-auth/ username="user1" password="testpassword"
This would return a response e.g.:
HTTP/1.0 200 OK
Allow: POST, OPTIONS
Content-Type: application/json
Date: Sun, 03 Sep 2017 16:57:38 GMT
Server: WSGIServer/0.2 CPython/3.6.1
X-Frame-Options: SAMEORIGIN
{
"token": "fgfdgfdgfdgfdgd45345345lkjlj"
}
You would then take the token and perform a GET/PUSH/etc like so:
http --json POST http://127.0.0.1:8000/api/v1/test/ test_text="Testing" 'Authorization: Token fgfdgfdgfdgfdgd45345345lkjlj'
I have been Google searching for a while now and cannot find any clear answers as to how the above two lines would translate into Javascript? How do I (1) Pass through credentials to get a token; (2) Retrieve the Token; (3) Use the token to make a GET and PUSH request?
I agree you should use Ajax.
You need an ajax call in the very beginning of you app:
var data = {username:'user',password:'password'}
$.ajax({
type: 'POST',
data: data,
url: 'http://your_url',
success: function(res){
console.log(res)
$.ajaxSetup({
headers: {
"token": res.token
}
});
},
error: function(error) {
callbackErr(error,self)
}
})
Haven`t tested, but idea is use an Ajax call to get the token and use .ajaxSetup to save the token to a header for all following ajax requests.
The you can do this:
var data = {test_text="Testing"}
$.ajax({
type: 'POST',
data: data,
url: 'http://127.0.0.1:8000/api/v1/test/',
success: function(res){
console.log(res) //answer of api call.
});
},
error: function(error) {
callbackErr(error,self)
}
})
Or this:
$.ajax({
type: 'GET',
url: 'http://127.0.0.1:8000/api/v1/ANOTHER_TES/',
success: function(res){
console.log(res) //answer of api call.
});
},
error: function(error) {
callbackErr(error,self)
}
})
Change type parameter of the call to change your request.
See #Tico's answer.
How do I (1) Pass through credentials to get a token; (2) Retrieve the Token; (3) Use the token to make a GET and PUSH request?
$.ajax({
type: 'POST',
data: {
username: "user1",
password: "testpassword"
},
url: 'http://127.0.0.1:8000/api/v1/api-token-auth/',
success: function(res){
$.ajaxSetup({
headers: {
"token": res.token
}});
$.ajax({
type: 'POST',
data: {
test_text: "Testing"
},
url: 'http://127.0.0.1:8000/api/v1/test/',
success: function(res){
alert(res);
}});
}
});
as post, get or any other url calls are asynchronous calls. So in order to maintain the program flow and make the post request you need to use promise feature of js, which will make your post call synchronous.
js promise description
var data = {username:'user',password:'password'}
$.ajax({
type: 'POST',
data: data,
url: 'http://your_url',
success: function(res){
console.log(res)
$.ajaxSetup({
headers: {
"token": res.token
}
});
},
error: function(error) {
callbackErr(error,self)
}
})
this code will work fine if you use this at the starting of your program, but this is asynchronous, to make it synchronous with your program you need to use promise.
And for the third part of your question you need to do this...
$.ajax({
type: 'GET',
url: 'http://your_url' + "/token=" + your_token,
success: function(res){
console.log(res)
},
error: function(error) {
callbackErr(error,self)
}
})
I am trying to detect the user's city via this website: http://www.ipaddresslocation.org/my-ip-address.php. Almost all of the free geolocation APIs I've seen so far were not very accurate. When the following code executes, I see all the information I need in the Response tab (in the Network tab in Firefox), but the success event fails and I am not able to access any of that data.
$(document).ready(function(){
getCity();
});
var parameters = {
"Content-Type": "text/html",
'Accept-Encoding': 'gzip, deflate',
};
function getCity() {
$.ajax({
type: "GET",
url: 'http://www.ipaddresslocation.org/ip-address-locator.php',
dataType: 'jsonp',
success: function(data) {
console.log("success");
},
error: function(xhr, status, error) {
console.log("ERROR");
console.log(error.message);
}
});
}
The problem with my code was that I was trying to get the server to respond when I just needed to read the HTML page in my browser. Because of the Same Origin policy, I ended up using the CORS Anywhere node.js proxy to add headers to the proxied request and then doing RegEx to get the city. This link is great at explaining how to make cross-domain requests: Loading cross domain endpoint with jQuery AJAX .
$(document).ready(function() {
$.ajaxPrefilter(function(options) {
if (options.crossDomain && jQuery.support.cors) {
var http = (window.location.protocol === 'http:' ? 'http:' : 'https:');
options.url = http + '//cors-anywhere.herokuapp.com/' + options.url;
}
});
$.get(
'http://www.ipaddresslocation.org/ip-address-locator.php',
function(response) {
//regex to get the desired info
});
});
This happens when third party APIs haven't set things up developer-friendly. You can use the complete callback instead of the success callback and then access the responseText property of the XHR response:
$(document).ready(function(){
getCity();
});
var parameters = {
"Content-Type": "text/html",
'Accept-Encoding': 'gzip, deflate',
};
function getCity() {
$.ajax({
type: "GET",
url: 'http://www.ipaddresslocation.org/ip-address-locator.php',
dataType: 'jsonp',
complete: function(jqXHR, txtStatus) {
var myData = jqXHR.responseText;
},
error: function(xhr, status, error) {
console.log("ERROR");
console.log(error.message);
}
});
}
http://api.jquery.com/jquery.ajax/
to get SharePoint List dataI am having an issue accessing the REST server via the CSOM. I have tried this with both the CSOM and just using jQuery. Code examples and the associated errors below. Can anyone direct me to a working example or tell me what I am doing wrong?
This code is part of a SharePoint Hosted App and the list is just a list in the root web. The user has permission to access the list and the app.
CSOM Example:
Yields:
Fail! : App Web is not deployed for this app's request url http://mySharePointRootWebURL.local.
var data = new SP.RequestExecutor("http://mySharePointRootWebURL.local/");
data.executeAsync({
method: "GET",
headers: { "Accept": "application/json;odata=verbose" },
url: "http://mySharePointRootWebURL.local/_api/web/lists/getbytitle(\'MyLstName\')/items",
success: function (data) { console.log('success!'); },
error: function (p1,p2,errorMessage) { console.log('Fail! :' + errorMessage); }
});
I can see that this example is not hitting the root web at all (from the app / app web).
jQuery Example
Yields:
Resource interpreted as Script but transferred with MIME type text/plain: "http://mySharePointRootWebURL.local/_api/web/lists/getbytitle(\'MyLstName\')/items&…Query19104068602353800088_1379462071044&alt=json-in-script&_=1379462071045". jquery.js:9597
Uncaught SyntaxError: Unexpected token < items:1
fail! : Error: jQuery19104068602353800088_1379462071044 was not called
$.ajax({
url: "http://mySharePointRootWebURL.local/_api/web/lists/getbytitle(\'MyListName\')/items",
type: "GET",
beforeSend: function(xhr){
xhr.setRequestHeader('Accept', 'application/json;odata=verbose'); },
headers: {"Accept":"application/json;odata=verbose"},
success: function(data){ console.log("success"); },
error: function errHandler(p1,p2,errMessage){ console.log("fail! : " + errMessage); },
dataType: 'jsonp',
crossDomain: true,
data: {
alt: 'json-in-script'
},
});
This is working as far as accessing the REST server and returning data, the problem is that the headers are not being added at all (verified in Fiddler). Without the headers the data comes back in XML. If that's how it has to be I will work with it, I guess, but I'd prefer to get JSON.
Your code doesn't look right. Here's code that wors with the cross-domain library
var executor = new SP.RequestExecutor(appweburl);
executor.executeAsync(
{
url:
appweburl +
"/_api/SP.AppContextSite(#target)/web/lists/getByTitle('Contacts')/items" +
"?#target='" + hostweburl + "'" +
"&$select=Id,FirstName,Title,WorkPhone,Email" +
"&$orderby=Title,FirstName",
method: "GET",
headers: { "accept": "application/json;odata=verbose" },
success: successHandler,
error: errorHandler
})