Image cache refreshing

Jul 10, 2007 at 8:42 AM
The image cache is driving me mad, as I keep having to rename some of my images to get them to update on the user profile widget for my app, and that's not really an option all the time.

I can't find a way to clear the facebook image cache for a given url in the .net wrapper you guys have created. The default facebook interface apparently has a facebook.fbml.refreshImgSrc('imgURL') call, though it's undocumented and only mentioned in the dev wiki here:

Am I missing something, or is it just not implemented in the .NET wrapper?

Jul 10, 2007 at 1:16 PM
Just not implemented, since this is the first I/we have heard of it. I'll add an issue, and we will get it added.

Jul 10, 2007 at 3:11 PM
Thanks! It's just one of those useful development tools which seems to have no documentation. I look forward to this addition, and in the meantime keep renaming images :(
Jul 12, 2007 at 6:23 PM
If you'd like a slightly better temporary fix, I put together this "Extended Facebook API" class that uses a lot of code from the Facebook client library. I needed the RefreshRefUrl so you'll see that in my class but not RefreshImgSrc. But if you copy-paste my function as a starting point then you should be able to support RefreshImgSrc with minimal tweaking.

Here is the sample usage:
ExtendedFacebookAPI exFacebook = new ExtendedFacebookAPI(FBAPPLICATIONKEY, "1.0", FB_SECRET, _fbService.SessionKey);
Response.Output.Write("Refresh Result: " + exFacebook.RefreshRefUrl(fbRefUrl));

Note that this requires you to have an authenticated session's sessionKey. There is some discussion on the FB boards around workarounds for this...

Ryan - I'll try to message you about contributing the useful part of this source (the new function) into the tree. I'm also curious about why I can't seem to compile the DLLs on my box. The first error is around loading version 1.0.61025.0 of System.Web.Extensions! I saw your discussion on the boards about playing with different .net versions but haven't had time to follow those yet...

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Globalization;
using System.Security.Cryptography;
using System.Text;
using System.Collections.Generic;
using System.Net;
using System.IO;
using System.Xml;

/// <summary>
/// Summary description for ExtendedFacebookAPI
/// </summary>
public class ExtendedFacebookAPI
String _applicationKey;
String _version;
String _secret;
String _sessionKey = null;


XmlNamespaceManager _nsManager;

public ExtendedFacebookAPI(String applicationKey, String version, String secret)
_applicationKey = applicationKey;
_version = version;
_secret = secret;

public ExtendedFacebookAPI(String applicationKey, String version, String secret, String sessionKey)
_applicationKey = applicationKey;
_version = version;
_secret = secret;
_sessionKey = sessionKey;

internal List<string> ParameterDictionaryToList(IEnumerable<KeyValuePair<string, string>> parameterDictionary)
List<string> parameters = new List<string>();

foreach (KeyValuePair<string, string> kvp in parameterDictionary)
parameters.Add(String.Format(CultureInfo.InvariantCulture, "{0}", kvp.Key));
return parameters;

/// <summary>
/// This method generates the signature based on parameters supplied
/// </summary>
/// <param name="parameters">List of paramenters</param>
/// <returns>Generated signature</returns>
internal string GenerateSignature(IDictionary<string, string> parameters)
StringBuilder signatureBuilder = new StringBuilder();
// Sort the keys of the method call in alphabetical order
List<string> keyList = ParameterDictionaryToList(parameters);
// Append all the parameters to the signature input paramaters
foreach (string key in keyList)
signatureBuilder.Append(String.Format(CultureInfo.InvariantCulture, "{0}={1}", key, parameterskey));

// Append the secret to the signature builder
byte[] hash;

MD5 md5 = MD5.Create();
// Compute the MD5 hash of the signature builder
hash = md5.ComputeHash(Encoding.Default.GetBytes(

// Reinitialize the signature builder to store the actual signature
signatureBuilder = new StringBuilder();

// Append the hash to the signature
foreach (byte hashByte in hash)
signatureBuilder.Append(hashByte.ToString("x2", CultureInfo.InvariantCulture));

return signatureBuilder.ToString();

internal string CreateHTTPParameterList(IDictionary<string, string> parameterList)
StringBuilder queryBuilder = new StringBuilder();

parameterList.Add("api_key", _applicationKey);
parameterList.Add("v", _version);
parameterList.Add("call_id", DateTime.Now.Ticks.ToString("x", CultureInfo.InvariantCulture));
parameterList.Add("sig", GenerateSignature(parameterList));

// Build the query
foreach (KeyValuePair<string, string> kvp in parameterList)
queryBuilder.Remove(queryBuilder.Length - 1, 1);

return queryBuilder.ToString();

/// <summary>
/// Get Query Response
/// </summary>
/// <param name="requestUrl">Request Url</param>
/// <param name="postString">posted query</param>
/// <returns>Response data</returns>
internal static string GetQueryResponse(string requestUrl, string postString)
// Create a web request for input path.
WebRequest webRequest = WebRequest.Create(requestUrl);
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";

if (!String.IsNullOrEmpty(postString))
byte[] parameterString = Encoding.ASCII.GetBytes(postString);
webRequest.ContentLength = parameterString.Length;

using (Stream buffer = webRequest.GetRequestStream())
buffer.Write(parameterString, 0, parameterString.Length);

WebResponse webResponse = webRequest.GetResponse();

string responseData;
using (StreamReader streamReader = new StreamReader(webResponse.GetResponseStream()))
responseData = streamReader.ReadToEnd();
return responseData;

internal XmlDocument LoadXMLDocument(string rawXML)
// Parse the data and extract the session details
XmlDocument xmlDocument = new XmlDocument();


_nsManager = new XmlNamespaceManager(xmlDocument.NameTable);
nsManager.AddNamespace("Facebook", RESOURCEFACEBOOK_NAMESPACE);

return xmlDocument;

/// <summary>
/// Parse the Facebook result for an error, and throw an exception.
/// For some of the different types of exceptions, custom action might be desirable.
/// </summary>
/// <param name="doc">The XML result.</param>
internal static void ErrorCheck(XmlDocument doc)
XmlNodeList errorNodes = doc.GetElementsByTagName("error_response");
String errList = "";

if (errorNodes.Count > 0)
foreach (XmlNode errNode in errorNodes)
errList = errNode.OuterXml;
throw new Exception("Facebook Exception: " + errList );

internal string ExecuteApiCallString(IDictionary<string, string> parameterDictionary, bool useSession)
if (useSession)
if (null == _sessionKey)
return "<error>Error: not using an authenticated session when needed in ExtendedFacebookAPI</error>";
parameterDictionary.Add("session_key", _sessionKey);

string requestUrl = "";
string parameters = CreateHTTPParameterList(parameterDictionary);
return GetQueryResponse(requestUrl, parameters);

public string RefreshRefUrl(string url)
string results = string.Empty;

Dictionary<string, string> parameterList = new Dictionary<string, string>(3);
parameterList.Add("method", "facebook.fbml.refreshRefUrl");
parameterList.Add("url", string.Format(CultureInfo.InstalledUICulture, url));

string xml = ExecuteApiCallString(parameterList, true);
if (!String.IsNullOrEmpty(xml))
XmlDocument xmlDocument = LoadXMLDocument(xml);

XmlNodeList nodeList = xmlDocument.GetElementsByTagName("fbmlrefreshRefURLresponse");

if (nodeList != null && nodeList.Count > 0)
if (nodeList0.HasChildNodes)
results = nodeList0.InnerText;

return results;