using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel; using System.Threading; using System.Windows; using BeWo.Multitenancy; using BeWo.QueryService; 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 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 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 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 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 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).Equals(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).Equals(typeof(CompactEmployeeDC))) { DoEmployeeServiceAsync(s => s.GetAllActiveEmployeesCompact().Cast().ToList(), r => pCallBack(r)); } else if (typeof(T).Equals(typeof(CompactTeamDC))) { DoEmployeeServiceAsync(s => s.GetAllTeamsCompact().Cast().ToList(), r => pCallBack(r)); } else if (typeof(T).Equals(typeof(CompactOrganisationDC))) { DoCustomerServiceAsync(s => s.GetAllActiveOrganisationsCompact().Cast().ToList(), r => pCallBack(r)); } else if (typeof(T).Equals(typeof(CompactPersonDC))) { DoCustomerServiceAsync(s => s.GetAllActivePersonsCompact().Cast().ToList(), r => pCallBack(r)); } else if (typeof(T).Equals(typeof(CompactSupportConceptDC))) { DoCustomerServiceAsync(s => s.GetAllActiveSupportConceptsCompact().Cast().ToList(), r => pCallBack(r)); } else if (typeof(T).Equals(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 (TextbausteinDC)) { DoOperationsServiceAsync(s => s.GetAllTextbausteine().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(); _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 einem anderen Benutzer geändert. Ihre Änderungen konnten leider NICHT gespeichert werden. Das Problem tritt auf, wenn mehrere Benutzer 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); } } }