Facebook tab, finding if liked - facebook

I have the following code to check if my tab is liked by the user:
protected bool IsPageLiked()
{
try
{
var current = ConfigurationManager.GetSection("facebookSettings")
as IFacebookApplication;
dynamic data = FacebookWebContext.Current.SignedRequest.Data;
if (data.page != null)
{
var pageId = (String)data.page.id;
var isUserAdmin = (Boolean)data.page.admin;
var userLikesPage = (Boolean)data.page.liked;
if (userLikesPage)
return true;
}
}
catch (Exception ex)
{
return false;
}
return false;
}
This works correctly when I load my tab initially.
However, if I try and call the same code after changing page within the tab, I get the following error:
{"Precondition failed: !String.IsNullOrEmpty(signedRequestValue)"}
Is there a way I can make this code work after the first page?
I know I can check if the tab is liked on the first page, and put this into a session object or something, but I'd prefer not to do this.
My app itself is MVC 3
Thanks
EDIT
I think what is happening is when I change page (I'm using a RedirectToAction method), it's loosing the signed_request query string, hence the error I am getting.
Edit 2
Not sure the above is what is happening after all, as I can't see any query string values on the initial page? It's still not able to get the signedrequest.
It looks like the signed_request is a form object (Request.Form["signed_request"] returns the string in the inital page, but not the second page).

Page tabs are basically just your app within an iframe on the page, like you've noticed the signed request is POSTED to the tab on page load.
When you change page within the tab the outer Facebook frame isn't reloading so the signed_request is not being re-posted to your tab which is why you can't access it again.
You will need to either pass the signed_request from one page to the next yourself or make sure all links use target="_top" so that the whole page is reloaded each time and you still get the POST.
To define which page you want your tab to load you can use an additional parameter called app_data in the url to your tab, eg
http://www.facebook.com/MY_PAGE?sk=app_MY_APP_ID&app_data=A_STRING_OF_DATA
Your tab will then receive this as part of signed_request, you can grab it and use it to work out which page your tab needs to display.

Related

How do I make a modal open only the first time a user visits the page?

I am using Bootstrap 5.0.2 as the basis of my website, I finally got the modal to appear on page opening, thanks stack overflow, my aim is to not have the modal appear should the visitor move to another page and then return.
This is the code for running the modal. What do I need to add to make it only function the first time this page is viewed per session?
<script>
window.addEventListener('DOMContentLoaded', () => {
const modal = new bootstrap.Modal(document.querySelector('#myModal'));
modal.show();
});
You would need to implement sessionStorage.
When a user visits the page, we check to see if the sessionStorage contains a value for the modal. If it is the first time they load the page, it would not contain a value as we haven't set anything to it yet. In that case, we show the modal as normal and set a value for the sessionStorage. That way, when the user refreshes the page the value is already set in sessionStorage so the if statement will not run.
window.addEventListener('DOMContentLoaded', () => {
if (!sessionStorage.getItem("modal")) {
const modal = new bootstrap.Modal(document.querySelector('#myModal'));
modal.show();
sessionStorage.setItem("modal", "blah");
}
});

Can we just let "prepareFromRequest" to behave just like traditional non-Ajax page?

Ok, let see how traditional non-Ajax page work. Suppose you have a page like the below link
abc.com#!search;item=car
In the traditional non-Ajax website, when first time you call "abc.com#!search;item=car", it will go to server and get data. After that you go to other page like "abc.com#!customer;name=tom" and then you hit back button it will go back to "abc.com#!search;item=car". However, this time it won't call to the server again cos it remembered it did before.
Now Here is the GWTP problem. Suppose the above abc.com was built in GWTP technology.
At the first time wen user enters the "abc.com#!search;item=car", the GWTP app will initialize the page "search" via onBind, then the prepareFromRequest will be called & it will go to server to get data.
That is Good, no problem. However, if we open a new page (like customer page) by using revealPlace, then we hit the back button it will go back to "search" page & it will call prepareFromRequest again. The prepareFromRequest will then make the exactly same call to server again. That is not good cos it wastes resource.
So I want the "prepareFromRequest" to be called ONLY at the time we initialise the page (run after onBind) & block the "prepareFromRequest" in all other page request (ex like user press the back button).
It mean "prepareFromRequest" should work just like traditional non-Ajax page mentioned above.
Can we do that? or
Do you have a better solution?
Why don't you just check in your prepareFromRequest method if you have already a search result for that specific searchterm and only issue a call to the backend if it has changed?
Something like this:
public Presenter extends .... {
String searchItem = null;
List<DTO> searchResult = null;
#Override
public void prepareFromRequest(PlaceRequest placeRequest) {
super.prepareFromRequest(placeRequest);
String item = placeRequest.getParameter("item",null));
if (searchItem == null || !searchItem.equals(item)) {
searchItem = item;
// MAKE A CALL TO THE BACKEND AND STORE THE DATA IN A FIELD.
searchResult = GET_FROM_SERVER(searchItem);
}
}
}

