GraphAPI request content Read/Write Timeout Throwing Invalid Operation Exception - c#

The code below creates a new folder within the SharePoint which will then copy a power point and add it to the newly created folder. I am making 2 requests, one to get the file itself and another to get the file contents for an appropriate copy. When performing the follow line
var tester = await graphClient.Sites[sharepoint.Id].Drive.Root.ItemWithPath("FolderPath/Template.pptx").Content.Request().GetAsync();
It doesn't seem to be working on creating the copy to the newly created folder. When examining in debugger I see my tester of stype System.IO.MemoryStream is getting an invalid operation exception with the Read.Timeout and Write.Timeout.
Any assistance would be great.
public async Task<string> Sharepoint_FolderCreate(string NewFolderName, string sharepoint_folder_path = "/SomeFolderPath")
{
var item = new DriveItem
{
Name = NewFolderName.Replace("?", " ").Replace("/", " ").Replace("\\", " ").Replace("<", " ").Replace(">", " ").Replace("*", " ").Replace("\"", " ").Replace(":", " ").Replace("|", " "),
Folder = new Folder { },
AdditionalData = new Dictionary<string, object>()
{
{"#microsoft.graph.conflictBehavior","rename"}
}
};
var scopes = new[] { "https://graph.microsoft.com/.default" };
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
// https://docs.microsoft.com/dotnet/api/azure.identity.clientsecretcredential
var clientSecretCredential = new ClientSecretCredential(
tenantID, clientId, clientSecret, options);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var sharepoint = await graphClient.Sites.GetByPath("/sites/SiteFolder", "localhost.sharepoint.com").Request().GetAsync();
await graphClient.Sites[sharepoint.Id].Drive.Root.ItemWithPath(sharepoint_folder_path).Children.Request().AddAsync(item);
var NewFolder = await graphClient.Sites[sharepoint.Id].Drive.Root.ItemWithPath($"{sharepoint_folder_path}/{item.Name}").Request().GetAsync();
return NewFolder.WebUrl;
}

Thank you to the above comments. My goal was achieved with the following code which creates a new folder then copies a powerpoint saved within a different folder in the sharepoint to the newly created folder.
public async Task<string> Sharepoint_FolderCreate(string NewFolderName, string sharepoint_folder_path = "/FolderPath")
{
var item = new DriveItem
{
Name = NewFolderName.Replace("?", " ").Replace("/", " ").Replace("\\", " ").Replace("<", " ").Replace(">", " ").Replace("*", " ").Replace("\"", " ").Replace(":", " ").Replace("|", " ").Trim(),
Folder = new Folder { },
AdditionalData = new Dictionary<string, object>()
{
{"#microsoft.graph.conflictBehavior","rename"}
}
};
var scopes = new[] { "https://graph.microsoft.com/.default" };
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
var clientSecretCredential = new ClientSecretCredential(tenantID, clientId, clientSecret, options);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var sharepoint = await graphClient.Sites.GetByPath("/sites/Folder", "localhost.sharepoint.com").Request().GetAsync();
await graphClient.Sites[sharepoint.Id].Drive.Root.ItemWithPath(sharepoint_folder_path).Children.Request().AddAsync(item);
var NewFolder = await graphClient.Sites[sharepoint.Id].Drive.Root.ItemWithPath($"{sharepoint_folder_path}/{item.Name}").Request().GetAsync();
var parentReference = new ItemReference
{
DriveId = NewFolder.ParentReference.DriveId,
Id = NewFolder.Id
};
await graphClient.Sites[sharepoint.Id].Drive.Root.ItemWithPath("/FolderPath/Template.pptx").Copy($"{item.Name}.pptx", parentReference).Request().PostAsync();
return NewFolder.WebUrl;
}

Related

Microsoft Graph upload large files

