hello, is there a way for consuming a Rest service in an app for windows 8.1 using WinJS? - rest

hello I'm trying to consume a REST service in an app for windows 8.1, I'm so gratefull if you can give me more information related about this topic, thanks !!

You could use the XMLHttpRequest object. But, since you are using WinsJS, the WinJS.xhr function would be more convenient.
Here's an example on how to use it:
(function () {
"use strict";
var app = WinJS.Application;
app.onactivated = function (args) {
// Change RSS feed URL as you need to.
var resDiv = document.getElementById("divResult"),
rssURL = "http://blogs.windows.com/windows/b/appbuilder/rss.aspx";
// Call WinJS.xhr to retrieve an XML feed from the Web.
WinJS.xhr({
url: rssURL,
responseType: "document"
}).done(
// When the result has completed, check the status.
function completed(result) {
if (result.status === 200) {
// Get the XML document from the results.
var xmlDocument = result.responseXML,
title = xmlDocument.getElementsByTagName('title')[0];
// Update the HTML in the app.
resDiv.style.backgroundColor = "lightGreen";
resDiv.innerText = "Downloaded RSS feed from the " + title.textContent + " blog.";
}
});
};
app.start();
})();

Related

Javascript injection goes wrong

In our Android project (download manager) we need to show built-in web browser so we able to catch downloads there with the all data (headers, cookies, post data) so we can handle them properly.
Unfortunately, WebView control we use does not provide any way to access POST data of the requests it makes.
So we use a hacky way to get this data. We inject this javascript code in the each html code the browser loads:
<script language="JavaScript">
HTMLFormElement.prototype._submit = HTMLFormElement.prototype.submit;
HTMLFormElement.prototype.submit = formSubmitMonitor;
window.addEventListener('submit', function(e) {
formSubmitMonitor(e);
}, true);
function formSubmitMonitor(e) {
var frm = e ? e.target : this;
formSubmitMonitor_onsubmit(frm);
frm._submit();
}
function formSubmitMonitor_onsubmit(f) {
var data = "";
for (i = 0; i < f.elements.length; i++) {
var name = f.elements[i].name;
var value = f.elements[i].value;
//var type = f.elements[i].type;
if (name)
{
if (data !== "")
data += '&';
data += encodeURIComponent(name) + '=' + encodeURIComponent(value);
}
}
postDataMonitor.onBeforeSendPostData(
f.attributes['method'] === undefined ? null : f.attributes['method'].nodeValue,
new URL(f.action, document.baseURI).href,
data,
f.attributes['enctype'] === undefined ? null : f.attributes['enctype'].nodeValue);
}
XMLHttpRequest.prototype.origOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
// these will be the key to retrieve the payload
this.recordedMethod = method;
this.recordedUrl = url;
this.origOpen(method, url, async, user, password);
};
XMLHttpRequest.prototype.origSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(body) {
if (body)
{
postDataMonitor.onBeforeSendPostData(
this.recordedMethod,
this.recordedUrl,
body,
null);
}
this.origSend(body);
};
const origFetch = window.fetch;
window.fetch = function()
{
postDataMonitor.onBeforeSendPostData(
"POST",
"test",
"TEST",
null);
return origFetch.apply(this, arguments);
}
</script>
Generally, it works fine.
But in Google Mail web interface, it's not working for some unknown reason. E.g. when the user enters his login name and presses Next. I thought it's using Fetch API, so I've added interception for it too. But this did not help. Please note, that we do not need to intercept the user credentials, but we need to be able to intercept all, or nothing. Unfortunately, this is the way the whole system works there...
Addition #1.
I've found another way: don't override shouldInterceptRequest, but override onPageStarted instead and call evaluateJavascript there. That way it works even on Google Mail web site! But why the first method is not working then? We break HTML code somehow?

.Net Core: Validate Anti Forgery Token with Ionic front end

