I have an asp.net website which sends a tweet on a button click event.
I am using the TwitterApi for this and have an authenticated developer account.
This function was working from September 2018 until last month, but all of a sudden it won't send the tweets on request.
The response I get now is - "Id = 1, Status = WaitingForActivation, Method = "{null}", Result = "{Not yet computed}""
After searching around, this doesn't seem like a twitter error, but an async error of some kind. I have made some minor alterations to my website in this time, but I cant see anything I have changed that would cause this issue.
The code is below.
Can any one see why this error would occur?
protected void Publish_Click(object sender, EventArgs e)
{
DataAccess.Publish();
SendEmails();
SendTweet();
Response.Redirect("OtherPage.aspx");
}
public static void SendTweet()
{
string text = DataAccess.GetText();
var twitter = new TwitterApi();
var response = twitter.Tweet(text);
}
public TwitterApi()
{
this.consumerKey = "XXX";
this.consumerKeySecret = "XXX";
this.accessToken = "XXX";
this.accessTokenSecret = "XXX";
sigHasher = new HMACSHA1(new ASCIIEncoding().GetBytes(string.Format("{0}&{1}", consumerKeySecret, accessTokenSecret)));
}
public Task<string> Tweet(string text)
{
var data = new Dictionary<string, string> {
{ "status", text },
{ "trim_user", "1" }
};
return SendRequest("statuses/update.json", data);
}
Task<string> SendRequest(string url, Dictionary<string, string> data)
{
var fullUrl = TwitterApiBaseUrl + url;
// Timestamps are in seconds since 1/1/1970.
var timestamp = (int)((DateTime.UtcNow - epochUtc).TotalSeconds);
// Add all the OAuth headers we'll need to use when constructing the hash.
data.Add("oauth_consumer_key", consumerKey);
data.Add("oauth_signature_method", "HMAC-SHA1");
data.Add("oauth_timestamp", timestamp.ToString());
data.Add("oauth_nonce", "a"); // Required, but Twitter doesn't appear to use it, so "a" will do.
data.Add("oauth_token", accessToken);
data.Add("oauth_version", "1.0");
// Generate the OAuth signature and add it to our payload.
data.Add("oauth_signature", GenerateSignature(fullUrl, data));
// Build the OAuth HTTP Header from the data.
string oAuthHeader = GenerateOAuthHeader(data);
// Build the form data (exclude OAuth stuff that's already in the header).
var formData = new FormUrlEncodedContent(data.Where(kvp => !kvp.Key.StartsWith("oauth_")));
return SendRequest(fullUrl, oAuthHeader, formData);
}
async Task<string> SendRequest(string fullUrl, string oAuthHeader, FormUrlEncodedContent formData)
{
using (var http = new HttpClient())
{
http.DefaultRequestHeaders.Add("Authorization", oAuthHeader);
var httpResp = await http.PostAsync(fullUrl, formData);
var respBody = httpResp.ToString();
return respBody;
}
}
Related
I have a Problem Updating the Server details in the dataset of the uploaded power bi Report. Please Help.
Here I used 2 approaches.
Approach 1
Used the below method in Microsoft.PowerBI.Api.V2
UpdateDatasourcesInGroup
public static void UpdateSqlDatabaseConnectionString(string WorkspaceId, string DatasetId, string Server, string Database)
{
var tokenCredentials = GetTokenCredentials();
using (var pbiClient = new PowerBIClient(new Uri(ApiUrl), tokenCredentials.Item1))
{
Datasource targetDatasource = pbiClient.Datasets.GetDatasourcesInGroup(WorkspaceId, DatasetId).Value.First();
string currentServer = targetDatasource.ConnectionDetails.Server;
string currentDatabase = targetDatasource.ConnectionDetails.Database;
if (Server.ToLower().Equals(currentServer.ToLower()) && Database.ToLower().Equals(currentDatabase.ToLower()))
{
Console.WriteLine("New server and database name are the same as the old names");
return;
}
DatasourceConnectionDetails connectionDetails = new DatasourceConnectionDetails
{
Database = Database,
Server = Server
};
UpdateDatasourceConnectionRequest updateConnRequest =
new UpdateDatasourceConnectionRequest
{
DatasourceSelector = targetDatasource,
ConnectionDetails = connectionDetails
};
UpdateDatasourcesRequest updateDatasourcesRequest = new UpdateDatasourcesRequest(updateConnRequest);
pbiClient.Datasets.UpdateDatasourcesInGroup(WorkspaceId, DatasetId, updateDatasourcesRequest);
}
}
Captured the request in fiddler
Request:
{
"updateDetails": [
{
"connectionDetails": {
"server": "OldServer",
"database": "OldDatabase"
},
"datasourceSelector": {
"datasourceType": "Sql",
"connectionDetails": {
"server": "NewServer",
"database": "NewDatabase"
},
"gatewayId": "gatewayId",
"datasourceId": "datasourceId"
}
}
]
}
Response:
{"error":{"code":"InvalidRequest","message":"Operation is not supported for selector # - connection details contains parameters"}}
Approach 2
Called the Power BI rest API
public static void UpdateServerName_RestAPI(string groupId, string datasetId)
{
var tokenCredentials = InitPowerBI_New();
HttpResponseMessage response;
try
{
var httpClient = new HttpClient();
// Add AccessToken in header
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokenCredentials.Item2);
var url = $"https://api.powerbi.com/v1.0/myorg/groups/{groupId}/datasets/{datasetId}/Default.UpdateDatasources";
var form = prepareJsonForUpdateServerDetails();
var content = new StringContent(form, Encoding.UTF8, "application/json");
response = httpClient.PostAsync(url, content).Result;
response.EnsureSuccessStatusCode();
httpClient.Dispose();
}
catch (Exception)
{
}
}
Request :
{
"UpdateDetails":[
{
"datasourceSelector":{
"datasourceType":"Sql",
"connectionDetails":{
"server":"OldServer",
"database":"OldDatabase"
}
},
"connectionDetails":{
"server":"NewServer",
"database":"NewDatabase"
}
}
]
}
Response:
{"error":{"code":"InvalidRequest","message":"Operation is not supported for selector # - connection details contains parameters"}}
Please Help.
Thank You
This happens when the report queries connect to a database using a parameter. In this case you cannot update the connection, rather update the parameters or remove the connection from the query.
So, if you see in your query code something like Sql.Database(#"ServerName",... you must use Client.Datasets.UpdateParameters and pass in for details:
UpdateMashupParameterDetails request = new()
{
Name = "ServerName",
NewValue = "newServerName"
};
and similarly for database.
Further details https://learn.microsoft.com/en-us/rest/api/power-bi/datasets/update-parameters
I dont get any response using client.PostAsync.
I created button in xamarin forms. It should send to server some sentences(json) and return info about them(again in json).
Button code:
private async void button_Analyze_Clicked(object sender, EventArgs e)
{
Request req = new Request()
{
UserId = this.UserId,
Language = Convert.ToString(picker_Language.SelectedItem) + ".",
Text = Convert.ToString(editor1.Text)
};
string jsonStr = JsonConvert.SerializeObject(req);
Dictionary<string, string> dict = new Dictionary<string, string>();
dict.Add("s", jsonStr);
FormUrlEncodedContent form = new FormUrlEncodedContent(dict);
HttpResponseMessage response = await client.PostAsync(markTextUrl, form).ConfigureAwait(false);
string result = await response.Content.ReadAsStringAsync();
Answer answ = JsonConvert.DeserializeObject<Answer>(result);
answersList.Add(answ);
await DisplayAlert("", " ", "Ok");
}
Controller code:
public string MarkText(string s) //работа с запросом из приложения
{
Request req = JsonConvert.DeserializeObject<Request>(s);
if (req != null)
{
Models.Request request = new Models.Request()
{
Text = req.Text,
Lang = req.Language,
UserId = int.Parse(req.UserId)
};
AnalyzeRequest(request);
Answer answ = new Answer()
{
Language = req.Language,
Text = req.Text,
Sentences = db.Histories.Last().Text,
Labels = db.Histories.Last().Label
};
return JsonConvert.SerializeObject(answ);
}
return null;
}
Problem is this code
HttpResponseMessage response = await client.PostAsync(markTextUrl, form).ConfigureAwait(false);
never return response and it doesnt reach controller function. If I wait for this code to complete Ill get System.OperationCanceledExeption:"The operation was canceled"
Solved!!! - See last edit.
In my MVC app I make calls out to a Web API service with HMAC Authentication Filterign. My Get (GetMultipleItemsRequest) works, but my Post does not. If I turn off HMAC authentication filtering all of them work. I'm not sure why the POSTS do not work, but the GETs do.
I make the GET call from my code like this (this one works):
var productsClient = new RestClient<Role>(System.Configuration.ConfigurationManager.AppSettings["WebApiUrl"],
"xxxxxxxxxxxxxxx", true);
var getManyResult = productsClient.GetMultipleItemsRequest("api/Role").Result;
I make the POST call from my code like this (this one only works when I turn off HMAC):
private RestClient<Profile> profileClient = new RestClient<Profile>(System.Configuration.ConfigurationManager.AppSettings["WebApiUrl"],
"xxxxxxxxxxxxxxx", true);
[HttpPost]
public ActionResult ProfileImport(IEnumerable<HttpPostedFileBase> files)
{
//...
var postResult = profileClient.PostRequest("api/Profile", newProfile).Result;
}
My RestClient builds like this:
public class RestClient<T> where T : class
{
//...
private void SetupClient(HttpClient client, string methodName, string apiUrl, T content = null)
{
const string secretTokenName = "SecretToken";
client.BaseAddress = new Uri(_baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
if (_hmacSecret)
{
client.DefaultRequestHeaders.Date = DateTime.UtcNow;
var datePart = client.DefaultRequestHeaders.Date.Value.UtcDateTime.ToString(CultureInfo.InvariantCulture);
var fullUri = _baseAddress + apiUrl;
var contentMD5 = "";
if (content != null)
{
var json = new JavaScriptSerializer().Serialize(content);
contentMD5 = Hashing.GetHashMD5OfString(json); // <--- Javascript serialized version is hashed
}
var messageRepresentation =
methodName + "\n" +
contentMD5 + "\n" +
datePart + "\n" +
fullUri;
var sharedSecretValue = ConfigurationManager.AppSettings[_sharedSecretName];
var hmac = Hashing.GetHashHMACSHA256OfString(messageRepresentation, sharedSecretValue);
client.DefaultRequestHeaders.Add(secretTokenName, hmac);
}
else if (!string.IsNullOrWhiteSpace(_sharedSecretName))
{
var sharedSecretValue = ConfigurationManager.AppSettings[_sharedSecretName];
client.DefaultRequestHeaders.Add(secretTokenName, sharedSecretValue);
}
}
public async Task<T[]> GetMultipleItemsRequest(string apiUrl)
{
T[] result = null;
try
{
using (var client = new HttpClient())
{
SetupClient(client, "GET", apiUrl);
var response = await client.GetAsync(apiUrl).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
await response.Content.ReadAsStringAsync().ContinueWith((Task<string> x) =>
{
if (x.IsFaulted)
throw x.Exception;
result = JsonConvert.DeserializeObject<T[]>(x.Result);
});
}
}
catch (HttpRequestException exception)
{
if (exception.Message.Contains("401 (Unauthorized)"))
{
}
else if (exception.Message.Contains("403 (Forbidden)"))
{
}
}
catch (Exception)
{
}
return result;
}
public async Task<T> PostRequest(string apiUrl, T postObject)
{
T result = null;
try
{
using (var client = new HttpClient())
{
SetupClient(client, "POST", apiUrl, postObject);
var response = await client.PostAsync(apiUrl, postObject, new JsonMediaTypeFormatter()).ConfigureAwait(false); //<--- not javascript formatted
response.EnsureSuccessStatusCode();
await response.Content.ReadAsStringAsync().ContinueWith((Task<string> x) =>
{
if (x.IsFaulted)
throw x.Exception;
result = JsonConvert.DeserializeObject<T>(x.Result);
});
}
}
catch (HttpRequestException exception)
{
if (exception.Message.Contains("401 (Unauthorized)"))
{
}
else if (exception.Message.Contains("403 (Forbidden)"))
{
}
}
catch (Exception)
{
}
return result;
}
//...
}
My Web API Controller is defined like this:
[SecretAuthenticationFilter(SharedSecretName = "xxxxxxxxxxxxxxx", HmacSecret = true)]
public class ProfileController : ApiController
{
[HttpPost]
[ResponseType(typeof(Profile))]
public IHttpActionResult PostProfile(Profile Profile)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
GuidValue = Guid.NewGuid();
Resource res = new Resource();
res.ResourceId = GuidValue;
var data23 = Resourceservices.Insert(res);
Profile.ProfileId = data23.ResourceId;
_profileservices.Insert(Profile);
return CreatedAtRoute("DefaultApi", new { id = Profile.ProfileId }, Profile);
}
}
Here is some of what SecretAuthenticationFilter does:
//now try to read the content as string
string content = actionContext.Request.Content.ReadAsStringAsync().Result;
var contentMD5 = content == "" ? "" : Hashing.GetHashMD5OfString(content); //<-- Hashing the non-JavaScriptSerialized
var datePart = "";
var requestDate = DateTime.Now.AddDays(-2);
if (actionContext.Request.Headers.Date != null)
{
requestDate = actionContext.Request.Headers.Date.Value.UtcDateTime;
datePart = requestDate.ToString(CultureInfo.InvariantCulture);
}
var methodName = actionContext.Request.Method.Method;
var fullUri = actionContext.Request.RequestUri.ToString();
var messageRepresentation =
methodName + "\n" +
contentMD5 + "\n" +
datePart + "\n" +
fullUri;
var expectedValue = Hashing.GetHashHMACSHA256OfString(messageRepresentation, sharedSecretValue);
// Are the hmacs the same, and have we received it within +/- 5 mins (sending and
// receiving servers may not have exactly the same time)
if (messageSecretValue == expectedValue
&& requestDate > DateTime.UtcNow.AddMinutes(-5)
&& requestDate < DateTime.UtcNow.AddMinutes(5))
goodRequest = true;
Any idea why HMAC doesn't work for the POST?
EDIT:
When SecretAuthenticationFilter tries to compare the HMAC sent, with what it thinks the HMAC should be they don't match. The reason is the MD5Hash of the content doesn't match the MD5Hash of the received content. The RestClient hashes the content using a JavaScriptSerializer.Serialized version of the content, but then the PostRequest passes the object as JsonMediaTypeFormatted.
These two types don't get formatted the same. For instance, the JavaScriptSerializer give's us dates like this:
\"EnteredDate\":\"\/Date(1434642998639)\/\"
The passed content has dates like this:
\"EnteredDate\":\"2015-06-18T11:56:38.6390407-04:00\"
I guess I need the hash to use the same data that's passed, so the Filter on the other end can confirm it correctly. Thoughts?
EDIT:
Found the answer, I needed to change the SetupClient code from using this line:
var json = new JavaScriptSerializer().Serialize(content);
contentMD5 = Hashing.GetHashMD5OfString(json);
To using this:
var json = JsonConvert.SerializeObject(content);
contentMD5 = Hashing.GetHashMD5OfString(json);
Now the sent content (formatted via JSON) will match the hashed content.
I was not the person who wrote this code originally. :)
Found the answer, I needed to change the SetupClient code from using this line:
var json = new JavaScriptSerializer().Serialize(content);
contentMD5 = Hashing.GetHashMD5OfString(json);
To using this:
var json = JsonConvert.SerializeObject(content);
contentMD5 = Hashing.GetHashMD5OfString(json);
Now the content used for the hash will be formatted as JSON and will match the sent content (which is also formatted via JSON).
last time I posted a question on here everyone provided some great guidance on getting my problem solved. Move forward in time and here is another. I'm attempting to redo a small helper tool I have that checks URL's and Files against VirusTotal to get some basic information. The code below works quite well but locks up the UI. I was told that I should look into Rx and am enjoying reading up on it but cannot seem to get my head wrapped around it. So now here is where the question comes in, what is the best way to design the following code to make it utilize Rx so that it is asynchronous and leaves my UI alone while it does it's thing. VirusTotal also utilizes multilevel JSON for responses so if anyone has a nice way of integrating that into this that would even be better.
class Virustotal
{
private string APIKey = "REMOVED";
private string FileReportURL = "https://www.virustotal.com/vtapi/v2/file/report";
private string URLReportURL = "http://www.virustotal.com/vtapi/v2/url/report";
private string URLSubmitURL = "https://www.virustotal.com/vtapi/v2/url/scan";
WebRequest theRequest;
HttpWebResponse theResponse;
ArrayList theQueryData;
public string GetFileReport(string checksum) // Gets latest report of file from VT using a hash (MD5 / SHA1 / SHA256)
{
this.WebPostRequest(this.FileReportURL);
this.Add("resource", checksum);
return this.GetResponse();
}
public string GetURLReport(string url) // Gets latest report of URL from VT
{
this.WebPostRequest(this.URLReportURL);
this.Add("resource", url);
this.Add("scan", "1"); //Automatically submits to VT if no result found
return this.GetResponse();
}
public string SubmitURL(string url) // Submits URL to VT for insertion to scanning queue
{
this.WebPostRequest(this.URLSubmitURL);
this.Add("url", url);
return this.GetResponse();
}
public string SubmitFile() // Submits File to VT for insertion to scanning queue
{
// File Upload code needed
return this.GetResponse();
}
private void WebPostRequest(string url)
{
theRequest = WebRequest.Create(url);
theRequest.Method = "POST";
theQueryData = new ArrayList();
this.Add("apikey", APIKey);
}
private void Add(string key, string value)
{
theQueryData.Add(String.Format("{0}={1}", key, Uri.EscapeDataString(value)));
}
private string GetResponse()
{
// Set the encoding type
theRequest.ContentType="application/x-www-form-urlencoded";
// Build a string containing all the parameters
string Parameters = String.Join("&",(String[]) theQueryData.ToArray(typeof(string)));
theRequest.ContentLength = Parameters.Length;
// We write the parameters into the request
StreamWriter sw = new StreamWriter(theRequest.GetRequestStream());
sw.Write(Parameters);
sw.Close();
// Execute the query
theResponse = (HttpWebResponse)theRequest.GetResponse();
StreamReader sr = new StreamReader(theResponse.GetResponseStream());
return sr.ReadToEnd();
}
}
Your code is poorly written which makes it more difficult to make it asynchronous - primarily the three class-level variables. When coding in Rx you want to think "functional programming" and not "OOP" - so no class-level variables.
So, what I've done is this - I've recoded the GetResponse method to encapsulate all of the state into a single call - and I've made it return IObservable<string> rather than just string.
The public functions can now be written like this:
public IObservable<string> GetFileReport(string checksum)
{
return this.GetResponse(this.FileReportURL,
new Dictionary<string, string>() { { "resource", checksum }, });
}
public IObservable<string> GetURLReport(string url)
{
return this.GetResponse(this.URLReportURL,
new Dictionary<string, string>()
{ { "resource", url }, { "scan", "1" }, });
}
public IObservable<string> SubmitURL(string url)
{
return this.GetResponse(this.URLSubmitURL,
new Dictionary<string, string>() { { "url", url }, });
}
public IObservable<string> SubmitFile()
{
return this.GetResponse("UNKNOWNURL", new Dictionary<string, string>());
}
And GetResponse looks like this:
private IObservable<string> GetResponse(
string url,
Dictionary<string, string> theQueryData)
{
return Observable.Start(() =>
{
var theRequest = WebRequest.Create(url);
theRequest.Method = "POST";
theRequest.ContentType="application/x-www-form-urlencoded";
theQueryData.Add("apikey", APIKey);
string Parameters = String.Join("&",
theQueryData.Select(x =>
String.Format("{0}={1}", x.Key, x.Value)));
theRequest.ContentLength = Parameters.Length;
using (var sw = new StreamWriter(theRequest.GetRequestStream()))
{
sw.Write(Parameters);
sw.Close();
}
using (var theResponse = (HttpWebResponse)theRequest.GetResponse())
{
using (var sr = new StreamReader(theResponse.GetResponseStream()))
{
return sr.ReadToEnd();
}
}
});
}
I haven't actually tested this - I don't have the APIKEY for starters - but it should work OK. Let me know how you go.
Working Platform: ASP.NET 4.0 C# ( Framework Agnostic )
Google GData is my dependency
using Google.GData.Client;
using Google.GData.Extensions;
using Google.GData.Documents;
I have two pages Auth and List.
Auth redirects to Google Server like this
public ActionResult Auth()
{
var target = Request.Url.ToString().ToLowerInvariant().Replace("auth", "list");
var scope = "https://docs.google.com/feeds/";
bool secure = false, session = true;
var authSubUrl = AuthSubUtil.getRequestUrl(target, scope, secure, session);
return new RedirectResult(authSubUrl);
}
Now it reaches the List Page if Authentication is successful.
public ActionResult List()
{
if (Request.QueryString["token"] != null)
{
String singleUseToken = Request.QueryString["token"];
string consumerKey = "www.blahblah.net";
string consumerSecret = "my_key";
string sessionToken = AuthSubUtil.exchangeForSessionToken(singleUseToken, null).ToString();
var authFactory = new GOAuthRequestFactory("writely", "qwd-asd-01");
authFactory.Token = sessionToken;
authFactory.ConsumerKey = consumerKey;
authFactory.ConsumerSecret = consumerSecret;
//authFactory.TokenSecret = "";
try
{
var service = new DocumentsService(authFactory.ApplicationName) { RequestFactory = authFactory };
var query = new DocumentsListQuery();
query.Title = "project";
var feed = service.Query(query);
var result = feed.Entries.ToList().ConvertAll(a => a.Title.Text);
return View(result);
}
catch (GDataRequestException gdre)
{
throw;
}
}
}
This fails at the line var feed = service.Query(query); with the error
Execution of request failed: https://docs.google.com/feeds/default/private/full?title=project
The HttpStatusCode recieved on the catch block is HttpStatusCode.Unauthorized
What is wrong with this code? Do I need to get TokenSecret? If so how?
You need to request a token from Google and use it to intialize your DocumentsService instance.
Here's an example using Google's ContactsService. It should be the same for the DocumentsService.
Service service = new ContactsService("My Contacts Application");
service.setUserCredentials("your_email_address_here#gmail.com", "yourpassword");
var token = service.QueryClientLoginToken();
service.SetAuthenticationToken(token);
But as you mentioned, you are using AuthSub. I jumped the gun a bit too fast.
I see that you are requesting a session token. According to the documentation of the API you must use the session token to authenticate requests to the service by placing the token in the Authorization header. After you've set the session token, you can use the Google Data APIs client library.
Here's a complete example (by Google) on how to use AuthSub with the .NET client library:
http://code.google.com/intl/nl-NL/apis/gdata/articles/authsub_dotnet.html
Let me include a shortened example:
GAuthSubRequestFactory authFactory =
new GAuthSubRequestFactory("cl", "TesterApp");
authFactory.Token = (String) Session["token"];
CalendarService service = new CalendarService(authFactory.ApplicationName);
service.RequestFactory = authFactory;
EventQuery query = new EventQuery();
query.Uri = new Uri("http://www.google.com/calendar/feeds/default/private/full");
EventFeed calFeed = service.Query(query);
foreach (Google.GData.Calendar.EventEntry entry in calFeed.Entries)
{
//...
}
And if I see correctly your example code pretty follows the same steps, except that you set the ConsumerKey and ConsumerSecret for the AuthFactory which is not done in the example by Google.
Used the 3-legged OAuth in the Google Data Protocol Client Libraries
Sample Code
string CONSUMER_KEY = "www.bherila.net";
string CONSUMER_SECRET = "RpKF7ykWt8C6At74TR4_wyIb";
string APPLICATION_NAME = "bwh-wssearch-01";
string SCOPE = "https://docs.google.com/feeds/";
public ActionResult Auth()
{
string callbackURL = String.Format("{0}{1}", Request.Url.ToString(), "List");
OAuthParameters parameters = new OAuthParameters()
{
ConsumerKey = CONSUMER_KEY,
ConsumerSecret = CONSUMER_SECRET,
Scope = SCOPE,
Callback = callbackURL,
SignatureMethod = "HMAC-SHA1"
};
OAuthUtil.GetUnauthorizedRequestToken(parameters);
string authorizationUrl = OAuthUtil.CreateUserAuthorizationUrl(parameters);
Session["parameters"] = parameters;
ViewBag.AuthUrl = authorizationUrl;
return View();
}
public ActionResult List()
{
if (Session["parameters"] != null)
{
OAuthParameters parameters = Session["parameters"] as OAuthParameters;
OAuthUtil.UpdateOAuthParametersFromCallback(Request.Url.Query, parameters);
try
{
OAuthUtil.GetAccessToken(parameters);
GOAuthRequestFactory authFactory = new GOAuthRequestFactory("writely", APPLICATION_NAME, parameters);
var service = new DocumentsService(authFactory.ApplicationName);
service.RequestFactory = authFactory;
var query = new DocumentsListQuery();
//query.Title = "recipe";
var feed = service.Query(query);
var docs = new List<string>();
foreach (DocumentEntry entry in feed.Entries)
{
docs.Add(entry.Title.Text);
}
//var result = feed.Entries.ToList().ConvertAll(a => a.Title.Text);
return View(docs);
}
catch (GDataRequestException gdre)
{
HttpWebResponse response = (HttpWebResponse)gdre.Response;
//bad auth token, clear session and refresh the page
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
Session.Clear();
Response.Write(gdre.Message);
}
else
{
Response.Write("Error processing request: " + gdre.ToString());
}
throw;
}
}
else
{
return RedirectToAction("Index");
}
}
This 2-legged sample never worked for me for google docs.