using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.ServiceModel; using System.Threading; using System.Windows; using BeWo.Multitenancy; using BeWo.Security; using BS.Shared; using BS.Shared.DataContracts; using BS.Shared.DataContracts.Compact; namespace BeWo.ServiceProxy { // Ich verlass mich jetzt mal hierdrauf: // http://dotnetslackers.com/WSE/re-51155_WCF_Proxy_Performance_vs_WSE_V3.aspx // Man muss also nicht schließen wenn nur eine Instanz vom Proxy gehalten wird // und Services PerCall konfiguriert sind... public static class ServiceFacade { public static object _Lock = string.Empty; private static Dictionary _EndpointAddresses; private static readonly Dictionary _ProxyCache; private static int _RunningAsyncs; // Nur um die EndpointAddresses wegen neuer SiteOfOrigin zu aktualisieren public static Dictionary EndpointAddresses { get { return _EndpointAddresses; } } public static void UpdateServerAddresses(String siteOfOrigin) { String serverName = siteOfOrigin; var test = serverName.Substring(serverName.Length - 1, 1); if (serverName.Substring(serverName.Length - 1, 1) != "/") serverName += "/"; _EndpointAddresses = new Dictionary { { typeof(IQueryService), new EndpointAddress(serverName + "QueryService.svc") }, { typeof(IStreamingService), new EndpointAddress(serverName + "StreamingService.svc") }, { typeof(IEmployeeService), new EndpointAddress(serverName + "EmployeeService.svc") }, { typeof(ICustomerService), new EndpointAddress(serverName + "CustomerService.svc") }, { typeof(IUserService), new EndpointAddress(serverName + "UserService.svc") }, { typeof(IValueListService), new EndpointAddress(serverName + "ValueListService.svc") }, { typeof(IDownloadService), new EndpointAddress(serverName + "DownloadService.svc") }, { typeof(IResourceService), new EndpointAddress(serverName + "ResourceService.svc") }, { typeof(IOperationsService), new EndpointAddress(serverName + "OperationsService.svc") }, { typeof(IAnalysisService), new EndpointAddress(serverName + "AnalysisService.svc") }, { typeof(IMailService), new EndpointAddress(serverName + "MailService.svc") }, { typeof(IAccountingService), new EndpointAddress(serverName + "AccountingService.svc") }, { typeof(IReportService), new EndpointAddress(serverName + "ReportService.svc") } }; } static ServiceFacade() { _ProxyCache = new Dictionary(); } public static void DoAccountingServiceAsync(Func pFunc, Action pCallBack, bool showWaitDialog) { DoAsync(pFunc, pCallBack, showWaitDialog); } public static void DoAccountingServiceAsync(Func pFunc, Action pCallBack) { DoAsync(pFunc, pCallBack, true); } public static void DoAccountingServiceAsync(Action pAction) { DoAsync(pAction, true); } public static void DoAccountingServiceAsync(Action pAction, Action callback) { DoAsync(pAction, callback, true); } public static void DoAnalysisServiceAsync(Func pFunc, Action pCallBack) { DoAsync(pFunc, pCallBack, true); } public static void DoAnalysisServiceAsync(Func pFunc, Action pCallBack, bool showWaitDialog) { DoAsync(pFunc, pCallBack, showWaitDialog); } public static void DoAccountingServiceSync(Action pAction) { pAction.Invoke(GetInstance()); } // public static void DoAnalysisServiceAsync(Action pAction) { DoAsync(pAction, true); } public static void DoCustomerServiceAsync(Func pFunc, Action pCallBack, bool showWaitDialog) { DoAsync(pFunc, pCallBack, showWaitDialog); } public static void DoCustomerServiceAsync(Func pFunc, Action pCallBack) { DoAsync(pFunc, pCallBack, true); } public static void DoCustomerServiceAsync(Action pAction) { DoAsync(pAction, true); } public static void DoCustomerServiceSync(Action pAction) { pAction.Invoke(GetInstance()); } public static T DoCustomerServiceSync(Func pFunc) { try { return pFunc.Invoke(GetInstance()); } catch (Exception e) { ShowErrorMessage(e); } return default(T); } public static void DoDownloadServiceAsync(Func pFunc, Action pCallBack) { DoAsync(pFunc, pCallBack, true); } public static void DoDownloadServiceAsync(Action pAction) { DoAsync(pAction, true); } public static void DoDownloadServiceSync(Action pAction) { try { pAction.Invoke(GetInstance()); } catch (Exception e) { // if (HandleServiceProxyException(e)) // throw e; ShowErrorMessage(e); } } public static T DoDownloadServiceSync(Func pFunc) { try { return pFunc.Invoke(GetInstance()); } catch (Exception e) { ShowErrorMessage(e); } return default(T); } public static void DoEmployeeServiceAsync(Func pFunc, Action pCallBack, bool showWaitDialog) { DoAsync(pFunc, pCallBack, showWaitDialog); } public static void DoEmployeeServiceAsync(Func pFunc, Action pCallBack) { DoAsync(pFunc, pCallBack, true); } public static void DoEmployeeServiceAsync(Action pAction) { DoAsync(pAction, true); } public static void DoEmployeeServiceSync(Action pAction) { try { pAction.Invoke(GetInstance()); } catch (Exception e) { ShowErrorMessage(e); } } public static T DoEmployeeServiceSync(Func pFunc) { try { return pFunc.Invoke(GetInstance()); } catch (Exception e) { ShowErrorMessage(e); } return default(T); } public static void DoWohnheimServiceAsync(Func pFunc, Action pCallBack, bool showWaitDialog) { DoAsync(pFunc, pCallBack, showWaitDialog); } public static void DoWohnheimServiceAsync(Func pFunc, Action pCallBack) { DoAsync(pFunc, pCallBack, true); } public static void DoWohnheimServiceAsync(Action pAction) { DoAsync(pAction, true); } public static void DoWohnheimServiceSync(Action pAction) { try { pAction.Invoke(GetInstance()); } catch (Exception e) { ShowErrorMessage(e); } } public static T DoWohnheimServiceSync(Func pFunc) { try { return pFunc.Invoke(GetInstance()); } catch (Exception e) { ShowErrorMessage(e); } return default(T); } public static void DoMailServiceAsync(Func pFunc, Action pCallBack) { DoAsync(pFunc, pCallBack, true); } public static void DoMailServiceAsync(Action pAction) { DoAsync(pAction, true); } public static T DoMailServiceSync(Func pFunc) { try { return pFunc.Invoke(GetInstance()); } catch (Exception e) { ShowErrorMessage(e); } return default(T); } public static void DoMultipleAccountingServicesAsync(List> pActions, Action pAllDoneCallBack) { DoMulitpleAsync(pActions, pAllDoneCallBack, true); } public static void DoMultipleCustomerServicesAsync(List> pActions, Action pAllDoneCallBack) { DoMulitpleAsync(pActions, pAllDoneCallBack, true); } public static void DoMultipleEmployeeServicesAsync(List> pActions, Action pAllDoneCallBack) { DoMulitpleAsync(pActions, pAllDoneCallBack, true); } public static void DoMultipleEmployeeServicesAsync(List> pActions, Action pAllDoneCallBack, bool showWaitDialog) { DoMulitpleAsync(pActions, pAllDoneCallBack, showWaitDialog); } public static void DoMultipleMailServicesAsync(List> pActions, Action pAllDoneCallBack) { DoMulitpleAsync(pActions, pAllDoneCallBack, true); } public static void DoMultipleOperationsServicesAsync(List> pActions, Action pAllDoneCallBack) { DoMulitpleAsync(pActions, pAllDoneCallBack, true); } public static void DoMultipleOperationsServicesSync(List> pActions) { DoMulitpleSync(pActions, true); } public static void DoMultipleResourceServicesAsync(List> pActions, Action pAllDoneCallBack) { DoMulitpleAsync(pActions, pAllDoneCallBack, true); } public static void DoMultipleValueListServicesAsync(List> pActions, Action pAllDoneCallBack) { DoMulitpleAsync(pActions, pAllDoneCallBack, true); } public static void DoOperationsServiceAsync(Func pFunc, Action pCallBack, bool showWaitDialog) { DoAsync(pFunc, pCallBack, showWaitDialog); } public static void DoOperationsServiceAsync(Func pFunc, Action pCallBack) { DoAsync(pFunc, pCallBack, true); } public static void DoOperationsServiceAsync(Action pAction, Action pCallBack) { DoAsync(pAction, pCallBack, true); } public static void DoOperationsServiceAsync(Action pAction) { DoAsync(pAction, true); } public static void DoOperationsServiceSync(Action pAction) { try { pAction.Invoke(GetInstance()); } catch (Exception e) { ShowErrorMessage(e); } } public static void DoOperationsServiceAsyncNoWait(Func pFunc, Action pCallBack, object state) { DoAsync(pFunc, cb => pCallBack(cb, state), false); } public static T DoOperationsServiceSync(Func pFunc) { try { return pFunc.Invoke(GetInstance()); } catch (Exception e) { ShowErrorMessage(e); } return default(T); } public static void DoQueryServiceAsync(Func pFunc, Action pCallBack) { DoAsync(pFunc, pCallBack, true); } public static void DoQueryServiceAsync(Action pAction) { DoAsync(pAction, true); } public static T DoQueryServiceSync(Func pFunc) { try { return pFunc.Invoke(GetInstance()); } catch (Exception e) { ShowErrorMessage(e); } return default(T); } public static void DoResourceServiceSync(Func pFunc) { try { pFunc.Invoke(GetInstance()); } catch (Exception e) { ShowErrorMessage(e); } } public static void DoResourceServiceAsync(Func pFunc, Action pCallBack, bool showWaitDialog) { DoAsync(pFunc, pCallBack, showWaitDialog); } public static void DoResourceServiceAsync(Func pFunc, Action pCallBack) { DoAsync(pFunc, pCallBack, true); } public static void DoResourceServiceAsync(Action pAction) { DoAsync(pAction, true); } public static void DoResourceServiceAsync(Action pAction, Action pCallback) { DoAsync(pAction, pCallback, true); } public static void DoStreamingServiceAsync(Func pFunc, Action pCallBack, Action pErrorCallBack) { DoAsync(pFunc, pCallBack, pErrorCallBack, true); } public static void DoStreamingServiceAsync(Action pAction) { DoAsync(pAction, true); } public static void DoUserServiceAsync(Func pFunc, Action pCallBack, bool showWaitDialog) { DoAsync(pFunc, pCallBack, showWaitDialog); } public static T DoUserServiceSync(Func pFunc) { return pFunc.Invoke(GetInstance()); } public static void DoUserServiceAsync(Action pAction, bool showWaitDialog) { DoAsync(pAction, showWaitDialog); } public static void DoUserServiceAsync(Action pAction, Action pCallBack, bool showWaitDialog) { DoAsync(pAction, pCallBack, showWaitDialog); } public static void DoValueListServiceAsync(Func pFunc, Action pCallBack) { DoAsync(pFunc, pCallBack, true); } public static void DoValueListServiceSync(Func pFunc, Action pCallBack) { DoAsync(pFunc, pCallBack, true); } public static T DoValueListServiceSync(Func pFunc) { try { return pFunc.Invoke(GetInstance()); } catch (Exception e) { ShowErrorMessage(e); } return default(T); } public static void DoValueListServiceAsync(Action pAction) { DoAsync(pAction, true); } public static void DoReportServiceAsync(Func pFunc, Action pCallBack) { DoAsync(pFunc, pCallBack, true); } public static void DoReportServiceAsync(Func pFunc, Action pCallBack, bool showWaitDialog) { DoAsync(pFunc, pCallBack, showWaitDialog); } public static void DoReportServiceSync(Action pAction) { try { pAction.Invoke(GetInstance()); } catch (Exception e) { ShowErrorMessage(e); } } public static void DoReportServiceAsync(Action pAction) { DoAsync(pAction, true); } public static T DoReportServiceSync(Func pFunc) { try { return pFunc.Invoke(GetInstance()); } catch (Exception e) { ShowErrorMessage(e); } return default(T); } public static void GetAll(Action> pCallBack) { if (typeof(T) == typeof(CompactCustomerDC)) { long? oid = null; if (!BeWoApp.LoggedOnUser.HasRight(UserRightType.ViewAll) && !BeWoApp.LoggedOnUser.HasRight(UserRightType.CustomerView_View)) { oid = BeWoApp.LoggedOnUser.Employee.EmployeeOid; } DoCustomerServiceAsync( s => s.GetAllActiveCustomersCompact(false, oid), r => { List list = r; if (oid != null) { list = list.Where(c => c.IsRelatedToEmployee).ToList(); } list.Sort((x, y) => { return (x.LastName + ", " + x.FirstName).CompareTo(y.LastName + ", " + y.FirstName); }); // (Comparison)new CustomerSorter().GetComparison("LastName", BeWo.Core.AbstractSorter.SortDirection.Ascending)); pCallBack(list.Cast().ToList()); }); } else if (typeof(T) == typeof(CompactEmployeeDC)) { DoEmployeeServiceAsync(s => s.GetAllActiveEmployeesCompact().Cast().ToList(), r => pCallBack(r)); } else if (typeof(T) == typeof(CompactTeamDC)) { DoEmployeeServiceAsync(s => s.GetAllTeamsCompact().Cast().ToList(), r => pCallBack(r)); } else if (typeof(T) == typeof(CompactOrganisationDC)) { DoCustomerServiceAsync(s => s.GetAllActiveOrganisationsCompact().Cast().ToList(), r => pCallBack(r)); } else if (typeof(T) == typeof(CompactPersonDC)) { DoCustomerServiceAsync(s => s.GetAllActivePersonsCompact().Cast().ToList(), r => pCallBack(r)); } else if (typeof(T) == typeof(CompactSupportConceptDC)) { DoCustomerServiceAsync(s => s.GetAllActiveSupportConceptsCompact().Cast().ToList(), r => pCallBack(r)); } else if (typeof(T) == typeof(CompactUserDC)) { DoUserServiceAsync(s => s.GetAllUsersCompact().Cast().ToList(), r => pCallBack(r), true); } else if (typeof (T) == typeof (ResourceDC)) { DoResourceServiceAsync(s => s.GetAllResources().Cast().ToList(), pCallBack, true); } else if (typeof (T) == typeof (TextModuleDC)) { DoOperationsServiceAsync(s => s.GetAllTextModules().Cast().ToList(), pCallBack); } else { throw new NotImplementedException(); } } // returnvalue with callback private static void DoAsync(Func pFunc, Action pCallback, bool showWaitDialog) where TClient : ClientBase, TInterface, new() where TInterface : class { DoAsync(pFunc, pCallback, null, showWaitDialog); } private static void DoAsync(Func pFunc, Action pCallback, Action pErrorCallback, bool showWaitDialog) where TClient : ClientBase, TInterface, new() where TInterface : class { try { if (showWaitDialog) { StartWaiting(); } pFunc.BeginInvoke( GetInstance(), cb => { try { T lResult = pFunc.EndInvoke(cb); if (pCallback != null) { pCallback(lResult); } if (showWaitDialog) { EndWaiting(); } } catch (Exception e) { // bool lThrow = ShowErrorMessage(e); // if (showWaitDialog) EndWaiting(); // if (lThrow) // throw e; if (showWaitDialog) { EndWaiting(); } ShowErrorMessage(e); if (pErrorCallback != null) { pErrorCallback(); } } }, null); } catch (Exception e) { // bool lThrow = ShowErrorMessage(e); // if (showWaitDialog) EndWaiting(); // if (lThrow) // throw e; if (showWaitDialog) { EndWaiting(); } ShowErrorMessage(e); } } // void without callback private static void DoAsync(Action pAction, bool showWaitDialog) where TClient : ClientBase, TInterface, new() where TInterface : class { DoAsync(pAction, null, showWaitDialog); } // private static void DoAsync(Action pAction, Action pCallback, bool ) // void with callback private static void DoAsync(Action pAction, Action pCallback, bool showWaitDialog) where TClient : ClientBase, TInterface, new() where TInterface : class { try { if (showWaitDialog) { StartWaiting(); } pAction.BeginInvoke( GetInstance(), cb => { try { pAction.EndInvoke(cb); if (pCallback != null) { pCallback(); } if (showWaitDialog) { EndWaiting(); } } catch (Exception e) { // bool lThrow = ShowErrorMessage(e); // if (showWaitDialog) EndWaiting(); // if (lThrow) // throw e; if (showWaitDialog) { EndWaiting(); } ShowErrorMessage(e); } }, null); } catch (Exception e) { // bool lThrow = ShowErrorMessage(e); // if (showWaitDialog) EndWaiting(); // if (lThrow) // throw e; if (showWaitDialog) { EndWaiting(); } ShowErrorMessage(e); } } private static void DoMulitpleAsync(List> pActions, Action pAllDoneCallBack, bool showWaitDialog) where TClient : ClientBase, TInterface, new() where TInterface : class { int lCount = pActions.Count; if (lCount == 0) { pAllDoneCallBack(); } foreach (var iAction in pActions) { DoAsync( iAction, delegate { Monitor.Enter(_Lock); lCount--; Monitor.Exit(_Lock); if (lCount == 0) { pAllDoneCallBack(); } }, showWaitDialog); } } private static void DoMulitpleSync(List> pActions, bool showWaitDialog) where TClient : ClientBase, TInterface, new() where TInterface : class { int lCount = pActions.Count; if (showWaitDialog) { StartWaiting(); } foreach (var iAction in pActions) { iAction.Invoke(GetInstance()); } if (showWaitDialog) { EndWaiting(); } } private static void EndWaiting() { Monitor.Enter(_Lock); if ((--_RunningAsyncs) == 0 && BeWoApp.MainControl != null) { BeWoApp.MainControl.EndWaiting(); } Monitor.Exit(_Lock); } private static TInterface GetInstance() where TClient : ClientBase, TInterface, new() where TInterface : class { TClient lClient = null; if (_ProxyCache.ContainsKey(typeof(TClient))) { lClient = (TClient)_ProxyCache[typeof(TClient)]; if (lClient.State == CommunicationState.Closing || lClient.State == CommunicationState.Closed || lClient.State == CommunicationState.Faulted) { if (lClient.State == CommunicationState.Faulted) { lClient.Abort(); } lClient = null; _ProxyCache.Remove(typeof(TClient)); } } if (lClient != null) {// EndpointAddresses aktualisieren if (!lClient.Endpoint.Address.Equals(EndpointAddresses[typeof(TInterface)])) { if (lClient.State == CommunicationState.Opened) lClient.Close(); if (_ProxyCache.ContainsKey(typeof(TClient))) _ProxyCache.Remove(typeof(TClient)); lClient = null; } } if (lClient == null) { lClient = new TClient(); if(!_ProxyCache.ContainsKey(lClient.GetType())) { _ProxyCache.Add(typeof(TClient), lClient); } lClient.Endpoint.Behaviors.Add(new SecurityHeaderEndpointBehavior()); lClient.Endpoint.Behaviors.Add(new MultitenancyEndpointBehavior()); lClient.Endpoint.Address = EndpointAddresses[typeof(TInterface)]; } return lClient; } private static void ShowErrorMessage(Exception e) { if (e is FaultException) { var lBeWoFault = (e as FaultException).Detail; String rowUpdated = "Der Datensatz wurde in der Zwischenzeit von " + BS.Shared.Translation.Translator.Translate("einem anderen Benutzer") + " geändert. Ihre Änderungen konnten leider NICHT gespeichert werden. Das Problem tritt auf, wenn mehrere " + BS.Shared.Translation.Translator.Translate("BenutzerPlural") + " gleichzeitig den gleichen Datensatz bearbeiten.\n\nSie müssen den Datensatz schließen und erneut öffnen, um die Änderungen vornehmen zu können."; switch (lBeWoFault.FaultType) { case BeWoFaultType.Concurrency: BeWoApp.ShowError(rowUpdated, e, false); break; case BeWoFaultType.DeleteNotPossible: MessageBox.Show(lBeWoFault.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Asterisk); break; case BeWoFaultType.LoginNameTaken: MessageBox.Show(lBeWoFault.Message, "Warnung", MessageBoxButton.OK, MessageBoxImage.Asterisk); return; case BeWoFaultType.CustomWithoutDetails: BeWoApp.ShowError(lBeWoFault.Message, e, false); break; default: if (!String.IsNullOrEmpty(e.Message) && e.Message.IndexOf("Row was updated or deleted by another transaction") >= 0) { BeWoApp.ShowError(rowUpdated, e, false); } else { if (!String.IsNullOrEmpty(lBeWoFault.Message)) { BeWoApp.ShowError(lBeWoFault.Message, e, true); } else { BeWoApp.ShowError(null, e, true); } } break; } } else { BeWoApp.ShowError(null, e, true); } } private static void StartWaiting() { Monitor.Enter(_Lock); if ((++_RunningAsyncs) == 1 && BeWoApp.MainControl != null) { BeWoApp.MainControl.StartWaiting(); } Monitor.Exit(_Lock); } } }