I am using Msal to AcquireTokenInteractive using Microsoft Graph SDK
Simple code
try
{
string[] scopes = { "user.read", "files.read" };
IPublicClientApplication app = PublicClientApplicationBuilder.Create(appId).WithRedirectUri(redirectUri).Build();
AuthenticationResult result = null;
var accounts = await app.GetAccountsAsync();
try
{
result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault()).ExecuteAsync();
}
catch (MsalUiRequiredException ex)
{
try
{
result = await app.AcquireTokenInteractive(scopes).ExecuteAsync();
}
catch (MsalException X)
{
ViewBag.ST = X.Message;
}
catch (Exception X)
{
ViewBag.ST = X.Message;
}
}
}
catch (Exception X)
{
ViewBag.ST = X.Message;
}
I am trying to get user's consent to allow my app to Read there data but when Code reaches app.AcquireTokenInteractive(scopes).ExecuteAsync(); It just keeps loading infinitely.
Definitely doing something weird, any idea what it is?
You need to embed the view as follows:
result = await app.AcquireTokenInteractive(scopes)
.WithUseEmbeddedWebView(true)
.ExecuteAsync();
Related
I am working on a Xamarin App where I am facing an issue.
Case 1:
Mode: Debug
Error: System.NullReferenceException: 'Object reference not set to an instance of an object'
Explanation:
No value is being set and passed to ViewModel, Controller.
Even I tried setting static values to variables and parameters.
LoginModel logtest = new LoginModel();
logtest.Username = "Test#user.com"; //uName;
logtest.Password = "2342534"; //pWord;
Tried solution:
In the beginning, I tried many different solutions nothing worked.
Then I create a new project and moved all the code to the new project, then it started working.
Case 2:
Mode: release
Now the same issue I am getting in release mode.
No value is being set and passed to ViewModels and Controller.
I have already tried moving code to a new project.
How can I resolve this? I am not sure is this a Visual studio issue or Xamarin issue or Apple.
I have tried updating Visual Studio enterprise 2019 and Xcode on Mac.
Deleted and recreated Provisioning Profiles and Signing Identities.
Code From LoginPage.xaml.cs
private async void LoginButtonClicked(object sender, EventArgs e)
{
await ((LoginViewModel)BindingContext).Login();
}
protected async override void OnAppearing()
{
//App.Current.MainPage = new Navigation(new DashboardPage());
//load the login page
Device.BeginInvokeOnMainThread(() =>
{
try
{
((LoginViewModel)BindingContext).IsLoading = false;
((LoginViewModel)BindingContext).RememberMe = DeviceStorage.RememberMe;
if (DeviceStorage.RememberMe == true)
{
((LoginViewModel)BindingContext).UserName = "Test#user.ca"; //Trying set static values here
((LoginViewModel)BindingContext).Password = "password"; //Trying set static values here
}
//RememberMeToggle.Toggled += switcher_Toggled;
((LoginViewModel)BindingContext).Load();
}
catch (Exception ex)
{
//logger.Error(App.LogPrefix() + "Error opening Navigation Page: " + ex.Message);
Console.WriteLine(App.LogPrefix() + "Error opening Load(): " + ex.Message);
}
});
}
Code from LoginViewModel.cs
public async Task Login()
{
IsLoading = true;
await TokenController.GetAuthorizationToken(UserName, Password);
}
Code from TokenController.cs
public static async Task GetAuthorizationToken(string uName, string pWord)
{
bool tokenReturned = false;
string tokenGetResponse = string.Empty;
// Have tried setting them static values as well
LoginModel logtest = new LoginModel();
logtest.Username = uName;
logtest.Password = pWord;
logtest.AppType = Constants.AppDetails.APP_CODE;
logtest.SystemCode = Constants.AppDetails.SYSTEM_CODE;
logtest.Push.PushSystem = PushAddressModel.PushSystemCode.FireBase;
logtest.Push.Address = ((App)App.Current).PushNotificationToken;
logtest.Push.AppCode = Constants.AppDetails.APP_CODE;
string uri = URI.message_Chat_Endpoint;
(tokenReturned, tokenGetResponse) = await ApiFunctions.Post(logtest, URI.token_Endpoint, false);
if (tokenReturned)
{
try
{
//deserialize the return object
TokenModel token = JsonConvert.DeserializeObject<TokenModel>(tokenGetResponse);
((App)App.Current).token = token;
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
//logger.Error(App.LogPrefix() + "Error: " + ex.Message);
}
Console.WriteLine("Profile Token loaded: " + ((App)App.Current).token.access_token);
}
else
{
Console.WriteLine("Error: Error loading profile token ");
//logger.Error(App.LogPrefix() + "Error loading profile token");
}
}
I have DocumentReference locationDocumentRef; in my state.
I'm changing locationDocumentRef based on the references, whether I gather by querying or by adding new document.
So I have this function to check the documents, if there is one set its reference to the locationDocumentRef, or add a new one and set its ref to the locationDocumentRef. I'm resetting its value everytime by setting it to null, since I didn't want to get previous result. But it prints null.
So my question is, how can I resolve them and get the value? I think I'm resolving too early in my code, so I can't await a non-future value. How can I fix it?
void firestoreCheckAndPush() async {
setState(() {
locationDocumentRef = null;
});
bool nameExists = await doesNameAlreadyExist(placeDetail.name);
if (nameExists) {
print('name exist');
} else {
print('name will be pushed on firestore');
pushNameToFirestore(placeDetail);
}
var resolvedRef = await locationDocumentRef;
print(resolvedRef.documentID); // I get null here
}
These are the functions that I have used
Future<bool> doesNameAlreadyExist(String name) async {
QuerySnapshot queryDb = await Firestore.instance
.collection('locations')
.where("city", isEqualTo: '${name}')
.limit(1)
.getDocuments();
if (queryDb.documents.length == 1) {
setState(() {
locationDocumentRef = queryDb.documents[0].reference;
});
return true;
} else {
return false;
}
}
And the other
void pushNameToFirestore(PlaceDetails pd) async {
DocumentReference justAddedRef =
await Firestore.instance.collection('locations').add(<String, String>{
'city': '${pd.name}',
'image': '${buildPhotoURL(pd.photos[0].photoReference)}',
});
setState(() {
locationDocumentRef = justAddedRef;
});
}
there is two mistakes i saw first here
var resolvedRef = await locationDocumentRef;
why you await for locationDocumentRef,
second you dont wait for pushNameToFirestore(PlaceDetails pd) firestoreCheckAndPush() function which is weird since pushNameToFirestore(String) is sync and this means you wouldnt wait for it to finish so if you are adding a new name it would print null.
correct me if i am wrong.
you can find more about sync and future here https://www.dartlang.org/tutorials/language/futures
look at the graph at the middle of the page
Try this
Future<List<DocumentSnapshot>> doesNameAlreadyExist(String name) async {
QuerySnapshot data = await Firestore.instance
.collection('locations')
.where("city", isEqualTo: name)
.limit(1)
.getDocuments();
return data.documents;
}
void firestoreCheckAndPush() async {
var data = await doesNameAlreadyExist('yourname');
if (data.length > 0) {
print('name exist');;
print('Document id '+ data[0].documentID);
} else {
print('name will be pushed on firestore');
}
}
Take a look into following code.
void firestoreCheckAndPush() async {
DocumentReference documentReference;
var data = await doesNameAlreadyExist('yourname');
var dataRef = await doesNameAlreadyExist('yourname');
if (data.length > 0) {
print('name exist');
documentReference = dataRef[0].reference;
print('Document id ' + data[0].documentID);
documentReference = dataRef[0].reference;
print('Document reference ');
print(documentReference);
} else {
print('name will be pushed on firestore');
}
}
For example, I have a car1 that was first owner by the manufacturer and then it was transferred over to the retailer and then to the user
In the fabcar example, I can know who is its current owner by i don't know who is the previous owner.
Is there a way to do it?
Here is the http://hyperledger-fabric.readthedocs.io/en/latest/write_first_app.html example I was following
Is not implemented in the chaincode. To do this you could implement a new method which returns the history of the asset.
Here the link to the official documentation for nodeJS (you can find it also for GoLang):
https://fabric-shim.github.io/ChaincodeStub.html#getHistoryForKey__anchor
Here an example:
async queryValueHistory(stub,args){
if (args.length != 1) {
throw new Error('Incorrect number of arguments. Expecting identifier ex: CAR01');
}
let carId = args[0];
let iterator = await stub.getHistoryForKey(carId);
let allResults = [];
while (true) {
let res = await iterator.next();
if (res.value && res.value.value.toString()) {
let jsonRes = {};
console.log(res.value.value.toString('utf8'));
jsonRes.TxId = res.value.tx_id;
jsonRes.Timestamp = res.value.timestamp;
jsonRes.IsDelete = res.value.is_delete.toString();
try {
jsonRes.Value = JSON.parse(res.value.value.toString('utf8'));
} catch (err) {
console.log(err);
jsonRes.Value = res.value.value.toString('utf8');
}
console.info(jsonRes);
allResults.push(jsonRes);
}
if (res.done) {
console.log('end of data');
try{
await iterator.close();
}catch(err){
console.log(err);
}
console.info(allResults);
return Buffer.from(JSON.stringify(allResults));
}
}
}
I am calling an api. I am getting a streamed response after sending the request. But i cannot parse the response and convert it to String/JSON. This is where I am calling the api.
static Future<String> callDeviceListFetchApi() async {
Completer completer = new Completer();
String jsonResponse;
String url = Constants.BASE_URL + Constants.DEVICE_REGISTER_URL;
var client = new http.Client();
var request = new http.Request('GET', Uri.parse(url));
request.headers[HttpHeaders.CONTENT_TYPE] = 'application/json';
request.headers[HttpHeaders.AUTHORIZATION] = '<auth code>';
await client.send(request).then((response) {
response.stream.bytesToString().then((value) {
print(value.toString());
jsonResponse = value.toString();
completer.complete(jsonResponse);
});
}).catchError((error) {
print(error.toString());
});
return completer.future;
}
I am getting the error,
Bad state: Stream has already been listened to Flutter error. Any idea why this is happening?
There's a couple of things wrong with your code. I think you have a slight misunderstanding about how Async and Futures work in dart - you should re-read the docs and this tutorial (part 1 and part 2).
Basically, the problem is that you were returning a 'Future' from an async function. If you return a future from an async function, it has issues (I don't know why the analyzer doesn't catch that).
Future<String> callDeviceListFetchApi() async {
Completer completer = new Completer();
String url = "<url>";
var client = new http.Client();
var request = new http.Request('GET', Uri.parse(url));
request.headers[HttpHeaders.CONTENT_TYPE] = 'application/json';
request.headers[HttpHeaders.AUTHORIZATION] =
'<auth string>';
var response = await client.send(request);
String jsonResponse;
try {
var value = await response.stream.bytesToString();
print(value.toString());
jsonResponse = value.toString();
} catch (error) {
print(error.toString());
}
return completer.complete(jsonResponse);
}
Or not async:
Future<String> callDeviceListFetchApiNotAsync() {
String url = "<url>";
var client = new http.Client();
var request = new http.Request('GET', Uri.parse(url));
request.headers[HttpHeaders.CONTENT_TYPE] = 'application/json';
request.headers[HttpHeaders.AUTHORIZATION] =
'<auth string>';
Completer completer = new Completer();
return client.send(request).then((response) {
return response.stream.bytesToString();
}).then((value) {
print(value.toString());
return value.toString();
}).catchError((error) {
print(error.toString());
// if you use catchError, whatever you return from it
// is the value you'll get wherever you resolve the future.
return null;
});
}
But unless you're trying to do something I'm not seeing, there's a way easier way to do this (assuming all you want to do is get a string from a server):
Future<String> getList() async {
var response = await http.get("<url>", headers: {
HttpHeaders.CONTENT_TYPE: 'application/json',
HttpHeaders.AUTHORIZATION: '<auth string>',
});
if (response.statusCode == 200) {
return response.body;
} else {
throw Error();
}
}
I am using the following code to upload a video to Youtube through youtube API. My problem is after uploading the video, I need to give the location of the video to the user. How do I find this ?
I'll be really grateful if someone can help me to solve this.
MediaFileSource ms = new MediaFileSource(videoFile, mimeType);
String videoTitle = title;
VideoEntry newEntry = new VideoEntry();
YouTubeMediaGroup mg = newEntry.getOrCreateMediaGroup();
mg.addCategory(new MediaCategory(YouTubeNamespace.CATEGORY_SCHEME, "Tech"));
mg.setTitle(new MediaTitle());
mg.getTitle().setPlainTextContent(videoTitle);
mg.setKeywords(new MediaKeywords());
mg.getKeywords().addKeyword("yt:crop=16:9");
mg.setDescription(new MediaDescription());
mg.getDescription().setHtmlContent(attributionDocument);
mg.setPrivate(true);
mg.setVideoId("Vid1");
ResumableGDataFileUploader uploader = null;
try {
uploader = new ResumableGDataFileUploader.Builder(
service, new URL(RESUMABLE_UPLOAD_URL), ms, newEntry)
.title(videoTitle)
.build();
uploader.start();
while (!uploader.isDone()) {
try {
Thread.sleep(PROGRESS_UPDATE_INTERVAL);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
switch(uploader.getUploadState()) {
case COMPLETE:
System.out.println("Uploaded successfully");
break;
case CLIENT_ERROR:
System.out.println("Upload Failed");
break;
default:
System.out.println("Unexpected upload status");
break;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ServiceException e) {
e.printStackTrace();
}
I managed to solve this by myself. Instead of using resumable file upload, I used direct upload. My code:
String id = "";
File videoFile = new File(videoLocation);
if (!videoFile.exists()) {
System.out.println("Sorry, that video doesn't exist.");
}
String videoTitle = title;
VideoEntry newEntry = new VideoEntry();
YouTubeMediaGroup mg = newEntry.getOrCreateMediaGroup();
mg.setTitle(new MediaTitle());
mg.getTitle().setPlainTextContent(videoTitle);
mg.setKeywords(new MediaKeywords());
mg.getKeywords().addKeyword("yt:crop=16:9");
mg.setDescription(new MediaDescription());
mg.getDescription().setHtmlContent(attributionDocument);
mg.setPrivate(true);
mg.addCategory(new MediaCategory(YouTubeNamespace.CATEGORY_SCHEME, "Tech"));
MediaFileSource ms = new MediaFileSource(videoFile, "video/quicktime");
newEntry.setMediaSource(ms);
String uploadUrl =
"http://uploads.gdata.youtube.com/feeds/api/users/default/uploads";
VideoEntry createdEntry = service.insert(new URL(uploadUrl), newEntry);
id =createdEntry.getId();
return id;
}
I hope this will save someone else's day.