get page path in page properties dialog cq5

I need to get the page path in dialog of page properties. I tried CQ.WCM.getPagePath. it works fine when page properties are changed from dialog, but returns path of siteadmin page when the dialog is accessed by right clicking on the page in site admin. Is there any other way to get page path? Thanks in advance.
You can get the selected path using the following code. In case the dialog is accessed from siteadmin, you can use get the selections from the active grid, or if it is accessed via the page, you can use CQ.WCM.getPagePath() method to get the path of the page.
function(comp) {
/* if accessed via siteadmin */
if(CQ.wcm.SiteAdmin.hasListSelection()) {
var grid = CQ.wcm.SiteAdmin.getActiveGrid();
var selections = grid.getSelectionModel().getSelections();
/*Since you can view only properties of one page at a time,
we would be having only one item in the array */
console.log(selections[0].id);
} else { /* accessed via page */
console.log(CQ.WCM.getPagePath());
}
}
The above function can be used for the beforerender event of your dialog.

Redirect back to facebook page tab after authentication?

im using drupal for facebook for my page tab app, and have a certain issue with it -
after authentication, the user is redirected through a custom module, with the code below -
<?php
function fb_example_fb($op, $data, &$return) {
$fb_app = isset($data['fb_app']) ? $data['fb_app'] : NULL;
$fb = isset($data['fb']) ? $data['fb'] : NULL;
if ($op == FB_OP_AJAX_EVENT) {
if ($data['event_type'] == 'session_change') {
if ($fbu = fb_facebook_user()) {
$url = url('http://apps.facebook.com/appname',
array('absolute' => TRUE, 'fb_canvas' => fb_is_canvas()));
$return[] = 'FB_JS.reload("'. $url .'");';
}
}
}
}
?>
everything works great when i want the user to be redirected to the canvas app.
the problem is, i wish for the user to be "redirected" back to the page tab after authenticating, hence i need to refresh the iframe / the main content div, so as soon as the user clicks the "LOGIN" button and authenticate, the page tab would be updated with custom driven content. my goal is to serve it to the users without ever making them leave the tab.
when i try to set the $url path in the code above to -
https://www.facebook.com/appname/app_4557794143 (the path for the page tab),
i get the following error from facebook after the page refreshes, instead of showing the tab - "
Sorry, your request could not be processed. Please try again"
how can i change the function so the window would be refreshed after pressing the connect button? can someone please shed some light on approaching this the right way?
thanks a lot everyone.
at the end the solution was quite simple, kind of a hack...
for some reason nothing worked when i tried to redirect through fb.js, and facebook kept giving the same error. so, the only thing left to do was to "override" fb.js.redirect and use -
if ($fbu = fb_facebook_user()) {
$return[] = 'top.location.href="https://www.facebook.com/exampleapp/app_707794143";';
}
for all of the future googlers out there...

mvc2 - getting the URL to reflect the form submission

I have an MVC2 application with a form (like ya do). The user enters a query into the form (in the /Cars/Index view) and hits the "submit" button which posts to the Details action of CarsController - the Details view renders with results, and all is well and good.
The user can enter a URL (such as /Cars/Details/123-125) and they get the Details view with 123, 124 and 125 displayed, same as if you'd entered it on the form. Also well and good.
What I want to enable, if possible, is that when the user enters "123-125" or whatever in the form the URL also reflects the results - instead of "/Cars/Details" for a URL, which is what shows now, I want it to show "/Cars/Details/123-125".
For the life of me, I cannot figure out how this should be done.
Any assistance is appreciated.
Change your form to a GET instead of POST method (POST is the default), and it should just work.
<% using (Html.BeginForm("Action", "Controller", FormMethod.Get)) { %>
It sounds like its not finding a matching route definition for /Cars/Details/123-125. I think this could be happening because of the way the routing engine works.
ASP.NET MVC Route Contraints with {ID}-{Slug} Format
Ok, here is the answer I came up with:
In short: Redirect to GET
Basically, I write an action with [HttpPost] Attribute that redirects the form submittal to another action with [HttpGet] attribute. The route works whether you submit the form or type in the URL manually.
[HttpPost]
public ActionResult Details(CarViewModel model, int? pageNbr) {
// simply takes the form POST and re-routes it as a GET to pretty up the URL
// (see second Details action)
int page = pageNbr ?? 0;
return RedirectToAction("Details", new { query = model.Query, pageNbr = page });
}
[HttpGet]
public ActionResult Details(CarViewModel model, int pageNbr)
{
// various magic to create the view...
return View(avm);
}
As an added bonus, this takes care of the "Are you sure you want to resubmit?" annoyance when someone refreshes the page or hits the BACK button in their browser.