I have a REST call that is working fine when I call it from a C# app, but I can't make my JavaScript page send the content in the body of the POST. This is the REST controller. Note the JavaScript below works fine if I remove the "FromBody" attribute from the call.
[Route("api/[controller]")]
public class AuthenticateController : Controller
{
[HttpPost]
public ActionResult Post([FromBody] CredentialsModel credentialsModel)
{
var authenticationModel = new AuthenticationModel { IsSuccess = false };
if (credentialsModel != null && !string.IsNullOrEmpty(credentialsModel.Username) && !string.IsNullOrEmpty(credentialsModel.Password))
{
authenticationModel = SecurityBusinessLayer.IsValidUser(credentialsModel.Username, credentialsModel.Password);
}
var json = JsonConvert.SerializeObject(authenticationModel, new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects, ReferenceLoopHandling = ReferenceLoopHandling.Serialize });
return Content(json);
}
}
This is the JavaScript using JQuery:
function authenticate(username, password)
{
//Get the authenticate api url
var uriHref = window.location.href;
var lastIndexOfSlash = uriHref.lastIndexOf('/');
var apiPath = uriHref.substring(0, lastIndexOfSlash) + "/api";
var encodedUri = encodeURI(apiPath + "/authenticate/");
var credentials = {};
credentials["Username"] = username;
credentials["Password"] = password;
//Post the username and password to the server
$.post(encodedUri, credentials, function (data)
{
//Parse the returned data (should match Adapt.Data.Generic.AuthenticationModel)
var response = JSON.parse(data);
if (response.IsSuccess)
{
//Ensure the token will expire
var expiryDate = new Date();
expiryDate = new Date(expiryDate.setTime(expiryDate.getTime() + 86400000));
//Set the auth token cookie
var cookieString = "authToken=" + response.Authtoken + "; expires=" + expiryDate.toUTCString() + ";path=/";
document.cookie = cookieString;
//Goto the xivic app page
window.location = "Index.html";
}
else
{
//Failed to log in, show error message
$("#badLoginMessage").css("visibility", "visible");
}
});
}
When you remove [FromBody, you have to post Json object instead of array]
$.ajax({
url: encodedUri,
type: 'POST',
data: {
Username: jsonString,Password:password
},
success: function (data) {
if (data.Success == true) {
}
else
{
}
},
error: function () {
},
complete: function () {
}
});
This is the working code based on #LeTungAnh, and #ibubi's code. I can't help but think that $post would still be a better method though. The reason $post was not working was that it was not sending a content type of application/json which is what ASP.NET Core requires.
function authenticate(username, password) {
//Get the authenticate api url
var uriHref = window.location.href;
var lastIndexOfSlash = uriHref.lastIndexOf('/');
var apiPath = uriHref.substring(0, lastIndexOfSlash) + "/api";
var encodedUri = encodeURI(apiPath + "/authenticate/");
var credentials = {};
credentials["Username"] = username;
credentials["Password"] = password;
var credentialsJson = JSON.stringify(credentials);
$.ajax({
url: encodedUri,
type: 'POST',
data: credentialsJson,
contentType: 'application/json',
success: function (responseJson) {
var authenticationObject = JSON.parse(responseJson)
if (authenticationObject.IsSuccess == true) {
//Ensure the token will expire
var expiryDate = new Date();
expiryDate = new Date(expiryDate.setTime(expiryDate.getTime() + 86400000));
//Set the auth token cookie
var cookieString = "authToken=" + authenticationObject.Authtoken + "; expires=" + expiryDate.toUTCString() + ";path=/";
document.cookie = cookieString;
//Goto the xivic app page
window.location = "Index.html";
}
else {
//Failed to log in, show error message
$("#badLoginMessage").css("visibility", "visible");
}
},
error: function () {
//Failed to log in, show error message
$("#badLoginMessage").css("visibility", "visible");
},
complete: function () {
}
});
}
Related
I keep running to Cannot find function for each in object error while trying to loop entries. Is there something I am not seeing?. Here the code. This code is supposed to fetch time data from a system via API do calculations and send email
function getTime() {
var range = [5323, 9626, 4998];
var user = [];
for (var i = 0; i < range.length; i++) {
var auth = 'token'
var from = '2020-01-08'
var to = '2020-01-09'
var url = 'https://api.10000ft.com/api/v1/users/' + range[i] + '/time_entries?from=' + from + '&to=' + to + '&auth=' + auth;
var options = {
method: 'get',
headers: {
Authorization: 'Bearer ' + auth
}
};
var submitted_time_entries = {};
var response = UrlFetchApp.fetch(url, options);
var response = JSON.parse(response.getContentText());
var time_entries = response.data;
time_entries.forEach(function (time_entry) {
if (time_entry.user_id in submitted_time_entries) {
submitted_time_entries[time_entry.user_id] += time_entry.hours;
} else {
submitted_time_entries[time_entry.user_id] = time_entry.hours;
}
});
submitted_time_entries.forEach(function (user_id) {
if (submitted_time_entries[user_id] < 3) {
//send mail
}
});
}
}
response.data is probably not the array you expect. The server may be returning an error or a successful response that isn't parseable as an array. To find out, print response.data to the console and confirm it's the array you expect.
Seems my API returned an object. I figured out the way around it by using Object.keys method and it worked. Here is the working code.
function getTime() {
var range = [53, 926, 8098];
var user = [];
for (var i = 0; i < range.length; i++) {
var auth = 'token';
var from = '2020-01-08'
var to = '2020-01-09'
var url = 'https://api.10000ft.com/api/v1/users/' + '449625' + '/time_entries?from=' + from + '&to=' + to + '&auth=' + auth;
var options = {
method: 'get',
headers: {
Authorization: 'Bearer ' + auth
}
};
var submitted_time_entries = {};
var response = UrlFetchApp.fetch(url, options);
var response = JSON.parse(response.getContentText());
var time_entries = response.data;
Object.keys(time_entries).forEach(function (time_entry) {
if (time_entry.user_id in submitted_time_entries) {
submitted_time_entries[time_entry.user_id] += time_entry.hours;
} else {
submitted_time_entries[time_entry.user_id] = time_entry.hours;
}
});
Object.keys(submitted_time_entries).forEach(function (user_id) {
if (submitted_time_entries[user_id] < 3) {
Logger.log(time_entry)
//send mail
}
});
}
}
i'm very new to Javascript and i just want to login into website from NodeJS request. This website need information from the first time visited to login.
Here is my code.
var cheerio = require('cheerio');
var loginLink = 'link';
var loginJar = request.jar();
var ltValue = '';
request.get({url: loginLink, jar: loginJar}, function(err, httpResponse, html)
{
var dat = cheerio.load(html);
var arr = dat('input[name="lt"]');
ltValue = arr.attr('value');
arr = dat('input[name="execution"]');
executionValue = arr.attr('value');
/*Post body*/
var loginBody = 'username=' + usn + '&password=' + pwd + '<=' + ltValue + '&execution=' + executionValue
request.post({url: loginLink, jar: loginJar, method: 'post', json: true, body: loginBody, }}, function(err, res, b)
{
if (b.indexOf('errors') != -1)
console.log("Success");
else console.log("Fail");
});
});
I have write try it in C# and it work correctly but in my NodeJs code it always return fail. I have tried everytime but i couldn't do it. Please help me with this problem.
byte[] binData = Encoding.ASCII.GetBytes(loginBody)
string loginFile = "loginInfo.txt";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("link");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = binData.Length;
request.CookieContainer = cookieContainer;
using (Stream stream = request.GetRequestStream())
{
stream.Write(binData, 0, binData.Length);
}
WebResponse response = request.GetResponse();
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
File.WriteAllText(loginFile, reader.ReadToEnd());
}
string loginData = userID + " " + password;
File.WriteAllText("login.txt", loginData);
Hi we have been using the following flow to trigger a custom Chrome logon event if the customer is known. Recently we have run into this warning.
(index):1259 [Deprecation] Passing 'PasswordCredential' objects into 'fetch(..., { credentials: ... })' is deprecated, and will be removed in M62, around October 2017. See https://www.chromestatus.com/features/5689327799500800 for more details and https://developers.google.com/web/updates/2017/06/credential-management-updates for migration suggestions.
We use the following to logon the customer.
My question is: 1) how can we mitigate/solve the above 'Deprecation' issue? And 2) is there a more native/standard method to ask for a confirmation to logon? (pref. in the users own browser language)
<script>
window.onload = function(e) {
var debug = false;
var _waitandaskagain = 1800;
var start = new Date()
var _askforconfirmation = false;
var cookie_name = "smartlock_cancel_cookie";
var smartlock_cancel_cookie = getCookie(cookie_name);
if (smartlock_cancel_cookie) {
return
} else {
navigator.credentials.get({
password: true,
}).then(function(cred) {
if (cred) {
if (cred.type == 'password') {
var form = new FormData();
cred.additionalData = form;
cred.additionalData.append("form_key", "SECRET");
var url = 'https://ourdomain.com/webcustomer/account/loginpostgoogle/';
if (_askforconfirmation && confirm('Logon to the website securely? Please Confirm')) {
fetch(url, {
method: 'POST',
credentials: cred
}).then(function(response) {
if (response.status == 202) {
if (debug) {
console.log('Login success; reloading now');
return;
}
navigator.credentials.store(cred);
window.location.reload();
}
if (debug) {
console.log('Server status: ' + response.status);
}
return;
}).catch(function(err) {
console.log('Smartlock Ajax error:' + err.message);
}).then(always, always);
} else {
expiry.setDate(start.getDate() + (_waitandaskagain));
document.cookie = cookie_name+"=true; expires=" + expiry.toGMTString() + "; path=/";
return;
}
}
} else if (typeof cred === "undefined") {
var end = new Date();
if (+end >= (+start + 100)) {
if (debug) {
console.log('Manual cancel detected - too slow');
}
expiry.setDate(start.getDate() + (_waitandaskagain));
document.cookie = cookie_name+"=true; expires=" + expiry.toGMTString() + "; path=/";
}
if (debug) {
console.log('Credentials undefined');
}
return;
}
});
}
}
1) Do not send credential object in the fetch, instead manually append to the form (or JSON), object things from the credential Object
fetch(url, {
method: 'POST',
credentials: cred // NO
}
// example with JSON
fetch(url, {
method: 'POST',
body: JSON.stringify({
pass: cred.password,
id: cred.id,
"form_key": "SECRET"
})
}
2) There is no standard in this regard, UX is completly up to you
var AUTHORIZE_URL = 'https://accounts.google.com/o/oauth2/auth'; //step 1. we can actually start directly here if that is necessary
var TOKEN_URL = 'https://accounts.google.com/o/oauth2/token'; //step 2. after we get the callback, go get token
var CLIENT_ID = ScriptProperties.getProperty('787853180530-2792spp2fgs0j7tsc2jph2ur6297tmft.apps.googleusercontent.com');
var CLIENT_SECRET = ScriptProperties.getProperty('V9mZYdRwCgCDsWDF6X2Aju0H');
//PUT YOUR URL HERE -
var REDIRECT_URL = 'https://script.google.com/macros/s/AKfycbyFabJD1uUo3NNXAVVlFVapCRnJw7dJKBmCF3X9nzhgPmxZbRM/exec';
var oauthTokenPropertyName = 'GOOGLE_OAUTH_ACCESS_TOKEN';
var oauthTokenExpiresPropertyName = 'GOOGLE_OAUTH_ACCESS_TOKEN_EXPIRES';
var refreshTokenPropertyName = 'GOOGLE_OAUTH_REFRESH_TOKEN';
function getURLForAuthorization() {
return AUTHORIZE_URL + '? response_type=code&client_id=' + CLIENT_ID + '&redirect_uri=' + REDIRECT_URL +
'&scope=https://www.googleapis.com/auth/yt-analytics.readonly&approval_prompt=force&access_type=offline&state=/profile';
}
function getAndStoreAccessToken(code) {
var parameters = {
method: 'post',
payload: 'client_id=' + CLIENT_ID + '&client_secret=' + CLIENT_SECRET + '&grant_type=authorization_code&redirect_uri=' + REDIRECT_URL + '&code=' + code
};
var response = UrlFetchApp.fetch(TOKEN_URL, parameters).getContentText();
storeOAuthValues_(response);
}
function getUrlFetchOptions() {
var token = UserProperties.getProperty(oauthTokenPropertyName);
return {
"contentType": "application/json",
"headers": {
"Authorization": "Bearer " + token,
"Accept": "application/json"
}
};
}
function attemptTokenRefresh_() {
var refreshToken = UserProperties.getProperty(refreshTokenPropertyName);
if (!refreshToken) {
Logger.log('No refresh token available to refresh with ' + refreshTokenPropertyName);
return false;
}
var requestData = {
method: 'post',
payload: {
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
refresh_token: refreshToken,
grant_type: 'refresh_token'
}
};
Logger.log('Attempting token refresh');
var response = UrlFetchApp.fetch(TOKEN_URL, requestData).getContentText();
storeOAuthValues_(response);
return true;
}
function storeOAuthValues_(response) {
var tokenResponse = JSON.parse(response);
var accessToken = tokenResponse.access_token;
// expires_in is in seconds and Date.now is ms
var endMs = Date.now() + tokenResponse.expires_in * 1000;
var refreshToken = tokenResponse.refresh_token;
//store the token for later retrieval
UserProperties.setProperty(oauthTokenPropertyName, accessToken);
if (refreshToken) { //on a refresh call we wont get a new refresh token, lets not wipe prev one out
UserProperties.setProperty(refreshTokenPropertyName, refreshToken);
}
UserProperties.setProperty(oauthTokenExpiresPropertyName, endMs);
}
function isOAuthed() {
if (hasValidToken_()) {
Logger.log('Valid oauth token found');
return true;
} else {
try {
return attemptTokenRefresh_();
} catch (e) {
Logger.log('Failed to refresh token with error: ' + e);
return false;
}
}
}
function hasValidToken_() {
if (!isTokenPresent_()) {
return false;
}
return (!isTokenExpired_());
}
function isTokenExpired_() {
var expirationTimeMs = UserProperties.getProperty(oauthTokenExpiresPropertyName);
if (!expirationTimeMs) {
return true;
}
expirationTimeMs = Number(expirationTimeMs);
var threshold = Date.now() + 30000;
return (expirationTimeMs < threshold);
}
function isTokenPresent_() {
var token = UserProperties.getProperty(oauthTokenPropertyName);
if (!token) { //if its empty or undefined
return false;
}
return true;
}
google developer https://console.developers.google.com/project -> project name select -> APIs&Auth -> credential
enter mail adres
I have one image attached with each record in my entity. I want to show these images in the records in a web resource just like a record picture. I am using the following code:
function GetData(){
// var base64image = document.getElementById('image').src.substr(document.getElementById('image').src.indexOf('base64')+7);
var recordId = window.parent.Xrm.Page.data.entity.getId();
var serverUrl = Xrm.Page.context.getServerUrl().toString();
var ODATA_ENDPOINT = "XRMServices/2011/OrganizationData.svc";
var objAnnotation = new Object();
var ODATA_EntityCollection = "/AnnotationSet";
var temp= "/AnnotationSet?$select=DocumentBody,FileName,MimeType,ObjectId&$filter=ObjectId/Id eq guid'" + recordId + "'";
var result =serverUrl + ODATA_ENDPOINT + ODATA_EntityCollection + temp;
// Parse the entity object into JSON
var jsonEntity = window.JSON.stringify(objAnnotation);
// Asynchronous AJAX function to Create a CRM record using OData
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
datatype: "json",
url: result ,
//data: jsonEntity,
async: false,
beforeSend: function (XMLHttpRequest) {
XMLHttpRequest.setRequestHeader("Accept", "application/json");
},
success: function(status){
alert("success paa jee!!");
},
error: function (xmlHttpRequest, textStatus, errorThrown) {
alert("Status: " + textStatus + "; ErrorThrown: " + errorThrown);
}
});
}
</script>
But I get an error $ is undefined when I reach the Ajax part. Basically every record has one Image in its notes attached to the entity's record and I want to show this image in a web resource as a record picture.
I am open to suggestions if there is a better/another way.
EDIT: I have edited the code and have updated the ODATA url.
In CRM 2011, I have used two Custom Aspx pages to show, the attached image.
Page 1: AccountImage.aspx have the following Control:
<asp:Image ID="IMG_Logo" runat="server" Height="50px" ImageUrl="AccountImageForm.aspx" Visible="false" />
In AccountImage.aspx On PageLoad
if (Request.QueryString["id"] != null)
{
Id = new Guid(Request.QueryString["id"]);
if (!IsPostBack)
{
ResetCache();
}
ShowImages();
}
The ShowImages() functions has below code:
function ShowImages()
{
IMG_Logo.Visible = false;
QueryExpression query = new QueryExpression("annotation");
query.Criteria.AddCondition("objectid", ConditionOperator.Equal, Id);
query.Criteria.AddCondition("mimetype", ConditionOperator.In, new string[] { "image/x-png", "image/pjpeg", "image/png", "image/jpeg" });
query.Criteria.AddCondition("subject", ConditionOperator.NotEqual, "membershipcardthumbnail");
query.Criteria.AddCondition("subject", ConditionOperator.NotEqual, "membershipcardimage");
query.ColumnSet = new ColumnSet(true);
EntityCollection AllLogoImageNotes = Common.Common.RetrieveMultiple(query);
if (AllLogoImageNotes.Entities.Count > 0)
{
foreach (Entity Note in AllLogoImageNotes.Entities)
{
if (Note.Attributes.Contains("subject") && Note.Attributes.Contains("documentbody"))
{
if (Note["subject"].ToString().ToLower() == "accountlogoimage")
{
HttpRuntime.Cache.Remove("AccountLogoImage");
HttpRuntime.Cache.Remove("AccountLogoImageType");
HttpRuntime.Cache.Add("AccountLogoImage", Convert.FromBase64String(Note["documentbody"].ToString()), null, DateTime.Now.AddMinutes(5), TimeSpan.Zero, CacheItemPriority.Normal, null);
HttpRuntime.Cache.Add("AccountLogoImageType", Note["mimetype"].ToString(), null, DateTime.Now.AddMinutes(5), TimeSpan.Zero, CacheItemPriority.Normal, null);
IMG_Logo.ImageUrl = "AccountImageForm.aspx" + "?time=" + DateTime.Now.ToString();
IMG_Logo.Visible = true;
}
}
}
}
}
As you can see, the line below:
IMG_Logo.ImageUrl = "AccountImageForm.aspx" + "?time=" + DateTime.Now.ToString();
In AccountImageForm.aspx write below code:
protected void Page_Load(object sender, EventArgs e)
{
Response.Clear();
if (HttpRuntime.Cache["AccountLogoImage"] != null)
{
Response.ContentType = HttpRuntime.Cache["AccountLogoImageType"].ToString();
byte[] data = (byte[])HttpRuntime.Cache["AccountLogoImage"];
Response.BinaryWrite(data);
}
}
In ODATA you can do the following:
retrieveImages("/AnnotationSet?$select=DocumentBody,MimeType&$filter=ObjectId/Id eq guid'" + Xrm.Page.data.entity.getId()+ "'", function (JsonObject) {
if (JsonObject != null) {
// debugger;
var ByteString= JsonObject[0].DocumentBody;
var MimeType = JsonObject[0].MimeType
}
function retrieveImages(query, SuccessFunc) {
var retrieveRecordsReq = new XMLHttpRequest();
var ODataPath = Xrm.Page.context.getServerUrl() + "/xrmservices/2011/OrganizationData.svc";
retrieveRecordsReq.open('GET', ODataPath + query, false);
retrieveRecordsReq.setRequestHeader("Accept", "application/json");
retrieveRecordsReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");
retrieveRecordsReq.onreadystatechange = function () {
if (this.readyState == 4 /* complete */) {
if (this.status == 200) {
this.onreadystatechange = null; //avoids memory leaks
var data = JSON.parse(this.responseText, SDK.REST._dateReviver);
if (data && data.d && data.d.results)
SuccessFunc(JSON.parse(this.responseText, SDK.REST._dateReviver).d.results);
}
else {
alert(SDK.REST._errorHandler(this));
}
}
};
retrieveRecordsReq.send();
}