I am developing an aplication that send and email with one or multiple attachments via Microsoft Graph, but when try to upload file send me an error: ": Invalid total bytes specified in the Content-Range header"
i asume that i must specifi Range Value in same where, but no idea.
This is my code:
private static async void SenMailUsingMicrosoftGraph(List<String>Destinations, List<String>Cc, string HidenCopy, string Body, string Title, List<FileInfo>Filess);
{
ClientSecretCredential credential = new ClientSecretCredential("MyTenantID", "MyClientId", "MyClientSecret");
List<Recipient> recipientsDestinatarios = new List<Recipient>();
List<Recipient> recipientsCopias = new List<Recipient>();
foreach (var c in Destinations)
{
recipientsDestinatarios.Add(
new Recipient
{
EmailAddress = new EmailAddress
{
Address = c
}
});
}
foreach (var mail in Cc)
{
recipientsCopias.Add(
new Recipient
{
EmailAddress = new EmailAddress
{
Address = mail
}
});
}
#endregion
var message = new Microsoft.Graph.Message
{
Subject = Title,
Body = new ItemBody
{
ContentType = BodyType.Html,
Content = Body
},
ToRecipients = recipientsDestinatarios
,
CcRecipients = recipientsCopias
,
BccRecipients = new List<Recipient>()
{
new Recipient
{
EmailAddress=new EmailAddress{Address=Hiden}
}
}
};
GraphServiceClient graphClient = new GraphServiceClient(credential);
#endregion
#region adjuntar ficheros
var msgResult = await graphClient.Users["myemail#mycompany.com"].MailFolders.Drafts.Messages
.Request()
.WithMaxRetry(9)
.AddAsync(message);
foreach (var Archivo in Filess)
{
var attachmentContentSize = Archivo.Length;
var attachmentItem = new AttachmentItem
{
AttachmentType = AttachmentType.File,
Name = Archivo.Name,
Size = attachmentContentSize,
};
//initiate the upload session for large files
var uploadSession = await graphClient.Users["myemail#mycompany.com"].Messages[msgResult.Id].Attachments
.CreateUploadSession(attachmentItem)
.Request()
.PostAsync();
var maxChunkSize = 1024 * 320;
var allBytes = System.IO.File.ReadAllBytes(Archivo.FullName);
using (var stream = new MemoryStream(allBytes))
{
stream.Position = 0;
LargeFileUploadTask<FileAttachment> largeFileUploadTask = new LargeFileUploadTask<FileAttachment>(uploadSession, stream, maxChunkSize);
await largeFileUploadTask.UploadAsync();
}
}
await graphClient.Users["myemail#mycompany.com"].Messages[msgResult.Id].Send().Request().PostAsync();
}
I try something like this:
var content = new System.Net.Http.Headers.ContentRangeHeaderValue(0,MyFile.Length-1,MyFile.Length);
but i dont now how to asign this content variable, i think that must go in the uploadSession but dont know how.
------------------------------------EDIT------------------------------
included a Picture where see that the size of the attachment is not zero

AndroidPublisherService - Play Developer API Client - Upload aab failes due to bad credentials

