If successful, I want to return the AccessToken string, if not I want to return an error message. These are both strings, so no problem. But when checking the return value on the calling side of the code, how can you do this effectively?
C# doesn't really use error messages, we use exceptions. The correct way to do this is to just throw an exception, and let the caller ignore or catch it.
If it's not "exceptional" to fail (eg., if some users have tokens and some don't), then an alternative would be to return a null string to indicate the absence of a token (and still throw an exception for "exceptional" cases such as not being able to contact Facebook, etc.). I don't think that's the case for you, since your example failure included an Exception object.
Bottom line, is that you generally leave exception handling (catch) to the top-most of the stack (usually, the UI) since that has the most context of the current operation. It's of no use to catch an exception, reformat to a string, and then return that instead - losing valuable exception info along the way. Just let the caller have the exception instead, and they can decide how to present that failure to the user (or to carry on without FB integration).
This is obviously mocked up, but hopefully gets my point across (code speaks louder than words):
class Facebook {
...
public string GetAccessToken(string username, string password) {
// can throw WebException if can't connect to FB
this.Connect();
// returns null token if not a Facebook user
if (!this.IsUser(username)) return null;
// can throw ArgumentException if password is wrong
var fbInfo = this.GetInfo(username, password);
return fbInfo.AccessToken;
}
...
}
class Page {
void Page_Load(object sender, EventArgs e) {
var fb = new Facebook();
string accessToken;
try {
accessToken = fb.GetAccessToken(this.User.Name, this.txtPassword.Text);
} catch (WebException ex) {
Log(ex);
this.divError.Text = "Sorry, Facebook is down";
// continue processing without Facebook
} catch (ArgumentException ex) {
// Don't log - we don't care
this.divError.Text = "Your password is invalid";
// stop processing, let the user correct password
return;
} catch (Exception ex) {
Log(ex);
// Unknown error. Stop processing and show friendly message
throw;
}
if (!string.IsNullOrEmpty(accessToken)) {
// enable Facebook integration
this.FillFacebookWallPosts(accessToken);
} else {
// disable Facebook integration
this.HideFacebook();
}
}
}