I'm developping a Facebook Application (using ASP.NET C# and Nathan Totten's Facebook C# SDK) and trying to access to extended permissions.
I tried on localhost (with an existing app in facebook), and everybody works. But when I try to use it directly in facebook, I obtain a blank page (i'm still connected on facebook).
Here is my code :
Page/aspx :
protected void btn_ask_question_Click(object sender, EventArgs e)
{
if (ControllerAccess.testUserConnected())
{
if (txt_ask_question.InnerText != "")
{
Dictionary<string, object> action = new Dictionary<string,object>();
action.Add("action", "askQuestion");
action.Add("message", txt_ask_question.InnerText);
action.Add("idTheme", ddl_choose_question_category.SelectedValue);
HttpContext.Current.Session["ActionToDo"] = action;
String s = Controller.GetExtendedPermission2(this, ControllerAccess.getScopeByAction("askQuestion"));
try{
Response.Redirect(s, false);
} catch(Exception ex)
{
}
}
}
}
In my Page_Load() :
if (HttpContext.Current.Session["ActionToDo"] != null)
{
Dictionary<string, object> action = HttpContext.Current.Session["ActionToDo"] as Dictionary<string, object>;
String s = action["action"].ToString();
switch (s)
{
case "askQuestion":
Guid idTheme;
Boolean themeExists = Guid.TryParse(action["idTheme"].ToString(), out idTheme);
if(themeExists)
{
askQuestion(action["message"].ToString(), idTheme);
lbl_errors.Text = "Votre question a bien été posée";
}
break;
default:
break;
}
HttpContext.Current.Session["ActionToDo"] = null;
}
In Control.cs :
public static string GetCustomOAuthDialogParameters(string AppID, string RedirectURI, string Scope, string State)
{
string CustomParameters = "?client_id=" + AppID + "&redirect_uri=" + RedirectURI + "&scope=" + Scope + "&state=" + State;
return CustomParameters;
}
public static void GetExtendedPermission(Page page, String scope)
{
ecritureFichier("GetExtendedPermission");
Label lbl_errors = page.Form.FindControl("lbl_errors") as Label;
string OAuthDialogAbsoluteURL = "";
try
{
string OAuthDialogURL = "https://www.facebook.com/dialog/oauth";
string PageLocation = GetCurrentPageFacebookPublishedPath(page.Request); //The redirect page (eg: https://apps.facebook.com/democsharpsdk/TestsExtendedPermission.aspx)
string UniqueReferenceCode = Guid.NewGuid().ToString();
OAuthDialogAbsoluteURL = OAuthDialogURL + GetCustomOAuthDialogParameters(AppID, PageLocation, scope, UniqueReferenceCode);
page.Response.Redirect(OAuthDialogAbsoluteURL, false);
}
catch (Exception exp)
{
lbl_errors.Text += "Erreur Catchée via ASP.NET : " + exp.Message;
}
}
The blank page appears when I use this line : page.Response.Redirect(OAuthDialogAbsoluteURL, false);
But I log all my steps and my OAuthDialogAbsoluteURL is correct :
https://www.facebook.com/dialog/oauth?client_id=XXXXXXXXXXXXXXXXX&redirect_uri=https://apps.facebook.com/name_of_my_app&scope=email&state=0443030f-dddd-4fe6-9d6c-9454409d01b3
When I type it into the adress bar manually, everything works correctly.
Do you have any idea about the difference between local version and published version or why the redirect doesn't work? Maybe facebook block some requests?
Thanks.
Make sure you settings point to the hosted version if you want to use the app to test different environments. Facebook doesn't let you authorise a user from a site that isn't connect to your app for security reasons.
Normally, you would see an error like "URL isn't owned by Application" or similar.
I finally resolved my problem usingChrome Debugger. The error was :
Refused to display document because display forbidden by X-Frame-Options
I used Javascript to fix it, and did my redirection like this :
Response.Write("<script>");
Response.Write("window.open('"+redirect+"','_top')");
Response.Write("</script>");
Hope it'll help some people.
Related
We are converting our old webservices (asmx) to use https, trying to get it working locally.
I have a test app I wrote in winforms jsut to call the service.
Trying to modify it to call via https, following this pattern
https://www.codeproject.com/Questions/751059/Call-https-Webservice-in-Console-Application
(Not sure I trust this pattern 100%, but it's a place to start, looks like it's trying to ignore all errors)
private void button8_Click(object sender, EventArgs e)
{
System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();
}
public class TrustAllCertificatePolicy : System.Net.ICertificatePolicy
{
public TrustAllCertificatePolicy()
{
AdStudent.ADStudent ws = new AdStudent.ADStudent();
ws.Url = "https://localhost/JCDCADStudent/ADStudent.asmx";
try
{
string str = ws.GetGuidString("Brown.Eric");
MessageBox.Show("secure guid is " + str + ".");
}
catch (Exception ex)
{
string cleanMsg = GetCleanMsg(ex.Message);
MessageBox.Show("\n\n " + cleanMsg + "\n\n\n\n\nProgrammer Msg:\n\n" + ex.Message, "Error");
}
}
public bool CheckValidationResult(ServicePoint sp, X509Certificate cert, WebRequest req, int problem)
{
return true;
}
private string GetCleanMsg(string message)
{
string startTag = "<ClientMsg>";
string endTag = "</ClientMsg>";
Int32 start = message.IndexOf(startTag) + startTag.Length;
Int32 end = message.IndexOf(endTag);
try
{
return message.Substring(start, end - start);
}
catch (Exception ex)
{
return "UNABLE TO PARSE MESSAGE : \n " + message;
}
}
}
}
I get the exception
{"The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel."}
inner exception
The remote certificate is invalid according to the validation procedure.
When I try and just run the HTTPS in the browser, it complains that like the title or subject field is not formatted correctly. but If I tell it to ignore that it opens the web service, I'm guessing that is the problem,
How do I fix it?
How do I get a better error like the one the browser gives me, to report in my app?
The cert was provided by our IT team, I'm not sure I can get it changed, it's a long-standing cert used for Dev.
Maybe I can get it regenerated correctly (it's applied to our machines via network policy)
I used google.cloud.storage for .mp3 files. I tried it before and it worked.
now I writed another new function that uses the existing storage function.
everything was suppose to work but I get this weird error:
"Google.Apis.Requests.RequestError
text-to-speach#XXXXXXXXXXX.iam.gserviceaccount.com does not have storage.objects.create access to objectsound/voiceAnimals20.mp3. [403]"
I dont know what to begin with. can anybody help me?
the Ok storage function is here:
public static string VoiceStorage(int catId, string URL,
Dictionary<string, int> voicesCounter)
{
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS",
#"C:\wordproject-XXXXXXXXXX.json");
// upload the image storage
//----------------
string voiceName;
voiceName = "voice" + BLLcategory.GetCategoryById(catId).CategoryName
+ voicesCounter[BLLcategory.GetCategoryById(catId).CategoryName]++ +
".mp3";
string bucketName = "XXXXXXXX";
var storage = StorageClient.Create();
using (var f = File.OpenRead(URL))
{
try
{
var res = storage.UploadObject(bucketName, voiceName, null,
f);
URL = "https://storage.cloud.google.com/" + bucketName + "/" +
voiceName;
}
catch (Exception e)
{
throw e;
}
}
return URL;
}
the new not working function is:
private void button12_Click(object sender, EventArgs e)
{
foreach (COMimageObject obj in BLLobject.GetObjects())
{
if(obj.VoiceURL==null)
{
try
{
string url=BLLtextToSpeach.TextToSpeach(obj.Name);
url=BLLtextToSpeach.VoiceStorage(
BLLimage.GetImageById(obj.ImageID).CategoryID,
url, voicesCounter);
BLLobject.UpdateVoiceURL(obj.ObjectId, url);
}
catch (Exception)
{
throw;
}
}
}
}
the catch happening after the line with url=BLLtextToSpeach.VoiceStorage
tnx!!
What the error mean is that the service account of the text-to-speach api doesn't have create access on the objectsound bucket. Go to the bucket permissions and add the text-to-speach service account with storage creator rights.
When you get this error:
[403] Errors [ Message[.................iam.gserviceaccount.com does
not have storage.buckets.list access to the Google Cloud project.
you need to have permissions in your service account from the IAM to read the buckets
storage.buckets.get Read bucket metadata, excluding IAM policies.
storage.buckets.list List buckets in a project. Also read bucket
metadata,
https://cloud.google.com/storage/docs/access-control/iam-permissions
The "Firebase Admin" will enable all necessary permissions.
using c# .net4.0
I am aware the asp.net button with in the gridview of type link does a post to the same page when clicked, i need make several manipualtion on server side before actually redirecting user to an external site hence i can't use Hyperlinkfield. What i need now is the external site htm page should open up in sperate window. I tried the following which works but source site's fonts get bigger???
heres what i tried
Response.Write("<script>");
Response.Write("window.open('http://www.google.co.uk','_blank')");
Response.Write("</script>");
Response.End();
may be i need a refresh source site??
Thanks
# Curt Here is the code for Hyperlink i tired
on page load added new button on gridview
HyperLinkField LinksBoundField = new HyperLinkField();
string[] dataNavigateUrlFields = {"link"};
LinksBoundField.DataTextField = "link";
LinksBoundField.DataNavigateUrlFields = dataNavigateUrlFields;
LinksBoundField.DataNavigateUrlFormatString = "http://" + Helper.IP + "/" + Helper.SiteName + "/" + Helper.ThirdPartyAccess + "?dispage={0}&token=" + Session["Token"];
LinksBoundField.HeaderText = "Link";
LinksBoundField.Target = "_blank";
GridViewLinkedService.Columns.Add(LinksBoundField);
GridViewLinkedService.RowDataBound += new GridViewRowEventHandler(grdView_RowDataBound);
to append external values (refe and appid) to navigate url
protected void grdView_RowDataBound(object sender, GridViewRowEventArgs e)
{
string strvalue = "";
string strvalue1 = "";
string strRef = "";
string strAppId = "";
foreach (GridViewRow row in GridViewLinkedService.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
//reference and appid
strAppId = row.Cells[0].Text;
strRef = row.Cells[1].Text;
HyperLink grdviewLink = (HyperLink)row.Cells[5].Controls[0];
strvalue = grdviewLink.NavigateUrl;
strvalue1 = Regex.Replace(strvalue, "(.*dispage\\=).*/(services.*)", "$1$2");
grdviewLink.NavigateUrl = "~/My Service/FillerPage.aspx?nurl=" + strvalue1 + "&AppID=" + strAppId.ToString() + "&Ref=" + strRef.ToString();
}
}
}
public partial class FillerPage : System.Web.UI.Page
{
private string refno = null;
private string appid = null;
private string nurl = null;
private string strvalue1 = "";
private string newtoken = "";
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString.GetValues("AppID") != null)
{
appid = Request.QueryString.GetValues("AppID")[0].ToString();
}
if (Request.QueryString.GetValues("Ref") != null)
{
refno = Request.QueryString.GetValues("Ref")[0].ToString();
}
if (Request.QueryString.GetValues("nurl") != null)
{
nurl = Request.QueryString.GetValues("nurl")[0].ToString();
}
while receiving the long url it gets messed up(same query multiple times and all jumbled up)?????
is there a better way to pass parameters ???
you need to register script not response.write
so the code for you is :
ClientScript.RegisterStartupScript(this.GetType(), Guid.NewGuid().ToString(), "<script language=JavaScript>window.open('http://www.google.co.uk','_blank')</script>");
Read more : ClientScriptManager.RegisterStartupScript.
In a situation where I need to run server side code, before then opening a new page, I sometimes create a Generic Handler File and link to this with a HyperLink, passing variables as Query Strings. Therefore something like:
/MyGenericFile.ashx?id=123
In this file, I would have some scripting that needs to be carried out, followed by a Response.Redirect().
As long as the HyperLink is set to target="_blank", the user won't even know they've been to a generic file, which is then redirected. It will appear as they've opened a new link.
Therefore the process would be:
User clicks link to .ashx file
Link opens in new window
Necessary scripting is ran
Response.Redirect() is ran
User is taken to web page (www.google.com in your example)
I believe this same process is used by advert management systems to help track clicks.
You can register a script to run on page load with ClientScriptManager.RegisterStartupScript.
I'm trying to build a Facebook 'fangate' tab or 'reveal' tab for a Facebook page.
You know how it goes - when a user visits the page, they are shown one bit of content if they haven't yet clicked 'Like' and another once they have.
I'm not a PHP guy so I'm attempting to do this with the Facebook C# SDK (http://facebooksdk.codeplex.com) in Visual Studio 2010. I'm fairly new to .NET too so I'm not doing so well with this!
I have to admit I've been cutting and pasting code from all over the place to get this to work and I think I'm almost there but I'm not getting this error:
Invalid signed request.
Line 82: var DecodedSignedRequest = FacebookSignedRequest.Parse(current, FacebookWebContext.Current.SignedRequest.Data.ToString());
Here's my code:
var settings = ConfigurationManager.GetSection("facebookSettings");
var current = settings as IFacebookApplication;
var DecodedSignedRequest = FacebookSignedRequest.Parse(current, FacebookWebContext.Current.SignedRequest.Data.ToString());
dynamic SignedRequestData = DecodedSignedRequest.Data;
var RawRequestData = (IDictionary<string, object>)SignedRequestData;
string currentFacebookPageID = current.AppId;
bool currentFacebookPageLiked = false;
if (RawRequestData.ContainsKey("page") == true)
{
Facebook.JsonObject RawPageData = (Facebook.JsonObject)RawRequestData["page"];
if (RawPageData.ContainsKey("id") == true)
currentFacebookPageID = (string)RawPageData["id"];
if (RawPageData.ContainsKey("liked") == true)
currentFacebookPageLiked = (bool)RawPageData["liked"];
}
if (currentFacebookPageLiked)
{
//Do some stuff for fans
}
else
{
//Do some stuff for non-fans
}
All the Facebook settings are in my web.config file and I have checked that the AppID and AppSecret are correct.
Can anyone offer me any insight into this issue please? Is there a better way of doing this that I've not yet found?
Many thanks in advance for any help.
OK, I've sorted it out - but I'm not sure why. I have a feeling that the Facebook C# SDK screws around with the signed request in some way. If I get the signed request using Request.Forms["signed_request"] it all seems to work.
I'll share my working code in the hope that it will help others with the same problem.
//Pull in the facebook app settings from the web.config file
var settings = ConfigurationManager.GetSection("facebookSettings");
var current = settings as IFacebookApplication;
//Set up some stuff for later
string currentFacebookPageID = current.AppId;
bool currentFacebookPageLiked = false;
//Get the signed request
FacebookSignedRequest SignedRequest = FacebookSignedRequest.Parse(current, Request.Form["signed_request"]);
dynamic SignedRequestData = SignedRequest.Data;
//extract what we need from the request
var RawRequestData = (IDictionary<string, object>)SignedRequestData;
//Check to see if we've got the data we need
if (RawRequestData.ContainsKey("page") == true)
{
//We do, lets examine it and set the boolean as appropriate
Facebook.JsonObject RawPageData = (Facebook.JsonObject)RawRequestData["page"];
if (RawPageData.ContainsKey("id") == true)
currentFacebookPageID = (string)RawPageData["id"];
if (RawPageData.ContainsKey("liked") == true)
currentFacebookPageLiked = (bool)RawPageData["liked"];
}
if (currentFacebookPageLiked)
{
//Do some stuff for fans
lblName.Text = "Hi " + result.first_name + " - You are a fan";
}
else
{
//Do some stuff for non-fans
lblName.Text = "Hi " + result.first_name + " - please click the like button";
}
This is the code i used and it worked great for me.
protected bool IsPageLiked()
{
var current = ConfigurationManager.GetSection("facebookSettings")
as IFacebookApplication;
dynamic signedRequest = FacebookSignedRequest.Parse(current, Request);
try
{
return signedRequest.Data.page.liked;
}
catch (Exception)
{
return false;
}
}
I am struggling to get off with ground with some Facebook dev work. All I want to do is retireve some user info for the logged in user. This is the code I got from another site & it looks fine to me, however is always returns IsConnected() to be false.
I am running this code within an iframe on my facebook app (in sandbox mode)
private const string APPLICATION_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxx";
private const string SECRET_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxx";
public Facebook.Rest.Api Api;
private Facebook.Session.ConnectSession _connectSession;
protected void Page_Load(object sender, EventArgs e)
{
_connectSession = new Facebook.Session.ConnectSession(APPLICATION_KEY,SECRET_KEY);
if (!_connectSession.IsConnected())
{
lit.Text = "Please sign-in with Facebook.";
}
else
{
try
{
Api = new Facebook.Rest.Api(_connectSession);
Facebook.Schema.user u = Api.Users.GetInfo();
img.ImageUrl = u.pic_square;
lit.Text = string.Format("Welcome, " + u.name);
}
catch (Exception ex)
{
lit.Text = ex.Message;
}
}
}
See this other SO question about a similar problem. The poster apparently found what he was looking for, but didn't know how to implement it. You may be able to do so, since there's a lot of information in the question body.