I have looked all over and have found similar solutions, but nothing that matches exactly what I'm working on.
We have a .net core MVC website with an API Controller for handling requests from an ionic mobile app which we are also developing.
In most cases, adding [ValidateAntiForgeryToken] to the API controller actions works. I have gone through the process of generating the token, passing it to Ionic, and storing it in the request headers for validation.
Here is the code I am using to fetch and store the token:
static XSRF_TOKEN_KEY: string = "X-XSRF-TOKEN";
static XSRF_TOKEN_NAME_KEY: string = "X-XSRF-TOKEN-NAME";
constructor(){}
static getXsrfToken(http: HTTP) : {tokenName: string, token: string} {
let tokenName: string = window.sessionStorage.getItem(ValidationManager.XSRF_TOKEN_NAME_KEY);
let token: string = window.sessionStorage.getItem(ValidationManager.XSRF_TOKEN_KEY);
if(!tokenName || !token){
this.fetchXsrfToken(http);
tokenName= window.sessionStorage.getItem(ValidationManager.XSRF_TOKEN_NAME_KEY);
token = window.sessionStorage.getItem(ValidationManager.XSRF_TOKEN_KEY);
}
return {
tokenName: tokenName,
token: token
};
}
private static setXsrfToken({ token, tokenName }: { token: string, tokenName: string }) {
window.sessionStorage.setItem(ValidationManager.XSRF_TOKEN_KEY, token);
window.sessionStorage.setItem(ValidationManager.XSRF_TOKEN_NAME_KEY, tokenName);
}
private static fetchXsrfToken(http: HTTP) {
let token: string = window.sessionStorage.getItem(ValidationManager.XSRF_TOKEN_KEY);
let tokenName: string = window.sessionStorage.getItem(ValidationManager.XSRF_TOKEN_NAME_KEY);
if (!token || !tokenName) {
let apiUrl: string = AppConfig.apiUrl + "/GetAntiforgeryToken";
http.get(apiUrl, {}, {})
.then(r => this.setXsrfToken(JSON.parse(r.data)))
.catch(r => console.error("Could not fetch XSRFTOKEN", r));
} else {
this.setXsrfToken({ token: token, tokenName: tokenName });
}
}
Here is the action in my controller that serves anti forgery tokens:
[HttpGet]
public override IActionResult GetAntiforgeryToken()
{
var tokens = _antiforgery.GetAndStoreTokens(HttpContext);
return new ObjectResult(new
{
token = tokens.RequestToken,
tokenName = tokens.HeaderName
});
}
I set the headers of the http plugin by calling this function from the view's associated typescript file:
initializeHttp() {
let token = ValidationManager.getXsrfToken(this.http);
this.http.setHeader(token.tokenName, token.token);
console.log("Http Initialized: ", token);
}
then any request I make with the http plugin is validated properly in the controller's action:
this.http.post(apiUrl, {}, {}).then(response => {
that.navCtrl.setRoot(HomePage);
});
Up to this point, everything works great. The problem arises when I try to use XmlHttpRequest to for a POST instead of the built-in http plugin:
let file = {
name: e.srcElement.files[0].name,
file: e.srcElement.files[0],
};
let formData: FormData = new FormData();
formData.append('file', file.file);
let xhr: XMLHttpRequest = new XMLHttpRequest();
xhr.open('POST', apiUrl, true);
console.log("setting request header: ", tokenVal); //verify that tokenVal is correct
xhr.setRequestHeader("X-XSRF-TOKEN", tokenVal);
xhr.send(formData);
If I remove the [ValidateAntiForgeryToken] attribute from the controller's action, the file is posted properly. However, nothing I have tried has worked with the attribute being included.
I believe the issue has something to do with the validation tokens being added to a cookie automatically by Ionic, and the cookie is passed along with the request from the http plugin. However, XMLHttpRequest does not pass the cookie along (and is unable to do so?).
I have read up on the subject quite a bit over the past few days but I admit that this validation is still mostly a black box to me. Is there a way to validate the request in my action using only the token which is passed up in the header?
The reason I am running into this problem is that I need to upload a file, which I was unable to do using the http plugin. There are solutions for uploading images using Ionic's file-transfer plugin, but it has been deprecated and the release notes suggest using XmlHttpRequest instead.
Other things I have tried:
I have found solutions for .net standard which use System.Web.Helpers.AntiForgery for custom validation on the server, but this namespace is not included in .net core and I could not find an equivalent.
I tried many different ways to post the file using the http plugin (since it has no issues validating the antiForgery token). Everything I tried resulted in the action being hit but the file being posted was always null. A solution which uploads a file using the http plugin would also be acceptable.
Why is it that I was able to spend two full days on this problem, but as soon as I post a question about it, I find the answer? Sometimes I think the internet gods are just messing with me.
As it turns out, the native http plugin has an uploadFile() function that I never saw mentioned anywhere else. Here's what the solution does:
Use the fileChooser plugin to select a file from the phone's storage
Use the filePath plugin to resolve the native filesystem path of the image.
Use http.uploadFile() instead of http.post()
This works because as mentioned above, I was able to properly set the validation token in the http plugin's header to be accepted by the controller.
And here is the code:
let apiUrl: string = AppConfig.apiUrl + "/UploadImage/";
this.fileChooser.open().then(
uri => {
this.filePath.resolveNativePath(uri).then(resolvedPath => {
loader.present();
this.http.uploadFile(apiUrl,{ },{ },resolvedPath, "image")
.then(result => {
loader.dismiss();
toastOptions.message = "File uploaded successfully!";
let toast = this.toastCtrl.create(toastOptions);
toast.present();
let json = JSON.parse(result.data);
this.event.imageUrl = json.imgUrl;
})
.catch(err => {
console.log("error: ", err);
loader.dismiss();
toastOptions.message = "Error uploading file";
let toast = this.toastCtrl.create(toastOptions);
toast.present();
});
});
}
).catch(
e => console.log(e)
);

