private void ProcessLoginError(SessionResponse ssnResponse, ServiceInvocationEventArgs invokerEventArgs) { Exception thrownException = invokerEventArgs.Exception; StatusDetail errorStatus = ssnResponse != null ? StatusResponse.GetStatusError(ssnResponse.status) : null; if (errorStatus != null) { thrownException = new NsException(errorStatus.message, thrownException); } else if (invokerEventArgs.InvokationAttempt == Configuration.RetryCount) { thrownException = new RetryCountExhaustedException("Login Failed.", thrownException); } else // If the _nsSvc.login(..) call repeatedly threw exceptions... { thrownException = new NsException("Login Failed.\nExceptions have been logged.", thrownException); } invokerEventArgs.Exception = thrownException; if (thrownException != null) { OnServiceInvocationError(invokerEventArgs); throw thrownException; } }
/// <summary> /// Occurs when an exception occurs during a NetSuite operation. /// </summary> /// <param name="e">The <see cref="com.celigo.net.ServiceManager.Utility.ServiceInvocationEventArgs"/> instance containing the event data.</param> protected virtual void OnServiceInvocationError(ServiceInvocationEventArgs e) { if (ServiceInvocationError != null) { ServiceInvocationError(this, e); } }
/// <summary> /// Occurs after a remote NetSuite Method is invoked. Deriving classes may override /// this method to perform additional processing after each Web Service invocation. /// </summary> /// <param name="e">The <see cref="com.celigo.net.ServiceManager.Utility.ServiceInvocationEventArgs"/> instance containing the event data.</param> protected virtual void OnAfterServiceInvocation(ServiceInvocationEventArgs e) { if (AfterServiceInvocation != null) { AfterServiceInvocation(this, e); } }
/// <summary> /// Occurs before a remote NetSuite Method is invoked. Deriving classes may override /// this method to perform additional processing before each Web Service invocation. /// </summary> /// <param name="e">The <see cref="com.celigo.net.ServiceManager.Utility.ServiceInvocationEventArgs"/> instance containing the event data.</param> protected virtual void OnBeforeServiceInvocation(ServiceInvocationEventArgs e) { if (BeforeServiceInvocation != null) { BeforeServiceInvocation(this, e); } }
private T TryInvokeService <T>(Func <object, T> invokerFunc, ServiceInvocationEventArgs invokerEventArgs, out bool retry) where T : class { T result; try { invokerEventArgs.Result = result = invokerFunc(invokerEventArgs.Arguments); OnAfterServiceInvocation(invokerEventArgs); retry = false; return(result); } catch (Exception ex) { Exception thrownException = invokerEventArgs.Exception = GetMostRelevantException(ex); OnServiceInvocationError(invokerEventArgs); if (invokerEventArgs.Cancel) { _log.Debug("Retry canceled by user code"); retry = false; } else if (invokerEventArgs.ForceRetry) { _log.Debug("Retry forced by user code"); retry = true; } else if (ErrorCanBeWorkedArround(thrownException)) { _log.Debug(string.Format("Operation Failed with Exception: {0}", thrownException.GetType().Name)); _log.Debug(thrownException.ToString()); _log.Debug("Attempting Workaround"); WaitForRetryInterval(); // Since we use request level authentication, this is no longer a solution. if (ErrorRequiresNewLogin(thrownException) || invokerEventArgs.InvokationAttempt >= 4) { ExecuteLogin(ServiceProxy, Credentials, OnServiceInvocationError); } retry = true; } else if (ErrorRequiresLockdown(thrownException)) { _log.Error("WebServices operations will be locked down until an explicit login call is made due to the following error.", ex); throw thrownException; } else { _log.Error(string.Format("Operation Failed with Exception: {0}", thrownException.GetType().Name), thrownException); throw new NsException(thrownException); } return(null); } }
/// <summary>Invokes the remote method using the specified parameters and settings.</summary> /// <param name="arg">Method arguments</param> /// <param name="method">Name of the remote method to execute.</param> /// <param name="searchPrefs">Search Preference settings.</param> /// <returns>Result of the web service.</returns> internal override T InvokeService <T>(object arg, string method, SearchPreferences searchPrefs) { lock (ServiceProxy) { Configuration.Configure(ServiceProxy, searchPrefs); T result = null; MethodInfo mi = ServiceProxy.GetType().GetMethod(method); ParameterInfo[] parameters = mi.GetParameters(); Func <object, T> invokerFunc = GetInvokerFunction <T>(mi, parameters); ServiceInvocationEventArgs invokerEventArgs = new ServiceInvocationEventArgs(method, arg); for (; invokerEventArgs.InvokationAttempt < Configuration.RetryCount; invokerEventArgs.InvokationAttempt++) { ServiceProxy.passport = Credentials.GetPassport(); OnBeforeServiceInvocation(invokerEventArgs); if (!invokerEventArgs.Cancel && this.IsSuspended) { throw new WebservicesLockdownException(); } else if (invokerEventArgs.Cancel) { break; } else if (_log.IsDebugEnabled && parameters.Length == 0) { LogInvocationMeaningfully(invokerEventArgs.MethodName); } else if (_log.IsDebugEnabled) { LogInvocationMeaningfully(invokerEventArgs.MethodName, invokerEventArgs.Arguments); } bool retry; result = TryInvokeService <T>(invokerFunc, invokerEventArgs, out retry); if (!retry) { break; } } if (invokerEventArgs.InvokationAttempt == Configuration.RetryCount) // Retry count was exhausted.. { invokerEventArgs.Exception = new RetryCountExhaustedException("Operation Failed", invokerEventArgs.Exception); OnServiceInvocationError(invokerEventArgs); throw invokerEventArgs.Exception; } return(result); } }
private static SessionResponse TryLogin(INetSuiteService serviceProxy, Passport passport, ILogger log, ServiceInvocationEventArgs invokerEventArgs, Action <ServiceInvocationEventArgs> onErrorCallback) { SessionResponse response = null; try { if (log.IsDebugEnabled) { log.Debug(string.Format("Logging into NetSuite [Username={0}, Account={1}, RoleId={2}]", passport.email, passport.account, passport.role == null ? null : passport.role.internalId )); } invokerEventArgs.Exception = null; response = serviceProxy.login(passport); } catch (SoapException soapEx) { invokerEventArgs.Exception = soapEx; log.Debug("Login Failed", soapEx); // if this is a InvalidCredentialFault then there's no point in continuing bool isInvalidCredentialError = soapEx.Detail.FirstChild.Name.EndsWith("invalidCredentialsFault") || soapEx.Detail.InnerText.StartsWith("WS_FEATURE_REQD"); if (isInvalidCredentialError && null == onErrorCallback) { invokerEventArgs.Exception = new InvalidCredentialException(invokerEventArgs.Exception); } else if (isInvalidCredentialError) { invokerEventArgs.Exception = new InvalidCredentialException(invokerEventArgs.Exception); onErrorCallback(invokerEventArgs); } } catch (Exception ex) { log.Debug("Login Failed", ex); invokerEventArgs.Exception = ex; } invokerEventArgs.Result = response; return(response); }
/// <summary>Performs the actual login</summary> /// <returns></returns> private SessionResponse ExecuteLogin(INetSuiteService serviceProxy, NetSuiteCredential credential, Action <ServiceInvocationEventArgs> onErrorCallback) { bool loggedIn = false; _log.Debug("Initializing NetSuite Service Proxy", null); serviceProxy.CookieContainer = new CookieContainer(); Configuration.Configure(serviceProxy); SessionResponse ssnResponse = null; ServiceInvocationEventArgs invokerEventArgs = new ServiceInvocationEventArgs("login", credential); for (; invokerEventArgs.InvokationAttempt < Configuration.RetryCount; invokerEventArgs.InvokationAttempt++) { ssnResponse = TryLogin(serviceProxy, credential.GetPassport(), _log, invokerEventArgs, onErrorCallback); loggedIn = (ssnResponse != null && ssnResponse.status.isSuccessSpecified && ssnResponse.status.isSuccess); if (this.IsSuspended) { this.IsSuspended = !loggedIn; } if (loggedIn || invokerEventArgs.Cancel) { break; } else if (!invokerEventArgs.ForceRetry) { throw invokerEventArgs.Exception; } else if (invokerEventArgs.InvokationAttempt != Configuration.RetryCount - 1) { WaitForRetryInterval(); } } if (!loggedIn) { ProcessLoginError(ssnResponse, invokerEventArgs); } return(ssnResponse); }
/// <summary> /// Invokes the Web Service. /// </summary> /// <param name="arg">Argument(s) to be passed on to the remote method.</param> /// <param name="method">The remote method to be invoked.</param> /// <param name="prefs">Search preferences</param> /// <returns>The result of the WebService call.</returns> /// <remarks>When invoking a remote method that accepts multiple parameters, you should /// provide an <see cref="System.Object"/> array as <paramref name="arg"/>.</remarks> internal override T InvokeService <T>(object arg, string method, SearchPreferences prefs) { IServiceManager svcMgr = null; ServiceInvocationEventArgs invokerArgs = new ServiceInvocationEventArgs(method, arg); try { OnBeforeServiceInvocation(invokerArgs); svcMgr = ServicePoolManager.GetServiceManager(); T result; if (svcMgr is NetSuiteServiceManager) { result = ((NetSuiteServiceManager)svcMgr).InvokeService <T>(arg, method, prefs); } else { result = null; } ServicePoolManager.ReleaseServiceManager(svcMgr); svcMgr = null; invokerArgs.Result = result; OnAfterServiceInvocation(invokerArgs); return(result); } catch (Exception ex) { _log.Error(ex.ToString()); invokerArgs.Exception = ex; OnServiceInvocationError(invokerArgs); throw new NsException(ex); } finally { if (svcMgr != null) { ServicePoolManager.ReleaseServiceManager(svcMgr); } } }