Xamarin.Auth and Google Drive API: OAuth2Authenticator not IsAuthenticated - xamarin.forms

So this is how I launch my login page:
this.OnGoogleDrive = new Command(() =>
{
var presenter = new OAuthLoginPresenter();
presenter.Login(auth);
});
And this is how I define my Authenticator:
var auth = new OAuth2Authenticator(
this.clientId,
string.Empty,
scope,
new Uri("https://accounts.google.com/o/oauth2/v2/auth"),
new Uri(redirectUrl),
new Uri("https://www.googleapis.com/oauth2/v4/token"),
isUsingNativeUI: true);
So my app opens a page where the Google login page appears and authorizes my scope. At the very end, it shows me a code that I had to copy paste. So far I thought that the page would instead make IsAutheticated true. But when I got to the method handling the Completed event, it is read as false.
Why is that? Was I using the wrong way to open the Login page?

Related

Pass combobox value from view to controller using #Html.ActionLink

I have a kendo.combobox() control on my Layout.cshtml page which is a list of projects.
#(Html.Kendo().ComboBox()
.Name("projects")
.Placeholder("select project")
.DataTextField("Text")
.DataValueField("ID")
.HtmlAttributes(new { style = "width:45%;" })
.Filter("contains")
.SelectedIndex((int)Session["ProjectNoIndex"])
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetProjectsList", "Home");
})
.ServerFiltering(true);
})
)
I have a menu as well in the Layout.cshtml which is created using #Html.ActionLinks (one sample below).
<li>#Html.ActionLink("Documents", "Search", "Document", new { projectNo = 1}, new {#id = "send"})</li>
Search action in Document controller and most other actions in the application expect the projectNo parameter (entire application works based on the selected project of the user). So, I thought of saving the selected ProjectNo in Session but if I do this then users can only work with 1 project even if they open the application in multiple tabs/windows in a single browser (sessions are shared across tabs/windows).
So, I thought of passing the selected ProjectNo using querystrings. I tried below, which worked fine except when user right clicks and open's the link in new tab. in such case, below click event does not fire.
$('#send').click(function () {
var x = $("#projects").data("kendoComboBox").selectedIndex;
var url = '#Url.Action("Search", "Document", new { projectNoIndex = "-1" })'
url = url.replace("-1", x);
this.href = url;
});
I don't want to restrict user by oncontextmenu = "return false;" option either. What are my options here?
Q1: How can I make sure I can pass the selected ProjectNo using querystring
Q2: Is there any other alternative to Session where I can persist the project information across tabs/windows which can be easily available in the entire application per user, per tab/window.

Return a parameter in Google App Script callback