actions on google--unable to use app.tell to give response from JSON

I am trying to get my webhook to return a parsed JSON response from an API. I can log it on the console, but when I try to use app.tell; it gives me: TypeError: Cannot read property 'tell' of undefined. I am basically able to successfully get the data from the API, but I'm not able to use it in a response for some reason. Thanks for the help!
[Actions.API_TRY] () {
var request = http.get(url2, function (response) {
// data is streamed in chunks from the server
// so we have to handle the "data" event
var buffer = "",
data,
route;
response.on("data", function (chunk) {
buffer += chunk;
});
response.on("end", function (err) {
// finished transferring data
// dump the raw data
console.log(buffer);
console.log("\n");
data = JSON.parse(buffer);
route = data.routes[0];
// extract the distance and time
console.log("Walking Distance: " + route.legs[0].distance.text);
console.log("Time: " + route.legs[0].duration.text);
this.app.tell(route.legs[0].distance.text);
});
});
}
This looks to me to be more of a JavaScript scoping issue than anything else. The error message is telling you that app is undefined. Often in Actions, you find code like yours embedded in a function which is defined inside the intent handler which is passed the instance of your Actions app (SDK or Dialog Flow).

.net core 2.0 external login - extra profile information

I have a .net core 2.0 app and am implementing external login providers like google, twitter, and facebook. I have the requirement to get the user's display name and profile picture, and can't find any documentaion of how to achieve this in .net core 2.0.
I add the authentication like this post: https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/
Here are my twitter login and callback functions...
[HttpGet]
[Route("/api/security/login/type/socialmedia/twitter")]
public IActionResult GetTwitterLogin(string redirect_uri)
{
ClientCallback = redirect_uri;
string redirectUrl = "/api/security/login/type/socialmedia/twittercallback";
var properties = SignInManager.ConfigureExternalAuthenticationProperties("Twitter", redirectUrl);
return Challenge(properties, "Twitter");
}
[HttpGet]
[Route("/api/security/login/type/socialmedia/twittercallback")]
public async Task<HttpResponseMessage> GetTwitterCallBackAsync()
{
var info = await SignInManager.GetExternalLoginInfoAsync();
var result = await SignInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true);
if (result.Succeeded)
{
}
else
{
}
Response.StatusCode = (int)HttpStatusCode.OK;
return null;
}
It looks like you can get some items from info.Principal.Claims, but nothing for the user's display name or profile picture.
How do you get the display name or profile picture for the various login providers?
I finally figured this out...you need to add claims when you configure the authentication. These claims look at the resulting json response and pulls items from it. The pertinent lines are the ClaimActions items.
services.AddAuthentication()
.AddTwitter(twitterOptions =>
{
twitterOptions.ConsumerKey = cfg.SystemConfig["TwitterConsumerKey"];
twitterOptions.ConsumerSecret = cfg.SystemConfig["TwitterConsumerSecret"];
twitterOptions.SaveTokens = true;
twitterOptions.RetrieveUserDetails = true;
twitterOptions.ClaimActions.MapJsonKey("display-name", "name");
twitterOptions.ClaimActions.MapJsonKey("profile-image-url", "profile_image_url_https");
})
.AddFacebook(facebookOptions =>
{
facebookOptions.AppId = cfg.SystemConfig["FacebookClientId"];
facebookOptions.AppSecret = cfg.SystemConfig["FacebookClientSecret"];
facebookOptions.SaveTokens = true;
facebookOptions.ClaimActions.MapJsonKey("display-name", "name");
})
.AddGoogle(googleOptions =>
{
googleOptions.ClientId = cfg.SystemConfig["GoogleClientId"];
googleOptions.ClientSecret = cfg.SystemConfig["GoogleClientSecret"];
googleOptions.SaveTokens = true;
googleOptions.ClaimActions.MapJsonSubKey("profile-image-url", "image", "url");
googleOptions.ClaimActions.MapJsonKey("display-name", "displayName" );
});
After getting the login information in your callback using
var info = await SignInManager.GetExternalLoginInfoAsync();
If populated successfully you can query the claims and find the values
var profileImageClaim = info.Principal.Claims.Where(x => x.Type == "profile-image-url").FirstOrDefault();
Facebook images are different from google and twitter and can be found using...
var claim = info.Principal.Claims.Where(x => x.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier").FirstOrDefault();
var url = "http://graph.facebook.com/" + claim.Value + "/picture";
In ASP.NET Core 2.0, FacebookOptions uses extension methods on ClaimActions to map the profile data returned by UserInformationEndpoint.
ClaimActions.MapJsonKey(ClaimTypes.DateOfBirth, "birthday");
In the mapping above, "birthday" is a top-level property in the Facebook Graph API response that's mapped to the value represented by the claim ClaimTypes.DateOfBirth.
To grab the profile picture you would do the same thing, but since the picture in the Graph API response is a nested JSON object, you would have to use MapCustomJson()
services.AddAuthentication()
.AddFacebook(options =>
{
// ...other options omitted
options.Fields.Add("picture");
options.ClaimActions.MapCustomJson("urn:facebook:picture",
claim => (string)claim.SelectToken("picture.data.url"));
})
Here, claim is a NewtonSoft JObject that uses JPath syntax to select the nested property value and cast it to a string.
The profile picture URL will now appear in your Claims list.

Facebook C# sdk batch request method return empty data array

I am creating Facebook application which get insights for user's page for multiple metric. Ex. for "page_active_users" and "page_active_users in one batch request.
I am using Facebook C# SDK. But not able to get data from Facebook insights (GraphAPI).
I used 5 different way to get the data but not succeed. By using Graph API method in browser shows data for a page but in batch request it returns empty array of data.
//type1
var para1 = new FacebookBatchParameter(HttpMethod.Get, "MyPageId/insights/")
{
Data = new { access_token = aToken, since = "2012-01-01", metric = "page_active_users" }
};
//type2
var para2 = new FacebookBatchParameter(HttpMethod.Get, "fql/", new
{
q = new[]{
"SELECT value,end_time FROM insights WHERE object_id=MyPageId AND metric='page_active_users' AND end_time=end_time_date('2012-01-01') AND period=86400"
}
}) { Data = new { access_token = aToken } };
//type 3
var para3 = new FacebookBatchParameter().Query(
"SELECT value,end_time FROM insights WHERE object_id=MyPageId AND metric='page_active_users' AND end_time=end_time_date('2012-01-01') AND period=86400");
//type 4
var para4 = new FacebookBatchParameter
{
Path = "MyPageId/insights/",
//Parameters = new {since = "2012-01-01"},
Data = new { access_token = aToken, since = "2012-01-01", metric = "page_active_users" },
HttpMethod = HttpMethod.Get
};
//type 5
var para5 = new FacebookBatchParameter
{
Path = "MyPageId/insights/page_active_users?since=2012-01-01",
//Parameters = new {since = "2012-01-01"},
Data = new { access_token = aToken },
HttpMethod = HttpMethod.Get
};
//Executed all above type by passing it to below method one by one.But always return empty data array while data is exists on Facebook which I tested using Grap API tool.
var result = client.Batch(para1-5);
Any help appreciated.
Thanks in advanced.
Dharmendra Mistry
I found solution on my own. Hope this will help someone. Here is the solution.
///I created an enum for list of metrics that facebook is providing
public enum FacebookMatricType
{
page_active_users,
page_active_users_locale
}
//Created a list of Facebook batch request for each metric using LINQ to Object and //concatenate string using string.format method.
var batchParameters = (from FacebookMatricType matricType in Enum.GetValues(typeof (FacebookMatricType))
select new object[]
{
pPageAccessToken,"insights",matricType.ToString(),pFromDate.Date.ToString("yyyy-MM-dd"),pPageId
}
into objectParamter
select new FacebookBatchParameter
{
HttpMethod = HttpMethod.Get,
Path =
string.Format(
"https://graph.facebook.com/{0}/{1}/{2}?since={3}&access_token={4}",
objectParamter)
}).ToList();
//Once I get the list of request I execute it using facebook web client using C# SDK.
var facebookClient = new FacebookClient(pProfileAccessToken);
var results = facebookClient.Batch(batchParameters.ToArray());
//Results are ready to deserialize.
Thank you. ;)
Dharmendra Mistry