As you probably already know, when your page tab app is firstly loaded, Facebook makes a POST request to the URL you specified in application's Page Tab URL (or Secure Page Tab URL) along with the signed_request string. This is why its value is not null on your landing page. But when you click on a link to navigate to another page inside your tab app, it suddenly becomes null. This is how it should be because you are making a GET request with no signed_request. To make your other pages able to access signed_request, you need to store it. I came up with the following code which works for me but if someone comes with a better solution, I would be glad to hear it:
public static string StoredSignedRequest
{
get
{
string signedRequest = HttpContext.Current.Request["signed_request"];
// If signed_request is provided, store it
if (!String.IsNullOrEmpty(signedRequest))
{
WriteCookie("fb-app-signed-request", signedRequest);
return signedRequest;
}
else
{
return ReadCookie("fb-app-signed-request");
}
}
}
public static void WriteCookie(string strCookieName, string strCookieValue)
{
var hcCookie = new HttpCookie(strCookieName, strCookieValue);
HttpContext.Current.Response.Cookies.Set(hcCookie);
}
public static string ReadCookie(string strCookieName)
{
foreach (string strCookie in HttpContext.Current.Response.Cookies.AllKeys)
{
if (strCookie == strCookieName)
{
return HttpContext.Current.Response.Cookies[strCookie].Value;
}
}
foreach (string strCookie in HttpContext.Current.Request.Cookies.AllKeys)
{
if (strCookie == strCookieName)
{
return HttpContext.Current.Request.Cookies[strCookie].Value;
}
}
return null;
}
Then you can use a JSON parser to parse the value of StoredSignedRequest. In my case, I use Newtonsoft:
public static JObject GetSignedRequestJsonObject()
{
string signed_request = StoredSignedRequest;
if (String.IsNullOrEmpty(signed_request))
{
// If signed_request is null on all pages except the landing page, add the following code to all pages so that it is stored:
// <input type="hidden" name="signed_request" value="<%= FacebookAppHelper.StoredSignedRequest %>" />
return null;
}
string payload = signed_request.Split('.')[1];
UTF8Encoding encoding = new UTF8Encoding();
string decodedJson = payload.Replace("=", string.Empty).Replace('-', '+').Replace('_', '/');
byte[] base64JsonArray = Convert.FromBase64String(decodedJson.PadRight(decodedJson.Length + (4 - decodedJson.Length % 4) % 4, '='));
string json = encoding.GetString(base64JsonArray);
return JObject.Parse(json);
}
The critical part is to not forget to add the hidden field (see commented line above) to all pages that you plan to access using a GET request inside your page tab application.