While invoking same MVC controller action method successively with different inputs noticed in the server logs during the second call still holding the input parameter values that were passed during the first call.
Below is the calling procedure in angular
var oDat = {
dob: '',
tob: '',
latlng: '',
timezone: ''
};
oDat.dob = dob.split('T')[0].split('-')[2] + '|' + dob.split('T')[0].split('-')[1] + '|' + dob.split('T')[0].split('-')[0];
oDat.tob = dob.split('T')[1].split(':')[0] + '|' + dob.split('T')[1].split(':')[1] + '|' + '0';
oDat.latlng = latlng;
oDat.timezone = tz;
//let headers = new Headers({ 'Content-Type': 'application/json; charset=utf-8' });
let headers = new HttpHeaders();
headers = headers.set('Content-Type', 'application/json; charset=utf-8');
return this.http.post(this.apiUrl9, JSON.stringify(oDat), {headers: headers}).pipe(
map(this.extractData),
catchError(this.handleError)
);
UPDATE
The issue remained same even after disable http cache
headers.append('Cache-control', 'no-cache');
headers.append('Cache-control', 'no-store');
headers.append('Expires', '0');
headers.append('Pragma', 'no-cache');
I resolved the server cache issue by setting below attribute right above the action method
[OutputCache(NoStore = true, Duration = 0)]
here is the link that helped Prevent Caching in ASP.NET MVC for specific actions using an attribute
Related
I'm trying to send an SMS via Twilio's API using an HTTP POST request that is called via server-side javascript in salesforce marketing cloud.
I can successfully send an SMS, the only problem is that accent characters (for instance ö, ü, à, è) are being omitted. So for instance if I send an SMS that should say "Dein persönlicher Rabatt", when I received the SMS, it says "Dein persnlicher Rabatt".
Here is my server-side javascript code:
`<script type="text/javascript" runat="server">
Platform.Load("core", "1");
var accountSid = [accountSid];
var authToken = [authToken];
var auth = Base64Encode(accountSid + ":" + authToken);
var phoneDE = DataExtension.Init("[Data Extension external key]");
var numbers = phoneDE.Rows.Retrieve();
var end = numbers.length;
for (var i=0; i<end; i++) {
var config = {
endpoint: "https://api.twilio.com/2010-04-01/Accounts/[accountSid]/Messages.json",
contentType: "application/x-www-form-urlencoded",
payload : "From=[phone]&To=" + numbers[i]["Phone"] + "&Body=Your cöntract is expiring today, you can sign it here: " + numbers[i]["URL"]
};
Write("Payload" + i + ": " + config.payload + " ");
try {
var httpResult = HTTP.Post(
config.endpoint,
config.contentType,
config.payload,
["Authorization"],
["Basic " + auth]
);
var result = Platform.Function.ParseJSON(httpResult.response);
Write(httpResult.StatusCode);
Write("result" + result);
} catch(error) {
Write("Error: " + Stringify(error));
}
}
</script>`
What do I need to do to ensure that my SMS includes the accent characters and that they are not omitted?
Thank you very much for your help.
Thanks for your answer Swimburger. I didn't get a chance to try it as I found another solution. However I do appreciate your feedback, your solution was the next approach I was going to try.
My solution was to modify the contentType of the POST request to include UTF-8 as the character set:
contentType: "application/x-www-form-urlencoded;charset=UTF-8"
Unfortunately, I don't have access to a Salesforce environment to try out your code, but here's a modified version of your code using node.js.
var accountSid = process.env.TWILIO_ACCOUNT_SID;
var authToken = process.env.TWILIO_AUTH_TOKEN;
var auth = Buffer.from(`${accountSid}:${authToken}`).toString('base64');
var body = new URLSearchParams();
body.append("From", "+12345678901");
body.append("To", "+12345678901");
body.append("Body", "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿĀāĂ㥹");
const request = new Request(
`https://api.twilio.com/2010-04-01/Accounts/${accountSid}/Messages.json`,
{
method: 'POST',
body: body.toString(),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Basic ${auth}`
}
}
);
fetch(request)
.then(response => response.json())
.then(jsonBody => console.log(jsonBody))
.catch((error) => {
console.error(error);
});
You need to configure the Twilio Account SID and Auth Token as env variables.
After that, running this script sends an SMS and the SMS contains all the characters.
I'm not sure if you are able to use these node.js APIs, but if you don't, this proves that the issue is caused by Salesforce's Server Side JavaScript APIs.
HTTP.Post probably removes the ö character.
If you do have access to node.js/npm packages, you could also use the Twilio helper library for Node.js.
I have created a simple webapi controller.
// POST request api to get a string base64 image, store it and returns its name.
public string Post([FromBody]string image)
{
if (image == null)
return "No image sent";
// Generating random file name using the current date and time and random text
string fileName = "image-" + DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss") + Path.ChangeExtension(
Path.GetRandomFileName(),
".jpg"
);
// If the directory does not exist create a new one
if (!Directory.Exists(#".\uploads\"))
{
DirectoryInfo DI = Directory.CreateDirectory(#".\uploads\");
}
File.WriteAllBytes(#".\uploads\" + fileName, Convert.FromBase64String(image));
return "Submitted as File: " + fileName;
}
When I send a post request through postman, it works as fine and returns the string "Submitted as File ..."
But when I try it in Angular I get the following error.
OPTIONS http://example.com/Api/Image/Index 405 (Method Not Allowed)
My angular service:
getResult(base64image) {
//Where base64image is a string.
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post('http://example.com/Api/Image/Index', base64image, options)
.map(res => res);
}
I know that it has something to with cors. But it is just a simple api.
I have successfully done this in the past for other services, however with box.com I get an error and I've tried everything I could think off and that others have suggested here.
I'm using .NET C#;
string postdata = "";
postdata += "client_id=" + HttpUtility.UrlEncode(client_id) + "&";
postdata += "client_secret=" + HttpUtility.UrlEncode(client_secret) + "&";
postdata += "refresh_token=" + HttpUtility.UrlEncode(refreshToken) + "&";
postdata += "redirect_uri=" + HttpUtility.UrlEncode(_redirectUri) + "&";
postdata += "grant_type=refresh_token";
var json = PostResponse(new Uri(#"https://www.box.com/api/oauth2/token"), postdata);
I've tried both with and without urlencoding of the values. Normally urlencoding is not needed in my experience.
I've also tried different order of parameters.
private string PostResponse(Uri uri, string postdata)
{
var bytes = Encoding.UTF8.GetBytes(postdata);
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = WebRequestMethods.Http.Post;
request.ContentType = "application/x-www-form-urlencoded; charset=utf-8";
request.ContentLength = bytes.Length;
Stream OutputStream = request.GetRequestStream();
OutputStream.Write(bytes, 0, bytes.Length);
var response = request.GetResponse();
var reader = new StreamReader(response.GetResponseStream());
return reader.ReadToEnd();
}
This code fails with error 400 (bad request). Similar code works fine with for example Google Drive.
Can anyone spot what I'm doing wrong with box.com? Thanks!
Got it working using box_device_id and box_device_name (indirectly part of my problem) plus examining the response in details which showed that a json error message was returned stating that the refresh token had expired. Turns out that Box expires refresh tokens when using them, issuing a new one. This is different from the other cloud drives I've integrated with.
I'm trying to use CORS against the Youtube API from a single page app. The point is to avoid a full page reload (like http://gdata-samples.googlecode.com/svn/trunk/gdata/youtube_upload_cors.html is doing). There are generally two ways this can be done:
Using a hidden iframe
or
using XMLHttpRequest with FormData
The latter is most elegant, but not supported in some inferior browsers. I'm in the lucky position that I may ignore those browsers.
Now I wrote the following code:
var fd = new FormData();
fd.append('token', token);
fd.append('file', element.files[0]);
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", uploadProgress, false);
xhr.addEventListener("load", uploadComplete, false);
xhr.addEventListener("error", uploadError, false);
xhr.addEventListener("abort", uploadAbort, false);
xhr.open("POST", $scope.uploadData.uploadUrl + '?nexturl=' + $location.absUrl());
xhr.send(fd);
This works (as in, it uploads the whole file, whilst emitting progress events happily), but at the end it errors out. I'm not sure what I'm doing wrong, but I'd really love to see a sample using this strategy instead of the full page refresh. Especially dealing with the response and the id in there I am very curious about.
Have you got something like this working?
It's possible by using Direct Uploading API v2 and FormData + XHR2. Something like:
var DEV_KEY = '<here application key: you can find at https://code.google.com/apis/youtube/dashboard/gwt/index.html>';
var ACCESS_TOKEN = '<here oAuth2 token>';
var TOKEN_TYPE = 'Bearer ';
// Helper method to set up all the required headers for making authorized calls to the YouTube API.
function generateYouTubeApiHeaders() {
return {
Authorization: TOKEN_TYPE + ACCESS_TOKEN,
'GData-Version': 2,
'X-GData-Key': 'key=' + DEV_KEY,
'X-GData-Client': 'App',
'Slug': Math.random().toString()
};
}
// Helper method to set up XML request for the video.
function generateXmlRequest(title, description, category, keywords) {
return '<?xml version="1.0"?> <entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007"> <media:group> <media:title type="plain">' + title + '</media:title> <media:description type="plain">' + description + '</media:description> <media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">' + category + '</media:category> <media:keywords>' + keywords + '</media:keywords></media:group> </entry>';
}
// Create XHR and add event listeners
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", uploadProgress, false);
xhr.addEventListener("load", uploadComplete, false);
xhr.addEventListener("error", uploadError, false);
xhr.addEventListener("abort", uploadAbort, false);
// Specify POST target
xhr.open("POST", 'https://uploads.gdata.youtube.com/feeds/api/users/default/uploads');
// Prepare form data
var fd = new FormData();
// The order of attachments is absolutely important
fd.append('xmlrequest', generateXmlRequest('Test', 'Video', 'Autos', 'dsdfsdf, sdsdf'));
fd.append('video', document.forms.uploadNewVideoForm.file.files[0]);
// Add authentication headers
var headers = generateYouTubeApiHeaders();
for(var header in headers) {
xhr.setRequestHeader(header, headers[header]);
}
// Send request
xhr.send(fd);
I'm trying to redirect the url of my app in node.js in this way:
// response comes from the http server
response.statusCode = 302;
response.setHeader("Location", "/page");
response.end();
But the current page is mixed with the new one, it looks strange :| My solution looked totally logical, I don't really know why this happens, but if I reload the page after the redirection it works.
Anyway what's the proper way to do HTTP redirects in node?
Looks like express does it pretty much the way you have. From what I can see the differences are that they push some body content and use an absolute url.
See the express response.redirect method:
https://github.com/visionmedia/express/blob/master/lib/response.js#L335
// Support text/{plain,html} by default
if (req.accepts('html')) {
body = '<p>' + http.STATUS_CODES[status] + '. Redirecting to ' + url + '</p>';
this.header('Content-Type', 'text/html');
} else {
body = http.STATUS_CODES[status] + '. Redirecting to ' + url;
this.header('Content-Type', 'text/plain');
}
// Respond
this.statusCode = status;
this.header('Location', url);
this.end(body);
};
server = http.createServer(
function(req, res)
{
url ="http://www.google.com";
body = "Goodbye cruel localhost";
res.writeHead(301, {
'Location': url,
'Content-Length': body.length,
'Content-Type': 'text/plain' });
res.end(body);
});
Yes it should be full url in setHeader.
res.statusCode = 302;
res.setHeader('Location', 'http://' + req.headers['host'] + ('/' !== req.url)? ( '/' + req.url) : '');
res.end();
What happens if you change it to 307 instead?
This issue may also depend on the type of request you are handling. A POST request cannot be redirected using the header. For example, a first-time visitor from to your app in FB will most-likely be coming via a "signed request" POST and therefore a redirect will not work.