The following example code successfully performs a callback to the Google App Script:
var SCRIPT_ID = "1eC5VsM2vkJXa9slM40MTKTlfARGAGyK1myMCU3AB_-Ox_jGxQaoPM8P2";
function getURL() { return getCallbackURL('testCallback'); }
function getCallbackURL(callback) {
var state = ScriptApp.newStateToken().withTimeout(3600).withMethod(callback).createToken();
return 'https://script.google.com/macros/d/'+SCRIPT_ID+'/usercallback?state='+state;
}
function doGet(e){ return HtmlService.createTemplate(" <div><p><a href='<?=getURL()?>' id='start-auth'><?=getURL()?></a></p></div>").evaluate()); }
function testCallback(e){
Logger.log('myVariable1= ' + e.parameter.myVariable1); // this doesn't work
Logger.log('myVariable2= ' + e.parameter.myVariable2); // this doesn't work
return HtmlService.createHtmlOutput('<b>Success. You can close this window. !</b>')
}
However I need to return a variable to the "testCallback" method as part of a HttpRepsonse redirect. I've tried settings a cookie and also setting a header variable in my asp.net C# application as follow:
HttpCookie cookie = new HttpCookie("myVariable1");
cookie.Value = "someValue1";
cookie.Expires = DateTime.Now.AddMinutes(1);
Response.Cookies.Add(cookie);
Response.AddHeader("myVariable2", "someValue2");
Response.Redirect(applicationCallbackUri, true);
but it's not clear whether the header or cookie variables are available to Google's callback method:
function testCallback(e){
Logger.log('myVariable1= ' + e.parameter.myVariable1);
Logger.log('myVariable2= ' + e.parameter.myVariable2);
return HtmlService.createHtmlOutput('<b>Success. You can close this window.
!</b>')
}
I've also tried using the .WithArguments method when creating the a new state token, but I'm not sure if its possible for my asp.net application to update the state object's arguments as part of the redirect/return.
I've also tried appending the variable to the Google Callback URL, e.g.
https://script.google.com/macros/d/1eC5VsM2vkJXa9slM40MTKTlfARGAGyK1myMCU3AB_-Ox_jGxQaoPM8P2?state=ADEpC8w0dL6mBVmDQHX3XcYcBP0JqQ5_etc&myVariable1=someValue1
However Google throws an "invalid state" error
The event object passed to your testCallback(e) function cannot reference HTTP headers or cookies and appending arbitrary url variables to the redirect url won't work either (the authorization server that does the redirect will omit them to ensure security).
The only valid way to send state vars is using the withArguments() method. However, your Logger.log() calls won't work b/c the calls (to the testCallback(e) function) are asynchronous and they are not tracked in the editor. Instead, try enabling StackDriver Logging from the Apps Script Editor's View menu and replace those Logger.log() calls with console.log(). Your logs should then show up under StackDriver Logging in your Google API Console for the project.

How to navigate in a Xamarin.Forms application as a specific user

My mobile application has a login page, and i want to do some thing like that:
when a user login he can navigate in all pages with his id, so he see his réservations, he can make a new reservation, he can cancel a reservation... (like sessions in a web application).
You can store user id to local storage then navigate pages with this user id
To store id in local storeage you can use application.current.properties:
Application.Current.Properties ["id"] = userId;
App.Current.SavePropertiesAsync();
And to get id from local storage:
if (Application.Current.Properties.ContainsKey("id"))
{
var id = Application.Current.Properties ["id"] as int;
}
In Xamarin.Forms you can navigate to the specific page like this:
await Navigation.PushAsync(new YourSpecificPage
{
BindingContext = the view model of your navigating page
});
OR, you can create your page object and can navigate towards it as :
var newPage = newPage();
await Navigation.PushAsync(newPage);

Activity Indicator is not visible on xaml page in xamarin.forms?

I have an activity indicator on xaml page. Initially its IsVisible property is false. I have a button on page. When user click on button it calls a web service to get data. I change the value of IsVisible property to true before calling the service so that activity indicator starts to display on page and after successful calling of service I change its value to again false so that it doesn't show any more on page.
But it is not working. I know the actual problem. When we call the web service the UI thread gets block and it doesn't show the activity indicator.
How I can enable the UI thread when web service gets called so that activity indicator can show on page until we get the data?
Try making your webservice call into an async and await it.
Depending on how you've structured things you may have to use a TaskCompletionSource as the following example demonstrates.
In this example when the button is clicked, the button is made invisible, and the ActivityIndicator is set to IsRunning=True to show it.
It then executes your long running task / webservice in the function ExecuteSomeLongTask using a TaskCompletionSource.
The reason for this is that in our button click code, we have the final lines:-
objActivityIndicator1.IsRunning = false;
objButton1.IsVisible = true;
That stop the ActivityIndicator from running and showing, and also set the button back to a visible state.
If we did not use a TaskCompletionSource these lines would execute immediately after calling the ExecuteSomeLongTask if it was a normal async method / function, and would result in the ActivityIndicator not running and the button still being visible.
Example:-
Grid objGrid = new Grid()
{
};
ActivityIndicator objActivityIndicator1 = new ActivityIndicator();
objGrid.Children.Add(objActivityIndicator1);
Button objButton1 = new Button();
objButton1.Text = "Execute webservice call.";
objButton1.Clicked += (async (o2, e2) =>
{
objButton1.IsVisible = false;
objActivityIndicator1.IsRunning = true;
//
bool blnResult = await ExecuteSomeLongTask();
//
objActivityIndicator1.IsRunning = false;
objButton1.IsVisible = true;
});
objGrid.Children.Add(objButton1);
return objGrid;
Supporting function:-
private Task<bool> ExecuteSomeLongTask()
{
TaskCompletionSource<bool> objTaskCompletionSource1 = new TaskCompletionSource<bool>();
//
Xamarin.Forms.Device.StartTimer(new TimeSpan(0, 0, 5), new Func<bool>(() =>
{
objTaskCompletionSource1.SetResult(true);
//
return false;
}));
//
return objTaskCompletionSource1.Task;
}
You need to do your work in an asynchronous way. Or in other words: Use Asnyc & Await to ensure, that you UI works well during the call.
You can find more informations in the Xamarin Docs.
async and await are new C# language features that work in conjunction
with the Task Parallel Library to make it easy to write threaded code
to perform long-running tasks without blocking the main thread of your
application.
If you need further asistance, please update your question and post your code or what you have tried so far.

ASP.Net MVC 3 Controller Action and Open New Window

i have a controller and an action. this action is to save data into database. and now, i want when i submit a button, my controller do an action and open new window.
public ActionResult New(FormCollection collection)
{
data.Population_Code = collection["Countrys[0].CountryCode"];
data.Population_Desc = collection["Countrys[0].CountryDesc"];
data.Population_Grouping = collection["Countrys[0].CountryGroup"];
data.Population_Type = "CNTRY";
data.Population_Redudant = "N";
data.Population_Modified_At = officeCode.User_Office.ToString();
db.SaveChanges();
//example for new window
//window.open('/Report/New.aspx')
return RedirectToAction("index");
}
so my controller do an action and open a new window.
anyone can help me ?
thanks
Technically, this can be done by returning javascript that will open the new window.
However, most browsers will kill a new window called in this manner (i.e. popup blocker).
You would be better off, if possible, by opening the link to your action in a new window from the start;
#Html.ActionLink("New report", "New", "Report", null, new {target = "_blank"})
Edit
I can see from your action, that it is probably a form that creates the report; you can also use the attribute target='_blank' on a form as well.

Resources