private static void HandleGetStateSuccess(AbstractLogger logger, IEpochTime epochTime, IDatabase database, IUserDatabase userDatabase, INotificationQueue notificationQueue, GetStateResponse response, IMixWebCallFactory mixWebCallFactory, Action <GetStateResponse> successCallback, Action failureCallback) { try { if (ValidateResponse(response)) { epochTime.ReferenceTime = response.Timestamp.Value; database.SetServerTimeOffsetMillis((long)epochTime.Offset.TotalMilliseconds); logger.Debug("New time offset: " + epochTime.Offset); successCallback(response); notificationQueue.LatestSequenceNumber = response.NotificationSequenceCounter.Value; } else { logger.Critical("Error validating get state response: " + JsonParser.ToJson(response)); failureCallback(); notificationQueue.Clear(); } } catch (Exception ex) { logger.Critical("Unhandled exception: " + ex); failureCallback(); notificationQueue.Clear(); } }
private void HandleRegisterSuccess(GuestControllerResult <LogInResponse> result, IEnumerable <Disney.Mix.SDK.Internal.GuestControllerDomain.MarketingItem> marketing, Action <IRegisterResult> callback) { IList <IInvalidProfileItemError> profileItemErrors = null; try { if (!result.Success) { callback(new RegisterResult(success: false, null, null)); return; } IRegisterResult registerResult = GuestControllerErrorParser.GetRegisterResult(result.Response.error); if (registerResult != null) { callback(registerResult); return; } profileItemErrors = GuestControllerErrorParser.GetRegisterProfileItemErrors(result.Response.error); if (result.Response.data == null) { if (result.Response.error != null && profileItemErrors == null) { logger.Critical("Received unhandled error exception" + JsonParser.ToJson(result.Response.error)); } callback(new RegisterResult(success: false, null, profileItemErrors)); return; } LogInData loginData = result.Response.data; if (loginData.displayName == null || loginData.etag == null || loginData.profile == null || loginData.token == null || loginData.token.access_token == null) { logger.Critical("Invalid login data:" + JsonParser.ToJson(loginData)); callback(new RegisterResult(success: false, null, profileItemErrors)); return; } loginData.profile.status = GuestControllerErrorParser.GetAccountStatusCode(result.Response.error, loginData.profile.status); string countryCode = GuestControllerUtils.GetCountryCode(loginData.profile); database.StoreSession(loginData.token.swid, loginData.token.access_token, loginData.token.refresh_token, loginData.displayName.displayName, loginData.profile.firstName, loginData.etag, loginData.profile.ageBand, loginData.displayName.proposedDisplayName, loginData.displayName.proposedStatus, loginData.profile.status, updateLastProfileRefreshTime: true, countryCode); mixSessionStarter.Start(loginData.token.swid, loginData.token.access_token, delegate { HandleMixSessionStartSuccess(profileItemErrors, loginData.token.swid, loginData.profile, loginData.displayName, marketing, callback); }, delegate { callback(new RegisterResult(success: false, null, profileItemErrors)); }); } catch (CorruptionException ex) { logger.Fatal("Corruption detected during registration: " + ex); callback(new RegisterCorruptionDetectedResult()); } catch (Exception ex2) { logger.Critical("Unhandled exception: " + ex2); callback(new RegisterResult(success: false, null, profileItemErrors)); } }
public static void Send(AbstractLogger logger, INotificationQueue notificationQueue, IMixWebCallFactory mixWebCallFactory, string inviteeDisplayName, bool requestTrust, Action <long> successCallback, Action <ISendFriendInvitationResult> failureCallback) { try { AddFriendshipInvitationRequest addFriendshipInvitationRequest = new AddFriendshipInvitationRequest(); addFriendshipInvitationRequest.InviteeDisplayName = inviteeDisplayName; addFriendshipInvitationRequest.IsTrusted = requestTrust; AddFriendshipInvitationRequest request = addFriendshipInvitationRequest; IWebCall <AddFriendshipInvitationRequest, AddFriendshipInvitationResponse> webCall = mixWebCallFactory.FriendshipInvitationPut(request); webCall.OnResponse += delegate(object sender, WebCallEventArgs <AddFriendshipInvitationResponse> e) { AddFriendshipInvitationResponse response = e.Response; if (NotificationValidator.Validate(response.Notification)) { notificationQueue.Dispatch(response.Notification, delegate { successCallback(response.Notification.Invitation.FriendshipInvitationId.Value); }, delegate { failureCallback(new SendFriendInvitationResult(success: false, null)); }); } else { logger.Critical("Failed to validate invitation: " + JsonParser.ToJson(response)); failureCallback(new SendFriendInvitationResult(success: false, null)); } }; webCall.OnError += delegate(object sender, WebCallErrorEventArgs e) { string status = e.Status; string message = e.Message; string text = status; if (text != null && text == "INVITATION_ALREADY_EXISTS") { logger.Error("Failed to send invitation because it already exists: " + message); failureCallback(new SendFriendInvitationAlreadyExistsResult(success: false, null)); } else { failureCallback(new SendFriendInvitationResult(success: false, null)); } }; webCall.Execute(); } catch (Exception ex) { logger.Critical("Unhandled exception: " + ex); failureCallback(new SendFriendInvitationResult(success: false, null)); } }
private void Start(string swid, string guestControllerAccessToken, RSAParameters rsaParameters, Action<MixSessionStartResult> successCallback, Action failureCallback) { try { ISessionRefresher sessionRefresher = sessionRefresherFactory.Create(this); IMixWebCallFactory mixWebCallFactory = mixWebCallFactoryFactory.Create(sessionStartEncryptor, swid, guestControllerAccessToken, sessionRefresher); StartUserSessionRequest request = BuildRequest(swid, rsaParameters); IWebCall<StartUserSessionRequest, StartUserSessionResponse> webCall = mixWebCallFactory.SessionUserPut(request); webCall.OnResponse += delegate(object sender, WebCallEventArgs<StartUserSessionResponse> e) { StartUserSessionResponse response = e.Response; if (!ValidateResponse(response)) { logger.Critical("Error parsing the session start response: " + JsonParser.ToJson(response)); failureCallback(); } else { long sessionId = response.SessionId.Value; byte[] ciphertext = Convert.FromBase64String(response.EncryptedSymmetricKey); byte[] symmetricKey = rsaEncryptor.Decrypt(ciphertext, rsaParameters); keychain.PushNotificationKey = symmetricKey; database.UpdateSessionDocument(swid, delegate(SessionDocument doc) { doc.PreviousSymmetricEncryptionKey = doc.CurrentSymmetricEncryptionKey; doc.CurrentSymmetricEncryptionKey = symmetricKey; doc.SessionId = sessionId; doc.LatestNotificationSequenceNumber = 0L; }); IWebCallEncryptor webCallEncryptor = webCallEncryptorFactory.Create(symmetricKey, sessionId); MixSessionStartResult obj = new MixSessionStartResult(webCallEncryptor); successCallback(obj); } }; webCall.OnError += delegate { failureCallback(); }; webCall.Execute(force: true); } catch (Exception ex) { logger.Critical("Unhandled exception: " + ex); failureCallback(); } }
private static IEnumerable <BaseNotification> EnumerateValidNotifications <TNotification>(AbstractLogger logger, IList <TNotification> notifications, Func <TNotification, bool> isValid) where TNotification : BaseNotification { if (notifications == null) { yield break; } foreach (TNotification notification in notifications) { if (isValid(notification)) { yield return(notification); } else { logger.Critical("Invalid notification: " + JsonParser.ToJson(notification)); } } }
private void HandleGetNotificationsResponse(GetNotificationsResponse response) { isPolling = false; if (isDisposed) { return; } if (!Validate(response)) { logger.Critical("Invalid notifications response:\n" + JsonParser.ToJson(response)); return; } long?lastNotificationTimestamp = response.LastNotificationTimestamp; List <BaseNotification> list = getStateResponseParser.CollectNotifications(response); RemoveMissingNotificationTimes(list, missedNotificationTimes); RemoveInvalidNotifications(list, queue); SortNotificationsBySequenceNumber(list); long value = response.NotificationSequenceCounter.Value; long requestedSince = queue.LatestSequenceNumber + 1; List <long> queued = queue.SequenceNumbers.ToList(); IEnumerable <long> missingSequenceNumbers = GetMissingSequenceNumbers(requestedSince, queued, list, value); long milliseconds = epochTime.Milliseconds; AddTimes(missingSequenceNumbers, missedNotificationTimes, milliseconds); bool anyMissing = missedNotificationTimes.Count > 0; bool anyReceived = list.Count > 0; int numIntervals = CurIntervals.Length; IntervalIndex = GetNextIntervalIndex(IntervalIndex, numIntervals, anyMissing, anyReceived); queue.Dispatch(list, delegate { }, delegate { }); DispatchOnNotificationsPolledIfNotNull(lastNotificationTimestamp); PollAgain(); if (IsNotificationMissingTooLong) { Pause(); missedNotificationTimes.Clear(); DispatchOnSynchronizationError(); } }
private IWebCall <TRequest, TResponse> CreateWebCall <TRequest, TResponse>(HttpMethod method, Uri uri, TRequest request, long latencyWwwCallTimeout, long maxWwwCallTimeout) where TRequest : BaseUserRequest where TResponse : BaseResponse, new() { request.UserId = swid; request.Timestamp = (database.GetServerTimeOffsetMillis().HasValue ? new long?(epochTime.Milliseconds) : null); string body = JsonParser.ToJson(request); Dictionary <string, string> dictionary = new Dictionary <string, string>(); dictionary.Add("Content-Type", webCallEncryptor.ContentType); dictionary.Add("X-Mix-OneIdToken", guestControllerAccessToken); dictionary.Add("X-Mix-ClientToken", mixClientToken); dictionary.Add("Cache-Control", "no-cache,no-store,must-revalidate"); Dictionary <string, string> dictionary2 = dictionary; if (webCallEncryptor.SessionId != null) { dictionary2.Add("X-Mix-UserSessionId", webCallEncryptor.SessionId); } MixWebCall <TRequest, TResponse> webCall = new MixWebCall <TRequest, TResponse>(logger, uri, body, method, dictionary2, wwwCallFactory, webCallEncryptor, latencyWwwCallTimeout, maxWwwCallTimeout, database, swid); webCalls.Add(webCall); webCallQueue.AddWebCall(webCall); if (isSessionRefreshing) { webCall.RefreshStatus = WebCallRefreshStatus.WaitingForRefreshCallback; } webCall.OnResponse += delegate { webCalls.Remove(webCall); webCallQueue.RemoveWebCall(webCall); }; webCall.OnError += delegate { webCalls.Remove(webCall); webCallQueue.RemoveWebCall(webCall); }; webCall.OnUnauthorized += delegate(object sender, WebCallUnauthorizedEventArgs e) { HandleOnUnauthorized(webCall, e); }; return(webCall); }
public static void Reject(AbstractLogger logger, INotificationQueue notificationQueue, IMixWebCallFactory mixWebCallFactory, long invitationId, Action <RemoveFriendshipInvitationNotification> successCallback, Action failureCallback) { try { RemoveFriendshipInvitationRequest removeFriendshipInvitationRequest = new RemoveFriendshipInvitationRequest(); removeFriendshipInvitationRequest.InvitationId = invitationId; RemoveFriendshipInvitationRequest request = removeFriendshipInvitationRequest; IWebCall <RemoveFriendshipInvitationRequest, RemoveFriendshipInvitationResponse> webCall = mixWebCallFactory.FriendshipInvitationDeletePost(request); webCall.OnResponse += delegate(object sender, WebCallEventArgs <RemoveFriendshipInvitationResponse> e) { RemoveFriendshipInvitationResponse response = e.Response; if (NotificationValidator.Validate(response.Notification)) { RemoveFriendshipInvitationNotification notification = response.Notification; notificationQueue.Dispatch(notification, delegate { successCallback(notification); }, failureCallback); } else { logger.Critical("Failed to validate invitation response: " + JsonParser.ToJson(response)); failureCallback(); } }; webCall.OnError += delegate { failureCallback(); }; webCall.Execute(); } catch (Exception ex) { logger.Critical("Unhandled exception: " + ex); failureCallback(); } }
public static void Accept(AbstractLogger logger, INotificationQueue notificationQueue, IMixWebCallFactory mixWebCallFactory, long invitationId, bool isTrusted, Action <AddFriendshipNotification> successCallback, Action failureCallback) { try { AddFriendshipRequest addFriendshipRequest = new AddFriendshipRequest(); addFriendshipRequest.InvitationId = invitationId; addFriendshipRequest.IsTrusted = isTrusted; AddFriendshipRequest request = addFriendshipRequest; IWebCall <AddFriendshipRequest, AddFriendshipResponse> webCall = mixWebCallFactory.FriendshipPut(request); webCall.OnResponse += delegate(object sender, WebCallEventArgs <AddFriendshipResponse> e) { AddFriendshipResponse response = e.Response; if (NotificationValidator.Validate(response.Notification)) { notificationQueue.Dispatch(response.Notification, delegate { successCallback(response.Notification); }, failureCallback); } else { logger.Critical("Failed to validate invitation response: " + JsonParser.ToJson(response)); failureCallback(); } }; webCall.OnError += delegate { failureCallback(); }; webCall.Execute(); } catch (Exception ex) { logger.Critical("Unhandled exception: " + ex); failureCallback(); } }
private void HandleLoginSuccess(GuestControllerResult <LogInResponse> result, Action <ILoginResult> callback) { try { LogInResponse response = result.Response; LogInData data = response.data; GuestApiErrorCollection gcErrorCollection = response.error; ILoginResult loginResult = GuestControllerErrorParser.GetLoginResult(gcErrorCollection); bool flag = false; string hallPassToken = string.Empty; string swid = string.Empty; if (data != null || loginResult == null) { goto IL_015d; } if (loginResult is ILoginFailedParentalConsentResult) { foreach (GuestApiError error in gcErrorCollection.errors) { TemporaryToken data2 = error.data; if (data2 != null) { flag = true; hallPassToken = data2.accessToken; swid = data2.swid; break; } } if (flag) { goto IL_015d; } callback(loginResult); } else { callback(loginResult); } goto end_IL_0018; IL_015d: if (data == null && !flag) { if (gcErrorCollection != null) { logger.Critical("Received unhandled error exception: " + JsonParser.ToJson(gcErrorCollection)); } callback(new LoginResult(success: false, null)); } else if (flag) { database.StoreSession(swid, hallPassToken, null, null, null, null, null, null, null, null, updateLastProfileRefreshTime: false, null); IGuestControllerClient guestControllerClient = guestControllerClientFactory.Create(swid); ProfileGetter.GetProfile(logger, guestControllerClient, delegate(ProfileData profileData) { if (profileData == null) { database.DeleteSession(swid); callback(new LoginFailedParentalConsentResult()); } else { StoreSession(swid, hallPassToken, null, profileData.etag, profileData.displayName, profileData.profile); HandleRefreshProfileSuccess(callback, loginResult, gcErrorCollection, profileData.profile, profileData.displayName, profileData.marketing, swid, hallPassToken); } }); } else if (!ValidateLogInData(data)) { logger.Critical("Error parsing the login data:" + JsonParser.ToJson(data)); callback(new LoginResult(success: false, null)); } else { Token token = data.token; StoreSession(token.swid, token.access_token, token.refresh_token, data.etag, data.displayName, data.profile); HandleRefreshProfileSuccess(callback, loginResult, gcErrorCollection, data.profile, data.displayName, data.marketing, token.swid, token.access_token); } end_IL_0018 :; } catch (CorruptionException ex) { logger.Fatal("Corruption detected during login: "******"Unhandled exception: " + ex2); callback(new LoginResult(success: false, null)); } }
public static void ModerateText(AbstractLogger logger, IMixWebCallFactory mixWebCallFactory, string text, bool isTrusted, Action <ModerateTextResponse> successCallback, Action failureCallback) { try { ModerateTextRequest moderateTextRequest = new ModerateTextRequest(); moderateTextRequest.Text = text; moderateTextRequest.ModerationPolicy = (isTrusted ? "Trusted" : "UnTrusted"); ModerateTextRequest request = moderateTextRequest; IWebCall <ModerateTextRequest, ModerateTextResponse> webCall = mixWebCallFactory.ModerationTextPut(request); webCall.OnResponse += delegate(object sender, WebCallEventArgs <ModerateTextResponse> e) { ModerateTextResponse response = e.Response; if (ValidateModerateTextResponse(response)) { successCallback(response); } else { logger.Critical("Failed to validate moderate text response: " + JsonParser.ToJson(response)); failureCallback(); } }; webCall.OnError += delegate { failureCallback(); }; webCall.Execute(); } catch (Exception ex) { logger.Critical("Unhandled exception: " + ex); failureCallback(); } }
private void HandleRefreshSuccess(Action <IRestoreLastSessionResult> callback, GuestControllerResult <RefreshResponse> result, SessionDocument lastSessionDoc) { try { GuestApiErrorCollection error2 = result.Response.error; RefreshData data = result.Response.data; IRestoreLastSessionResult error = GuestControllerErrorParser.GetRestoreLastSessionResult(error2); if (data == null && error != null) { if (error is IRestoreLastSessionFailedInvalidOrExpiredTokenResult && lastSessionDoc.AccountStatus == "AWAIT_PARENT_CONSENT") { callback(new RestoreLastSessionFailedParentalConsentResult()); } else { callback(error); } return; } if (data == null) { if (error2 != null) { logger.Critical("Received unhandled error exception:\n" + JsonParser.ToJson(error2) + "\nResponse headers:\n" + string.Join("\n", result.ResponseHeaders.Select((KeyValuePair <string, string> h) => h.Key + ": " + h.Value).ToArray())); } callback(new RestoreLastSessionResult(success: false, null)); return; } if (!ValidateRefreshData(data)) { logger.Critical("Error parsing the refresh data: " + JsonParser.ToJson(data)); callback(new RestoreLastSessionResult(success: false, null)); return; } Token token = data.token; lastSessionDoc.GuestControllerAccessToken = token.access_token; lastSessionDoc.GuestControllerEtag = data.etag; database.UpdateGuestControllerToken(token, data.etag); try { IInternalSession session = sessionFactory.Create(lastSessionDoc.Swid); session.Resume(delegate(IResumeSessionResult r) { HandleOfflineSessionResumed(r, session, error, callback); }); } catch (Exception ex) { logger.Critical("Error creating session: " + ex); callback(new RestoreLastSessionResult(success: false, null)); } } catch (CorruptionException ex2) { logger.Fatal("Corruption detected during session restoration: " + ex2); callback(new RestoreLastSessionCorruptionDetectedResult()); } catch (Exception ex) { logger.Critical("Unhandled exception: " + ex); callback(new RestoreLastSessionResult(success: false, null)); } }
public void SetRsaParameters(RSAParameters rsaParameters) { string value = JsonParser.ToJson(rsaParameters); SetValue("RsaParametersKey", value); }
public static void Search(AbstractLogger logger, IMixWebCallFactory mixWebCallFactory, string displayName, IUserDatabase userDatabase, Action <IInternalUnidentifiedUser> successCallback, Action failureCallback) { try { DisplayNameSearchRequest displayNameSearchRequest = new DisplayNameSearchRequest(); displayNameSearchRequest.DisplayName = displayName; DisplayNameSearchRequest request = displayNameSearchRequest; IWebCall <DisplayNameSearchRequest, DisplayNameSearchResponse> webCall = mixWebCallFactory.SearchDisplaynamePost(request); webCall.OnResponse += delegate(object sender, WebCallEventArgs <DisplayNameSearchResponse> e) { DisplayNameSearchResponse response = e.Response; if (ValidateResponse(response)) { userDatabase.InsertUserDocument(new UserDocument { DisplayName = response.DisplayName, FirstName = response.FirstName, Swid = null, HashedSwid = null }); IInternalUnidentifiedUser obj = RemoteUserFactory.CreateUnidentifiedUser(response.DisplayName, response.FirstName, userDatabase); successCallback(obj); } else { logger.Critical("Failed to validate display name search response: " + JsonParser.ToJson(response)); failureCallback(); } }; webCall.OnError += delegate(object sender, WebCallErrorEventArgs e) { logger.Debug("Failed to find user: "******"Unhandled exception: " + ex); failureCallback(); } }
private QueueItem CreateRefreshQueueItem(Action <GuestControllerResult <RefreshResponse> > callback) { Action <GuestControllerResult <RefreshResponse> > failureCallback = delegate(GuestControllerResult <RefreshResponse> r) { callback(new GuestControllerResult <RefreshResponse>(success: false, r.Response, r.ResponseHeaders)); }; QueueItem queueItem = CreateQueueItem("/client/{client-id}/guest/refresh-auth/{refresh-token}", HttpMethod.POST, new EmptyRequest(), GuestControllerAuthenticationType.None, delegate(GuestControllerResult <RefreshResponse> r) { if (!r.Success) { AuthenticationUnavailableEventArgs e = new AuthenticationUnavailableEventArgs(); this.OnAuthenticationLost(this, e); failureCallback(r); } else { GuestApiErrorCollection guestApiErrorCollection = r.Response.error; RefreshData data = r.Response.data; IRefreshGuestControllerTokenError refreshGuestControllerTokenError = GuestControllerErrorParser.GetGuestControllerTokenRefreshError(guestApiErrorCollection); if (refreshGuestControllerTokenError is IRefreshRequiresLegalMarketingUpdateError) { refreshGuestControllerTokenError = null; guestApiErrorCollection = null; this.OnLegalMarketingUpdateRequired(this, new LegalMarketingUpdateRequiredEventArgs()); } if (refreshGuestControllerTokenError is IRefreshTokenGatedLocationError) { logger.Critical("Location gated during Guest Controller token refresh"); AuthenticationLostGatedCountryEventArgs e2 = new AuthenticationLostGatedCountryEventArgs(); this.OnAuthenticationLost(this, e2); failureCallback(r); } else if (refreshGuestControllerTokenError is IRefreshProfileDisabledError || refreshGuestControllerTokenError is IRefreshTemporaryBanError) { logger.Critical("Banned during Guest Controller token refresh"); AccountBannedEventArgs e3 = new AccountBannedEventArgs(logger, null); this.OnAuthenticationLost(this, e3); failureCallback(r); } else if (refreshGuestControllerTokenError != null) { logger.Critical("Guest Controller token refresh error: " + refreshGuestControllerTokenError); AuthenticationRevokedEventArgs e4 = new AuthenticationRevokedEventArgs(); this.OnAuthenticationLost(this, e4); failureCallback(r); } else if (guestApiErrorCollection != null) { logger.Critical("Unhandled error during Guest Controller token refresh: " + JsonParser.ToJson(guestApiErrorCollection)); AuthenticationUnavailableEventArgs e = new AuthenticationUnavailableEventArgs(); this.OnAuthenticationLost(this, e); failureCallback(r); } else if (data == null || data.token == null || data.token.access_token == null || data.token.refresh_token == null) { logger.Critical("Refreshing Guest Controller token returned invalid refresh data: " + JsonParser.ToJson(data)); AuthenticationUnavailableEventArgs e = new AuthenticationUnavailableEventArgs(); this.OnAuthenticationLost(this, e); failureCallback(r); } else { Token token = data.token; database.UpdateGuestControllerToken(token, data.etag); this.OnAccessTokenChanged(this, new GuestControllerAccessTokenChangedEventArgs(token.access_token)); callback(r); } } }); queueItem.RefreshedAccessToken = true; return(queueItem); }
public void ClearAlerts(IEnumerable <IAlert> alerts, Action <IClearAlertsResult> callback) { try { List <IInternalAlert> list = new List <IInternalAlert>(); foreach (IAlert alert in alerts) { IInternalAlert internalAlert = alert as IInternalAlert; if (internalAlert == null) { logger.Critical("Can't clear unknown alert"); callback(new ClearAlertsResult(success: false)); return; } list.Add(internalAlert); } IWebCall <ClearAlertsRequest, ClearAlertsResponse> webCall = mixWebCallFactory.AlertsClearPut(new ClearAlertsRequest { AlertIds = list.Select((IInternalAlert a) => a.AlertId).Cast <long?>().ToList() }); webCall.OnResponse += delegate(object sender, WebCallEventArgs <ClearAlertsResponse> e) { ClearAlertsResponse response = e.Response; if (NotificationValidator.Validate(response.Notification)) { notificationQueue.Dispatch(response.Notification, delegate { callback(new ClearAlertsResult(success: true)); }, delegate { callback(new ClearAlertsResult(success: false)); }); } else { logger.Critical("Failed to validate clear alerts response: " + JsonParser.ToJson(response)); callback(new ClearAlertsResult(success: false)); } }; webCall.OnError += delegate { callback(new ClearAlertsResult(success: false)); }; webCall.Execute(); } catch (Exception ex) { logger.Critical("Unhandled exception: " + ex); callback(new ClearAlertsResult(success: false)); } }
public static void Unfriend(AbstractLogger logger, INotificationQueue notificationQueue, IMixWebCallFactory mixWebCallFactory, string friendSwid, Action successCallback, Action failureCallback) { try { RemoveFriendshipRequest removeFriendshipRequest = new RemoveFriendshipRequest(); removeFriendshipRequest.FriendUserId = friendSwid; RemoveFriendshipRequest request = removeFriendshipRequest; IWebCall <RemoveFriendshipRequest, RemoveFriendshipResponse> webCall = mixWebCallFactory.FriendshipDeletePost(request); webCall.OnResponse += delegate(object sender, WebCallEventArgs <RemoveFriendshipResponse> e) { RemoveFriendshipResponse response = e.Response; RemoveFriendshipNotification notification = response.Notification; if (NotificationValidator.Validate(notification)) { notificationQueue.Dispatch(notification, successCallback, failureCallback); } else { logger.Critical("Failed to validate remove friendship response: " + JsonParser.ToJson(response)); failureCallback(); } }; webCall.OnError += delegate { failureCallback(); }; webCall.Execute(); } catch (Exception ex) { logger.Critical("Unhandled exception: " + ex); failureCallback(); } }