Trying to make use of the AndroidPublisherService from Play Developer API Client.
I can list active tracks and the releases in those tracks, but when I try to upload a new build there seems to be no way of attaching the authentication already made previously to read data.
I've authenticated using var googleCredentials = GoogleCredential.FromStream(keyDataStream) .CreateWithUser(serviceUsername); where serviceUsername is the email for my service account.
private static void Execute(string packageName, string aabfile, string credfile, string serviceUsername)
{
var credentialsFilename = credfile;
if (string.IsNullOrWhiteSpace(credentialsFilename))
{
// Check env. var
credentialsFilename =
Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS",
EnvironmentVariableTarget.Process);
}
Console.WriteLine($"Using credentials {credfile} with package {packageName} for aab file {aabfile}");
var keyDataStream = File.OpenRead(credentialsFilename);
var googleCredentials = GoogleCredential.FromStream(keyDataStream)
.CreateWithUser(serviceUsername);
var credentials = googleCredentials.UnderlyingCredential as ServiceAccountCredential;
var service = new AndroidPublisherService();
var edit = service.Edits.Insert(new AppEdit { ExpiryTimeSeconds = "3600" }, packageName);
edit.Credential = credentials;
var activeEditSession = edit.Execute();
Console.WriteLine($"Edits started with id {activeEditSession.Id}");
var tracksList = service.Edits.Tracks.List(packageName, activeEditSession.Id);
tracksList.Credential = credentials;
var tracksResponse = tracksList.Execute();
foreach (var track in tracksResponse.Tracks)
{
Console.WriteLine($"Track: {track.TrackValue}");
Console.WriteLine("Releases: ");
foreach (var rel in track.Releases)
Console.WriteLine($"{rel.Name} version: {rel.VersionCodes.FirstOrDefault()} - Status: {rel.Status}");
}
using var fileStream = File.OpenRead(aabfile);
var upload = service.Edits.Bundles.Upload(packageName, activeEditSession.Id, fileStream, "application/octet-stream");
var uploadProgress = upload.Upload();
if (uploadProgress == null || uploadProgress.Exception != null)
{
Console.WriteLine($"Failed to upload. Error: {uploadProgress?.Exception}");
return;
}
Console.WriteLine($"Upload {uploadProgress.Status}");
var tracksUpdate = service.Edits.Tracks.Update(new Track
{
Releases = new List<TrackRelease>(new[]
{
new TrackRelease
{
Name = "Roswell - Grenis Dev Test",
Status = "completed",
VersionCodes = new List<long?>(new[] {(long?) upload?.ResponseBody?.VersionCode})
}
})
}, packageName, activeEditSession.Id, "internal");
tracksUpdate.Credential = credentials;
var trackResult = tracksUpdate.Execute();
Console.WriteLine($"Track {trackResult?.TrackValue}");
var commitResult = service.Edits.Commit(packageName, activeEditSession.Id);
Console.WriteLine($"{commitResult.EditId} has been committed");
}
And as the code points out, all action objects such as tracksList.Credential = credentials; can be given the credentials generated from the service account.
BUT the actual upload action var upload = service.Edits.Bundles.Upload(packageName, activeEditSession.Id, fileStream, "application/octet-stream"); does not expose a .Credential object, and it always fails with:
The service androidpublisher has thrown an exception: Google.GoogleApiException: Google.Apis.Requests.RequestError
Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project. [401]
Errors [
Message[Login Required.] Location[Authorization - header] Reason[required] Domain[global]
]
at Google.Apis.Upload.ResumableUpload`1.InitiateSessionAsync(CancellationToken cancellationToken)
at Google.Apis.Upload.ResumableUpload.UploadAsync(CancellationToken cancellationToken)
So, how would I go about providing the actual Upload action with the given credentials here?
Managed to figure this out during the day, I was missing one call to CreateScoped() when creating the GoogleCredential object as well as a call to InitiateSession() on the upload object.
var googleCredentials = GoogleCredential.FromStream(keyDataStream)
.CreateWithUser(serviceUsername)
.CreateScoped(AndroidPublisherService.Scope.Androidpublisher);
Once that was done I could then get a valid oauth token by calling
var googleCredentials = GoogleCredential.FromStream(keyDataStream)
.CreateWithUser(serviceUsername)
.CreateScoped(AndroidPublisherService.Scope.Androidpublisher);
var credentials = googleCredentials.UnderlyingCredential as ServiceAccountCredential;
var oauthToken = credentials?.GetAccessTokenForRequestAsync(AndroidPublisherService.Scope.Androidpublisher).Result;
And I can now use that oauth token in the upload request:
upload.OauthToken = oauthToken;
_ = await upload.InitiateSessionAsync();
var uploadProgress = await upload.UploadAsync();
if (uploadProgress == null || uploadProgress.Exception != null)
{
Console.WriteLine($"Failed to upload. Error: {uploadProgress?.Exception}");
return;
}
The full code example for successfully uploading a new aab file to google play store internal test track thus looks something like this:
private async Task UploadGooglePlayRelease(string fileToUpload, string changeLogFile, string serviceUsername, string packageName)
{
var serviceAccountFile = ResolveServiceAccountCertificateInfoFile();
if (!serviceAccountFile.Exists)
throw new ApplicationException($"Failed to find the service account certificate file. {serviceAccountFile.FullName}");
var keyDataStream = File.OpenRead(serviceAccountFile.FullName);
var googleCredentials = GoogleCredential.FromStream(keyDataStream)
.CreateWithUser(serviceUsername)
.CreateScoped(AndroidPublisherService.Scope.Androidpublisher);
var credentials = googleCredentials.UnderlyingCredential as ServiceAccountCredential;
var oauthToken = credentials?.GetAccessTokenForRequestAsync(AndroidPublisherService.Scope.Androidpublisher).Result;
var service = new AndroidPublisherService();
var edit = service.Edits.Insert(new AppEdit { ExpiryTimeSeconds = "3600" }, packageName);
edit.Credential = credentials;
var activeEditSession = await edit.ExecuteAsync();
_logger.LogInformation($"Edits started with id {activeEditSession.Id}");
var tracksList = service.Edits.Tracks.List(packageName, activeEditSession.Id);
tracksList.Credential = credentials;
var tracksResponse = await tracksList.ExecuteAsync();
foreach (var track in tracksResponse.Tracks)
{
_logger.LogInformation($"Track: {track.TrackValue}");
_logger.LogInformation("Releases: ");
foreach (var rel in track.Releases)
_logger.LogInformation($"{rel.Name} version: {rel.VersionCodes.FirstOrDefault()} - Status: {rel.Status}");
}
var fileStream = File.OpenRead(fileToUpload);
var upload = service.Edits.Bundles.Upload(packageName, activeEditSession.Id, fileStream, "application/octet-stream");
upload.OauthToken = oauthToken;
_ = await upload.InitiateSessionAsync();
var uploadProgress = await upload.UploadAsync();
if (uploadProgress == null || uploadProgress.Exception != null)
{
Console.WriteLine($"Failed to upload. Error: {uploadProgress?.Exception}");
return;
}
_logger.LogInformation($"Upload {uploadProgress.Status}");
var releaseNotes = await File.ReadAllTextAsync(changeLogFile);
var tracksUpdate = service.Edits.Tracks.Update(new Track
{
Releases = new List<TrackRelease>(new[]
{
new TrackRelease
{
Name = $"{upload?.ResponseBody?.VersionCode}",
Status = "completed",
InAppUpdatePriority = 5,
CountryTargeting = new CountryTargeting { IncludeRestOfWorld = true },
ReleaseNotes = new List<LocalizedText>(new []{ new LocalizedText { Language = "en-US", Text = releaseNotes } }),
VersionCodes = new List<long?>(new[] {(long?) upload?.ResponseBody?.VersionCode})
}
})
}, packageName, activeEditSession.Id, "internal");
tracksUpdate.Credential = credentials;
var trackResult = await tracksUpdate.ExecuteAsync();
_logger.LogInformation($"Track {trackResult?.TrackValue}");
var commitResult = service.Edits.Commit(packageName, activeEditSession.Id);
commitResult.Credential = credentials;
await commitResult.ExecuteAsync();
_logger.LogInformation($"{commitResult.EditId} has been committed");
}

Azure Devops GitHttpClient's CreateAnnotatedTagAsync API fails

When calling GitHttpClient.CreateAnnotatedTagAsync, I keep getting "VS30063: You are not authorized to access https://dev.azure.com" even though my credentials are valid.
This is my code:
var vssConnection = new VssConnection(new Uri("ORG_URI"), new VssBasicCredential(string.Empty, "PAT"));
var gitClient = vssConnection.GetClient<GitHttpClient>();
var tag = new GitAnnotatedTag
{
Name = "tagname",
Message = "A new tag",
TaggedBy = new GitUserDate
{
Name = "Name",
Email = "Email",
Date = DateTime.Now,
ImageUrl = null
},
ObjectId = "SHA",
TaggedObject = new GitObject
{
ObjectId = "SHA",
ObjectType = GitObjectType.Commit
},
Url = string.Empty
};
var sourceRepo = await gitClient.GetRepositoryAsync("PROJECT", repoName);
// This call works
var tags = await gitClient.GetTagRefsAsync(sourceRepo.Id);
// The tag is printed to the console
Console.WriteLine(tags.First().Name);
// This throws "VS30063: You are not authorized to access https://dev.azure.com"
await gitClient.CreateAnnotatedTagAsync(tag, "PROJECT", sourceRepo.Id);
There is an issue with your PAT token. I just created a tag using your code and PAT with FULL Access:
Can you create a new token and try again?

Delete a folder from Amazon S3 using API

I am trying to delete all the files inside a folder which is basically the date.
Suppose, if there are 100 files under folder "08-10-2015", instead of sending all those 100 file names, i want to send the folder name.
I am trying below code and it is not working for me.
DeleteObjectsRequest multiObjectDeleteRequest = new DeleteObjectsRequest();
multiObjectDeleteRequest.BucketName = bucketName;
multiObjectDeleteRequest.AddKey(keyName + "/" + folderName + "/");
AmazonS3Config S3Config = new AmazonS3Config()
{
ServiceURL = string.Format(servicehost)
};
using (IAmazonS3 client = Amazon.AWSClientFactory.CreateAmazonS3Client(accesskey, secretkey, S3Config))
{
try
{
DeleteObjectsResponse response = client.DeleteObjects(multiObjectDeleteRequest);
Console.WriteLine("Successfully deleted all the {0} items", response.DeletedObjects.Count);
}
catch (DeleteObjectsException e)
{
// Process exception.
}
I am using the above code and it is not working.
I think you can delete the entire folder using the following code:
AmazonS3Config cfg = new AmazonS3Config();
cfg.RegionEndpoint = Amazon.RegionEndpoint.EUCentral1;
string bucketName = "your bucket name";
AmazonS3Client s3Client = new AmazonS3Client("your access key", "your secret key", cfg);
S3DirectoryInfo directoryToDelete = new S3DirectoryInfo(s3Client, bucketName, "your folder name or full folder key");
directoryToDelete.Delete(true); // true will delete recursively in folder inside
I am using amazon AWSSDK.Core and AWSSDK.S3 version 3.1.0.0 for .net 3.5.
I hope it can help you
You have to:
List all objects in the folder
Retrieve key for each object
Add this key to a multiple Delete Object Request
Make the request to delete all objects
AmazonS3Config S3Config = new AmazonS3Config()
{
ServiceURL = "s3.amazonaws.com",
CommunicationProtocol = Amazon.S3.Model.Protocol.HTTP,
};
const string AWS_ACCESS_KEY = "xxxxxxxxxxxxxxxx";
const string AWS_SECRET_KEY = "yyyyyyyyyyyyyyyy";
AmazonS3Client client = new AmazonS3Client(AWS_ACCESS_KEY, AWS_SECRET_KEY, S3Config);
DeleteObjectsRequest request2 = new DeleteObjectsRequest();
ListObjectsRequest request = new ListObjectsRequest
{
BucketName = "yourbucketname",
Prefix = "yourprefix"
};
ListObjectsResponse response = await client.ListObjectsAsync(request);
// Process response.
foreach (S3Object entry in response.S3Objects)
{
request2.AddKey(entry.Key);
}
request2.BucketName = "yourbucketname";
DeleteObjectsResponse response2 = await client.DeleteObjectsAsync(request2);
I'm not sure why they didn't keep this method in future SDKs, but, for those interested, here is the implementation of the S3DirectoryInfo.Delete method:
ListObjectsRequest listObjectsRequest = new ListObjectsRequest
{
BucketName = bucket,
Prefix = directoryPrefix
};
DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest
{
BucketName = bucket
};
ListObjectsResponse listObjectsResponse = null;
do
{
listObjectsResponse = s3Client.ListObjects(listObjectsRequest);
foreach (S3Object item in listObjectsResponse.S3Objects.OrderBy((S3Object x) => x.Key))
{
deleteObjectsRequest.AddKey(item.Key);
if (deleteObjectsRequest.Objects.Count == 1000)
{
s3Client.DeleteObjects(deleteObjectsRequest);
deleteObjectsRequest.Objects.Clear();
}
listObjectsRequest.Marker = item.Key;
}
}
while (listObjectsResponse.IsTruncated);
if (deleteObjectsRequest.Objects.Count > 0)
{
s3Client.DeleteObjects(deleteObjectsRequest);
}

Logging with Twitter c# implementation on parse.com

In my application i want users to be able to login with facebook and twitter.
For facebook i see there is a procedure ready for that ParseFacebookUtils but there isn't anything like that for Twitter so im making my own.
I have create an implementation for logging in with twitter:
void LoginToTwitter ()
{
var auth = new OAuth1Authenticator(
"<authkey>",
"<authsecret>",
new Uri("https://api.twitter.com/oauth/request_token"),
new Uri("https://api.twitter.com/oauth/authorize"),
new Uri("https://api.twitter.com/oauth/access_token"),
new Uri("http://twitter.com/"));
auth.Completed += GetTwitterData;
var ui = auth.GetUI(Activity);
StartActivity(ui);
}
async public void GetTwitterData( object sender, AuthenticatorCompletedEventArgs e )
{
var request = new OAuth1Request(
"GET",
new Uri("https://api.twitter.com/1.1/account/verify_credentials.json "),
null,
e.Account);
await request.GetResponseAsync().ContinueWith(t =>
{
var res = t.Result;
var resString = res.GetResponseText();
Console.WriteLine("Result Text: " + resString);
var jo = Newtonsoft.Json.Linq.JObject.Parse(resString);
var imageUrl = new Java.Net.URL((string)jo["profile_image_url"]);
var twitterId = jo["id"];
var accessToken = e.Account.Properties["access_token"].ToString();
var expiresIn = Convert.ToDouble(e.Account.Properties["expires_in"]);
var expiryDate = DateTime.Now + TimeSpan.FromSeconds( expiresIn );
var userRealName = e.Account.Properties["screen_name"];
}, UIScheduler);
}
And now the only thing left is to associate there data With a new user or if the user exist to logg him in.
I see ParseFacebookUtils creates a randomly username for each user. In order for me to do something like that i must first check if the random generated username doesn't already exist, is it a good idea to use twitter username for that?
Also facebook stores something called authData of type authData with content like this:
{"facebook": {"access_token":"some_token","expiration_date":"some_date","id":"some_id"}}
How i can create something like that for twitter? i have already generate the required fields
I have successfully Login with twitter on Xamarin.Android with Parse.com
Here is how i manage to do it in case is useful to someone else, you will need components Xamarin.auth and RestSharp:
void LoginToTwitter ()
{
var auth = new OAuth1Authenticator(
"some_key",
"some_key",
new Uri("https://api.twitter.com/oauth/request_token"),
new Uri("https://api.twitter.com/oauth/authorize"),
new Uri("https://api.twitter.com/oauth/access_token"),
new Uri("https://mobile.twitter.com/"));
//save the account data in the authorization completed even handler
auth.Completed += GetTwitterData;
var ui = auth.GetUI(Activity);
StartActivity(ui);
}
public async void GetTwitterData( object sender, AuthenticatorCompletedEventArgs e )
{
//use the account object and make the desired API call
if (e.IsAuthenticated)
Console.WriteLine("Logged in");
var request = new OAuth1Request(
"GET",
new Uri("https://api.twitter.com/1.1/account/verify_credentials.json"),
null,
e.Account, true);
await request.GetResponseAsync().ContinueWith(t =>
{
if (!t.IsFaulted && !t.IsCanceled){
var res = t.Result;
var resString = res.GetResponseText();
//Console.WriteLine("Result Text: " + resString);
var jo = Newtonsoft.Json.Linq.JObject.Parse(resString);
imageUrl = new Java.Net.URL((string)jo["profile_image_url"]);
var twitterId = jo["id"];
}
}, UIScheduler);
var userID = e.Account.Properties["user_id"];
var name = e.Account.Properties["screen_name"];
var oauth_consumer_key = e.Account.Properties["oauth_consumer_key"];
var oauth_consumer_secret = e.Account.Properties["oauth_consumer_secret"];
var oauth_token = e.Account.Properties["oauth_token"];
var oauth_token_secret = e.Account.Properties["oauth_token_secret"];
var authData = new Dictionary<string,string>();
authData.Add("user_id",userID.ToString());
authData.Add("screen_name",name.ToString());
authData.Add("oauth_consumer_key",oauth_consumer_key.ToString());
authData.Add("oauth_consumer_secret",oauth_consumer_secret.ToString());
authData.Add("oauth_token",oauth_token.ToString());
authData.Add("oauth_token_secret",oauth_token_secret.ToString());
await ParseLoginOrCreate(authData);
}
public async Task<ParseUser> ParseLoginOrCreate(Dictionary<string,string> authInfo)
{
var rest = new RestSharp.RestClient ("https://api.parse.com");
var req = new RestSharp.RestRequest ("1/users/", RestSharp.Method.POST);
req.AddHeader ("X-Parse-Application-Id", "some_key");
req.AddHeader ("X-Parse-REST-API-Key", "some_key");
req.AddHeader ("Content-Type", "application/json");
var payload = "{ \"authData\": { \"twitter\": { ";
payload += "\"id\": \"" + authInfo["user_id"] + "\", ";
payload += "\"screen_name\": \"" + authInfo["screen_name"] + "\", ";
payload += "\"consumer_key\": \"" + authInfo["oauth_consumer_key"] + "\", ";
payload += "\"consumer_secret\": \"" + authInfo["oauth_consumer_secret"] + "\", ";
payload += "\"auth_token\": \"" + authInfo["oauth_token"] + "\", ";
payload += "\"auth_token_secret\": \"" + authInfo["oauth_token_secret"] + "\" ";
payload += "} } }";
req.AddParameter("application/json", payload, RestSharp.ParameterType.RequestBody);
RestSharp.IRestResponse res = null;
var result = await Task<JContainer>.Run(()=>{
res = rest.Execute(req);
var content = res.Content;
return JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JContainer>(content);
});
var sessionToken = (String)result["sessionToken"];
var objectId = (String)result["objectId"];
if (res.StatusCode == System.Net.HttpStatusCode.Created)
{
req = new RestSharp.RestRequest ("1/users/" + objectId, RestSharp.Method.PUT);
req.AddHeader ("X-Parse-Application-Id", "some_key");
req.AddHeader ("X-Parse-REST-API-Key", "some_key");
req.AddHeader ("X-Parse-Session-Token", sessionToken);
req.AddHeader ("Content-Type", "application/json");
req.AddParameter("application/json", "{ \"username\": \"" + authInfo["screen_name"] + "\" }", RestSharp.ParameterType.RequestBody);
result = await Task<JContainer>.Run(() => {
res= rest.Execute(req);
var content = res.Content;
return JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JContainer>(content);
});
}
await ParseUser.BecomeAsync (sessionToken);
return ParseUser.CurrentUser;
}

Categories