public static DataTransferObject Deserialize(byte[] data) { MemoryStream memStream = new MemoryStream(data); XmlDocument doc = new XmlDocument(); doc.Load(memStream); XmlNode node = doc.SelectSingleNode("/*"); // Get the type of the object that was serialized. // In case of a generic DTO, the type is FactoryTransferObject<T>, and we need special logic to handle that. Type type; if (node.Name.StartsWith("FactoryTransferObjectOf")) { type = typeof(FactoryTransferObject <>); int length = "FactoryTransferObjectOf".Length; string genericArgument = "OpenDentBusiness." + node.Name.Substring(length); Type genericType = Type.GetType(genericArgument); type = type.MakeGenericType(genericType); } else { type = Type.GetType("OpenDentBusiness." + node.Name); } memStream = new MemoryStream(data); //resets to beginning of stream XmlSerializer serializer = new XmlSerializer(type); DataTransferObject retVal = (DataTransferObject)serializer.Deserialize(memStream); memStream.Close(); return(retVal); }
public DtoInformation(DataTransferObject dto) { FullNameComponents = GetComponentsFromDtoMeth(dto.MethodName); AssemblyName = FullNameComponents[0]; //OpenDentBusiness or else a plugin name ClassName = FullNameComponents[1]; MethodName = FullNameComponents[2]; ClassType = null; Ass = Plugins.GetAssembly(AssemblyName); if (Ass == null) { ClassType = Type.GetType(AssemblyName //actually, the namespace which we require to be same as assembly by convention + "." + ClassName + "," + AssemblyName); } else //plugin was found { ClassType = Ass.GetType(AssemblyName //actually, the namespace which we require to be same as assembly by convention + "." + ClassName); } Parameters = dto.Params; ParamTypes = DtoObject.GenerateTypes(Parameters, AssemblyName); MethodInfo = ClassType.GetMethod(MethodName, ParamTypes); if (MethodInfo == null) { throw new ApplicationException("Method not found with " + Parameters.Length.ToString() + " parameters: " + dto.MethodName); } ParamObjs = DtoObject.GenerateObjects(Parameters); }
internal static string SendAndReceive(DataTransferObject dto) { string dtoString = dto.Serialize(); OpenDentalServer.ServiceMain service = new OpenDentBusiness.OpenDentalServer.ServiceMain(); service.Url = ServerURI; if (MidTierProxyAddress != null && MidTierProxyAddress != "") { IWebProxy proxy = new WebProxy(MidTierProxyAddress); ICredentials cred = new NetworkCredential(MidTierProxyUserName, MidTierProxyPassword); proxy.Credentials = cred; service.Proxy = proxy; } //The default useragent is //Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 4.0.30319.296) //But DHS firewall doesn't allow that. MSIE 6.0 is probably too old, and their firewall also looks for IE8Mercury. service.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; MS Web Services Client Protocol 4.0.30319.296; IE8Mercury)"; string result = service.ProcessRequest(dtoString); //The web service (xml) serializer/deserializer is removing the '\r' portion of our newlines during the data transfer. //Replacing the string is not the best solution but it works for now. The replacing happens inside ProcessRequest() (server side) and here (client side). //It's done server side for usage purposes within the methods being called (exampe: inserting into db) and then on the client side for displaying purposes. if (result != null) { result = result.Replace("\n", "\r\n"); } return(result); }
///<summary>Only used if the dto passed into ProcessRequest is trying to call "Userods.HashPassword". ///This is so that passwords will be hashed on the server to utilize the server's MD5 hash algorithm instead of the workstation's algorithm. ///This is due to the group policy security option "System cryptography: Use FIPS compliant algorithms for encryption, ///hashing and signing" that is enabled on workstations for some users but not on the server. This allows those users to utilize the server's ///algorithm without requiring the workstations to have the algorithm at all.</summary> private static string GetHashPassword(DataTransferObject dto) { DtoGetString dtoGetString = (DtoGetString)dto; string[] fullNameComponents = GetComponentsFromDtoMeth(dtoGetString.MethodName); string assemblyName = fullNameComponents[0]; //OpenDentBusiness or else a plugin name string className = fullNameComponents[1]; string methodName = fullNameComponents[2]; Type classType = null; Assembly ass = Plugins.GetAssembly(assemblyName); if (ass == null) { classType = Type.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className + "," + assemblyName); } else //plugin was found { classType = ass.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className); } DtoObject[] parameters = dtoGetString.Params; Type[] paramTypes = DtoObject.GenerateTypes(parameters, assemblyName); MethodInfo methodInfo = classType.GetMethod(methodName, paramTypes); if (methodInfo == null) { throw new ApplicationException("Method not found with " + parameters.Length.ToString() + " parameters: " + dtoGetString.MethodName); } object[] paramObjs = DtoObject.GenerateObjects(parameters); string strResult = (string)methodInfo.Invoke(null, paramObjs); strResult = XmlConverter.XmlEscape(strResult); return(strResult); }
public static DataTransferObject Deserialize(string data) { StringReader strReader = new StringReader(data); //XmlReader reader=XmlReader.Create(strReader); XmlTextReader reader = new XmlTextReader(strReader); string strNodeName = ""; while (reader.Read()) { if (reader.NodeType != XmlNodeType.Element) { continue; } strNodeName = reader.Name; break; } //strReader.Close(); //reader.Close(); Type type = Type.GetType("OpenDentBusiness." + strNodeName); //StringReader strReader2=new StringReader(data); //XmlReader reader2=XmlReader.Create(strReader2); XmlSerializer serializer = new XmlSerializer(type); DataTransferObject retVal = (DataTransferObject)serializer.Deserialize(reader); strReader.Close(); reader.Close(); return(retVal); }
public static DataTransferObject Deserialize(string data) { StringReader strReader = new StringReader(data); //XmlReader reader=XmlReader.Create(strReader); XmlTextReader reader = new XmlTextReader(strReader); string strNodeName = ""; while (reader.Read()) { if (reader.NodeType != XmlNodeType.Element) { continue; } strNodeName = reader.Name; break; } //strReader.Close(); //reader.Close(); Type type = Type.GetType("OpenDentBusiness." + strNodeName); //StringReader strReader2=new StringReader(data); //XmlReader reader2=XmlReader.Create(strReader2); XmlSerializer serializer = new XmlSerializer(type); DataTransferObject retVal = (DataTransferObject)serializer.Deserialize(reader); strReader.Close(); reader.Close(); if (retVal.Params != null) { foreach (DtoObject dtoCur in retVal.Params.Where(x => x != null && x.Obj != null)) { dtoCur.Obj = XmlConverter.XmlUnescapeRecursion(dtoCur.Obj.GetType(), dtoCur.Obj); } } return(retVal); }
internal static byte[] SendAndReceive(DataTransferObject dto) { byte[] data = dto.Serialize(); //#if DEBUG // string xmlString=Encoding.UTF8.GetString(data); // Debug.WriteLine("Client Sent: "+xmlString); //#endif if (client == null) { try{ client = new TcpClient(ServerName, ServerPort); netStream = client.GetStream(); } catch { throw new Exception("Server is refusing the connection. Either the server program is not running, or a port on the server is being blocked by a firewall."); } } try{ netStream.Write(data, 0, data.Length); } catch (Exception e) { netStream.Close(); client.Close(); client = null; throw e; } //Receive the TcpServer.response------------------------------------- Byte[] buffer = new Byte[16384]; //a power of 2 that will easily cover average size result sets. //MemoryStream memStream=new MemoryStream(); int numberOfBytesRead = 0; StringBuilder strBuild = new StringBuilder(); //int readValue; Decoder decoder = Encoding.UTF8.GetDecoder(); char[] chars; do { //this next line blocks until the response comes back numberOfBytesRead = netStream.Read(buffer, 0, buffer.Length); //readValue=netStream.ReadByte(); // Use Decoder class to convert from bytes to UTF8 // in case a character spans two buffers. chars = new char[decoder.GetCharCount(buffer, 0, numberOfBytesRead)]; decoder.GetChars(buffer, 0, numberOfBytesRead, chars, 0); strBuild.Append(chars); // Check for EOF or an empty message. if (strBuild.ToString().IndexOf("<EOF>") != -1) { break; } }while(numberOfBytesRead != 0); //netStream.DataAvailable); strBuild.Replace("<EOF>", ""); //memStream must be decoupled by converting to byte[] and then back to memStream. buffer = Encoding.UTF8.GetBytes(strBuild.ToString()); //memStream.ToArray(); return(buffer); }
///<summary></summary> public static void ProcessGetVoid(DtoGetVoid dto) { string result = SendAndReceive(dto); //this might throw an exception if server unavailable if (result != "0") { DtoException exception = (DtoException)DataTransferObject.Deserialize(result); throw new Exception(exception.Message); } }
///<summary>Optionally set hasConnectionLost true to keep the calling thread here until a connection to the Middle Tier connection can be established ///in the event of a web connection failure. Set hasConnectionLost to false if a throw is desired when a connection cannot be made.</summary> public static void ProcessGetVoid(DtoGetVoid dto, bool hasConnectionLost = true) { string result = SendAndReceive(dto, hasConnectionLost); if (result != "0") { DtoException exception = (DtoException)DataTransferObject.Deserialize(result); throw ThrowExceptionForDto(exception); } }
///<summary></summary> public static int ProcessGetInt(DtoGetInt dto) { string result = SendAndReceive(dto); //this might throw an exception if server unavailable try { return(PIn.Int(result)); } catch { DtoException exception = (DtoException)DataTransferObject.Deserialize(result); throw new Exception(exception.Message); } }
///<summary></summary> public static double ProcessGetDouble(DtoGetDouble dto) { string result = SendAndReceive(dto); //this might throw an exception if server unavailable try { return(PIn.Double(result)); } catch { DtoException exception = (DtoException)DataTransferObject.Deserialize(result); throw ThrowExceptionForDto(exception); } }
public static SerializableDictionary <K, V> ProcessGetSerializableDictionary <K, V>(DtoGetSerializableDictionary dto) { string result = SendAndReceive(dto); try { return(XmlConverter.Deserialize <SerializableDictionary <K, V> >(result)); } catch { DtoException exception = (DtoException)DataTransferObject.Deserialize(result); throw ThrowExceptionForDto(exception); } }
public static DataTable ProcessGetTableLow(DtoGetTableLow dto) { string result = SendAndReceive(dto); try { return(XmlConverter.XmlToTable(result)); } catch { DtoException exception = (DtoException)DataTransferObject.Deserialize(result); throw new Exception(exception.Message); } }
///<summary></summary> public static string ProcessGetString(DtoGetString dto) { string result = SendAndReceive(dto); //this might throw an exception if server unavailable DtoException exception; try { exception = (DtoException)DataTransferObject.Deserialize(result); } catch { return(XmlConverter.XmlUnescape(result)); } throw ThrowExceptionForDto(exception); }
///<summary></summary> public static string ProcessGetString(DtoGetString dto) { string result = SendAndReceive(dto); //this might throw an exception if server unavailable DtoException exception; try { exception = (DtoException)DataTransferObject.Deserialize(result); } catch { return(result); } throw new Exception(exception.Message); }
///<summary>Optionally set hasConnectionLost true to keep the calling thread here until a connection to the Middle Tier connection can be established ///in the event of a web connection failure. Set hasConnectionLost to false if a throw is desired when a connection cannot be made.</summary> public static string ProcessGetString(DtoGetString dto, bool hasConnectionLost = true) { string result = SendAndReceive(dto, hasConnectionLost); DtoException exception; try { exception = (DtoException)DataTransferObject.Deserialize(result); } catch { return(XmlConverter.XmlUnescape(result)); } throw ThrowExceptionForDto(exception); }
///<summary>Optionally set hasConnectionLost true to keep the calling thread here until a connection to the Middle Tier connection can be established ///in the event of a web connection failure. Set hasConnectionLost to false if a throw is desired when a connection cannot be made.</summary> internal static string SendAndReceive(DataTransferObject dto, bool hasConnectionLost = true) { //Anyone trying to invoke a method other than CheckUserAndPassword must first check the current HasLoginFailed status as to not call the middle tier too often. bool isCheckUserAndPassword = (dto.MethodName == nameof(OpenDentBusiness) + "." + nameof(Userods) + "." + nameof(Userods.CheckUserAndPassword)); if (!isCheckUserAndPassword && HasLoginFailed) { throw new ODException("Invalid username or password.", ODException.ErrorCodes.CheckUserAndPasswordFailed); } string dtoString = dto.Serialize(); IOpenDentalServer service = OpenDentBusiness.WebServices.OpenDentalServerProxy.GetOpenDentalServerInstance(); return(SendAndReceiveRecursive(service, dtoString, hasConnectionLost)); }
///<summary>Optionally set hasConnectionLost true to keep the calling thread here until a connection to the Middle Tier connection can be established ///in the event of a web connection failure. Set hasConnectionLost to false if a throw is desired when a connection cannot be made.</summary> public static bool ProcessGetBool(DtoGetBool dto, bool hasConnectionLost = true) { string result = SendAndReceive(dto, hasConnectionLost); if (result == "True") { return(true); } if (result == "False") { return(false); } DtoException exception = (DtoException)DataTransferObject.Deserialize(result); throw ThrowExceptionForDto(exception); }
///<summary></summary> public static bool ProcessGetBool(DtoGetBool dto) { string result = SendAndReceive(dto); if (result == "True") { return(true); } if (result == "False") { return(false); } DtoException exception = (DtoException)DataTransferObject.Deserialize(result); throw new Exception(exception.Message); }
///<summary>Optionally set hasConnectionLost true to keep the calling thread here until a connection to the Middle Tier connection can be established ///in the event of a web connection failure. Set hasConnectionLost to false if a throw is desired when a connection cannot be made.</summary> public static DataSet ProcessGetDS(DtoGetDS dto, bool hasConnectionLost = true) { string result = SendAndReceive(dto, hasConnectionLost); if (Regex.IsMatch(result, "<DtoException xmlns:xsi=")) { DtoException exception = (DtoException)DataTransferObject.Deserialize(result); throw new Exception(exception.Message); } try { return(XmlConverter.XmlToDs(result)); } catch (Exception ex) { throw ProcessExceptionDeserialize(result, ex); } }
///<summary></summary> public static DataSet ProcessGetDS(DtoGetDS dto) { string result = SendAndReceive(dto); if (Regex.IsMatch(result, "<DtoException xmlns:xsi=")) { DtoException exception = (DtoException)DataTransferObject.Deserialize(result); throw new Exception(exception.Message); } try { return(XmlConverter.XmlToDs(result)); } catch { DtoException exception = (DtoException)DataTransferObject.Deserialize(result); throw ThrowExceptionForDto(exception); } }
public static DataTransferObject Deserialize(byte[] data) { MemoryStream memStream = new MemoryStream(data); XmlDocument doc = new XmlDocument(); doc.Load(memStream); XmlNode node = doc.SelectSingleNode("/*"); //Console.WriteLine(node.Name+node.InnerText); Type type = Type.GetType("OpenDentBusiness." + node.Name); memStream = new MemoryStream(data); //resets to beginning of stream XmlSerializer serializer = new XmlSerializer(type); DataTransferObject retVal = (DataTransferObject)serializer.Deserialize(memStream); memStream.Close(); return(retVal); }
internal static string SendAndReceive(DataTransferObject dto) { string dtoString = dto.Serialize(); OpenDentalServer.ServiceMain service = new OpenDentBusiness.OpenDentalServer.ServiceMain(); service.Url = ServerURI; string result = service.ProcessRequest(dtoString); //The web service (xml) serializer/deserializer is removing the '\r' portion of our newlines during the data transfer. //Replacing the string is not the best solution but it works for now. The replacing happens inside ProcessRequest() (server side) and here (client side). //It's done server side for usage purposes within the methods being called (exampe: inserting into db) and then on the client side for displaying purposes. if (result != null) { result = result.Replace("\n", "\r\n"); } return(result); }
///<summary>Returns an exception to be thrown if an exception is being caught while attempting to deserialize a serialized string returned ///from the server.</summary> ///<param name="result">The serialized string sent by the server.</param> ///<param name="ex">The exception that was caught while trying to deserialize the result.</param> private static Exception ProcessExceptionDeserialize(string result, Exception ex) { if (ex is ThreadAbortException) { //If we abort a thread while it is trying to deserialize the result, it will attempt to deserialize it below and throw a different //exception. We want the abort exception to bumble up to ODThread to be caught and handled. Normally, ThreadAbortExceptions bubble up //even if caught. However, it does not when a different exception is thrown within a catch. return(ex); } DtoException exception; try { exception = (DtoException)DataTransferObject.Deserialize(result); } catch (Exception e) { throw new AggregateException("Error deserializing result from server.", new Exception("Result: " + result), e, ex); } return(ThrowExceptionForDto(exception)); }
///<summary></summary> public static T ProcessGetObject <T>(DtoGetObject dto) { string result = SendAndReceive(dto); //this might throw an exception if server unavailable try { return(XmlConverter.Deserialize <T>(result)); /* * XmlSerializer serializer=new XmlSerializer(typeof(T)); * //Type.GetType("OpenDentBusiness."+dto.ObjectType)); * StringReader strReader=new StringReader(result); * XmlReader xmlReader=XmlReader.Create(strReader); * object obj=serializer.Deserialize(xmlReader); * strReader.Close(); * xmlReader.Close(); * return (T)obj;*/ } catch { DtoException exception = (DtoException)DataTransferObject.Deserialize(result); throw new Exception(exception.Message); } }
///<summary>Pass in a serialized dto. It returns a dto which must be deserialized by the client. ///Set serverMapPath to the root directory of the OpenDentalServerConfig.xml. Typically Server.MapPath(".") from a web service. ///Optional parameter because it is not necessary for Unit Tests (mock server).</summary> public static string ProcessDto(string dtoString, string serverMapPath = "") { #if DEBUG //System.Threading.Thread.Sleep(100);//to test slowness issues with web service. #endif DataTransferObject dto = DataTransferObject.Deserialize(dtoString); try { string[] methNameComps = GetComponentsFromDtoMeth(dto.MethodName); if (methNameComps.Length == 3 && methNameComps[2].ToLower() == "hashpassword") { return(GetHashPassword(dto)); } //Always attempt to set the database connection settings from the config file if they haven't been set yet. //We use to ONLY load in database settings when Security.LogInWeb was called but that is not good enough now that we have more services. //E.g. We do not want to manually call "Security.LogInWeb" from the CEMT when all we want is a single preference value. if (string.IsNullOrEmpty(DataConnection.GetServerName()) && string.IsNullOrEmpty(DataConnection.GetConnectionString())) { RemotingClient.RemotingRole = RemotingRole.ServerWeb; //the application virtual path is usually /OpenDentalServer, but may be different if hosting multiple databases on one IIS server string configFilePath = ""; if (!string.IsNullOrWhiteSpace(HostingEnvironment.ApplicationVirtualPath) && HostingEnvironment.ApplicationVirtualPath.Length > 1) { //There can be multiple config files within a physical path that is shared by multiple IIS ASP.NET applications. //In order for the same physical path to host multiple applications, they each need a unique config file for db connection settings. //Each application will have a unique ApplicationVirtualPath which we will use to identify the corresponding config.xml. configFilePath = ODFileUtils.CombinePaths(serverMapPath, HostingEnvironment.ApplicationVirtualPath.Trim('/') + "Config.xml"); } if (string.IsNullOrWhiteSpace(configFilePath) || !File.Exists(configFilePath)) //returns false if the file doesn't exist, user doesn't have permission for file, path is blank or null { //either configFilePath not set or file doesn't exist, default to OpenDentalServerConfig.xml configFilePath = ODFileUtils.CombinePaths(serverMapPath, "OpenDentalServerConfig.xml"); } Userods.LoadDatabaseInfoFromFile(configFilePath); } //Set Security.CurUser so that queries can be run against the db as if it were this user. Security.CurUser = Userods.CheckUserAndPassword(dto.Credentials.Username , dto.Credentials.Password , Programs.IsEnabled(ProgramName.eClinicalWorks)); Security.PasswordTyped = dto.Credentials.Password; Type type = dto.GetType(); #region DtoGetTable if (type == typeof(DtoGetTable)) { DtoGetTable dtoGetTable = (DtoGetTable)dto; string[] fullNameComponents = GetComponentsFromDtoMeth(dtoGetTable.MethodName); string assemblyName = fullNameComponents[0]; //OpenDentBusiness or else a plugin name string className = fullNameComponents[1]; string methodName = fullNameComponents[2]; Type classType = null; Assembly ass = Plugins.GetAssembly(assemblyName); if (ass == null) { classType = Type.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className + "," + assemblyName); } else //plugin was found { classType = ass.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className); } DtoObject[] parameters = dtoGetTable.Params; Type[] paramTypes = DtoObject.GenerateTypes(parameters, assemblyName); MethodInfo methodInfo = classType.GetMethod(methodName, paramTypes); if (methodInfo == null) { throw new ApplicationException("Method not found with " + parameters.Length.ToString() + " parameters: " + dtoGetTable.MethodName); } object[] paramObjs = DtoObject.GenerateObjects(parameters); DataTable dt = (DataTable)methodInfo.Invoke(null, paramObjs); String response = XmlConverter.TableToXml(dt); return(response); } #endregion #region DtoGetTableLow else if (type == typeof(DtoGetTableLow)) { DtoGetTableLow dtoGetTableLow = (DtoGetTableLow)dto; DtoObject[] parameters = dtoGetTableLow.Params; object[] paramObjs = DtoObject.GenerateObjects(parameters); DataTable dt = Reports.GetTable((string)paramObjs[0]); String response = XmlConverter.TableToXml(dt); return(response); } #endregion #region DtoGetDS else if (type == typeof(DtoGetDS)) { DtoGetDS dtoGetDS = (DtoGetDS)dto; string[] fullNameComponents = GetComponentsFromDtoMeth(dtoGetDS.MethodName); string assemblyName = fullNameComponents[0]; //OpenDentBusiness or else a plugin name string className = fullNameComponents[1]; string methodName = fullNameComponents[2]; Type classType = null; Assembly ass = Plugins.GetAssembly(assemblyName); if (ass == null) { classType = Type.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className + "," + assemblyName); } else //plugin was found { classType = ass.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className); } DtoObject[] parameters = dtoGetDS.Params; Type[] paramTypes = DtoObject.GenerateTypes(parameters, assemblyName); MethodInfo methodInfo = classType.GetMethod(methodName, paramTypes); if (methodInfo == null) { throw new ApplicationException("Method not found with " + parameters.Length.ToString() + " parameters: " + dtoGetDS.MethodName); } object[] paramObjs = DtoObject.GenerateObjects(parameters); DataSet ds = (DataSet)methodInfo.Invoke(null, paramObjs); String response = XmlConverter.DsToXml(ds); return(response); } #endregion #region DtoGetSerializableDictionary else if (type == typeof(DtoGetSerializableDictionary)) { DtoGetSerializableDictionary dtoGetSD = (DtoGetSerializableDictionary)dto; string[] fullNameComponents = GetComponentsFromDtoMeth(dtoGetSD.MethodName); string assemblyName = fullNameComponents[0]; //OpenDentBusiness or else a plugin name string className = fullNameComponents[1]; string methodName = fullNameComponents[2]; Type classType = null; Assembly ass = Plugins.GetAssembly(assemblyName); if (ass == null) { classType = Type.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className + "," + assemblyName); } else //plugin was found { classType = ass.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className); } DtoObject[] parameters = dtoGetSD.Params; Type[] paramTypes = DtoObject.GenerateTypes(parameters, assemblyName); MethodInfo methodInfo = classType.GetMethod(methodName, paramTypes); if (methodInfo == null) { throw new ApplicationException("Method not found with " + parameters.Length.ToString() + " parameters: " + dtoGetSD.MethodName); } object[] paramObjs = DtoObject.GenerateObjects(parameters); Object objResult = methodInfo.Invoke(null, paramObjs); Type returnType = methodInfo.ReturnType; return(XmlConverter.Serialize(returnType, objResult)); } #endregion #region DtoGetLong else if (type == typeof(DtoGetLong)) { DtoGetLong dtoGetLong = (DtoGetLong)dto; string[] fullNameComponents = GetComponentsFromDtoMeth(dtoGetLong.MethodName); string assemblyName = fullNameComponents[0]; //OpenDentBusiness or else a plugin name string className = fullNameComponents[1]; string methodName = fullNameComponents[2]; Type classType = null; Assembly ass = Plugins.GetAssembly(assemblyName); if (ass == null) { classType = Type.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className + "," + assemblyName); } else //plugin was found { classType = ass.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className); } DtoObject[] parameters = dtoGetLong.Params; Type[] paramTypes = DtoObject.GenerateTypes(parameters, assemblyName); MethodInfo methodInfo = classType.GetMethod(methodName, paramTypes); if (methodInfo == null) { throw new ApplicationException("Method not found with " + parameters.Length.ToString() + " parameters: " + dtoGetLong.MethodName); } object[] paramObjs = DtoObject.GenerateObjects(parameters); long longResult = (long)methodInfo.Invoke(null, paramObjs); return(longResult.ToString()); } #endregion #region DtoGetInt else if (type == typeof(DtoGetInt)) { DtoGetInt dtoGetInt = (DtoGetInt)dto; string[] fullNameComponents = GetComponentsFromDtoMeth(dtoGetInt.MethodName); string assemblyName = fullNameComponents[0]; //OpenDentBusiness or else a plugin name string className = fullNameComponents[1]; string methodName = fullNameComponents[2]; Type classType = null; Assembly ass = Plugins.GetAssembly(assemblyName); if (ass == null) { classType = Type.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className + "," + assemblyName); } else //plugin was found { classType = ass.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className); } DtoObject[] parameters = dtoGetInt.Params; Type[] paramTypes = DtoObject.GenerateTypes(parameters, assemblyName); MethodInfo methodInfo = classType.GetMethod(methodName, paramTypes); if (methodInfo == null) { throw new ApplicationException("Method not found with " + parameters.Length.ToString() + " parameters: " + dtoGetInt.MethodName); } object[] paramObjs = DtoObject.GenerateObjects(parameters); int intResult = (int)methodInfo.Invoke(null, paramObjs); return(intResult.ToString()); } #endregion #region DtoGetDouble else if (type == typeof(DtoGetDouble)) { DtoGetDouble dtoGetDouble = (DtoGetDouble)dto; string[] fullNameComponents = GetComponentsFromDtoMeth(dtoGetDouble.MethodName); string assemblyName = fullNameComponents[0]; //OpenDentBusiness or else a plugin name string className = fullNameComponents[1]; string methodName = fullNameComponents[2]; Type classType = null; Assembly ass = Plugins.GetAssembly(assemblyName); if (ass == null) { classType = Type.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className + "," + assemblyName); } else //plugin was found { classType = ass.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className); } DtoObject[] parameters = dtoGetDouble.Params; Type[] paramTypes = DtoObject.GenerateTypes(parameters, assemblyName); MethodInfo methodInfo = classType.GetMethod(methodName, paramTypes); if (methodInfo == null) { throw new ApplicationException("Method not found with " + parameters.Length.ToString() + " parameters: " + dtoGetDouble.MethodName); } object[] paramObjs = DtoObject.GenerateObjects(parameters); double doubleResult = (double)methodInfo.Invoke(null, paramObjs); return(doubleResult.ToString()); } #endregion #region DtoGetVoid else if (type == typeof(DtoGetVoid)) { DtoGetVoid dtoGetVoid = (DtoGetVoid)dto; string[] fullNameComponents = GetComponentsFromDtoMeth(dtoGetVoid.MethodName); string assemblyName = fullNameComponents[0]; //OpenDentBusiness or else a plugin name string className = fullNameComponents[1]; string methodName = fullNameComponents[2]; Type classType = null; Assembly ass = Plugins.GetAssembly(assemblyName); if (ass == null) { classType = Type.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className + "," + assemblyName); } else //plugin was found { classType = ass.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className); } DtoObject[] parameters = dtoGetVoid.Params; Type[] paramTypes = DtoObject.GenerateTypes(parameters, assemblyName); MethodInfo methodInfo = classType.GetMethod(methodName, paramTypes); if (methodInfo == null) { throw new ApplicationException("Method not found with " + parameters.Length.ToString() + " parameters: " + dtoGetVoid.MethodName); } object[] paramObjs = DtoObject.GenerateObjects(parameters); methodInfo.Invoke(null, paramObjs); return("0"); } #endregion #region DtoGetObject else if (type == typeof(DtoGetObject)) { DtoGetObject dtoGetObject = (DtoGetObject)dto; string[] fullNameComponents = GetComponentsFromDtoMeth(dtoGetObject.MethodName); string assemblyName = fullNameComponents[0]; //OpenDentBusiness or else a plugin name string className = fullNameComponents[1]; string methodName = fullNameComponents[2]; //if(className != "Security" || methodName != "LogInWeb") {//because credentials will be checked inside that method // Userods.CheckCredentials(dtoGetObject.Credentials);//will throw exception if fails. //} Type classType = null; Assembly ass = Plugins.GetAssembly(assemblyName); //if(className!="Security" || methodName!="LogInWeb") {//Do this for everything except Security.LogInWeb, because Plugins.GetAssembly will fail in that case. // ass=Plugins.GetAssembly(assemblyName); //} if (ass == null) { classType = Type.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className + "," + assemblyName); } else //plugin was found { classType = ass.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className); } DtoObject[] parameters = dtoGetObject.Params; Type[] paramTypes = DtoObject.GenerateTypes(parameters, assemblyName); MethodInfo methodInfo = classType.GetMethod(methodName, paramTypes); if (methodInfo == null) { throw new ApplicationException("Method not found with " + parameters.Length.ToString() + " parameters: " + dtoGetObject.MethodName); } if (className == "Security" && methodName == "LogInWeb") { parameters[2] = new DtoObject(serverMapPath, typeof(string)); //because we can't access this variable from within OpenDentBusiness. RemotingClient.RemotingRole = RemotingRole.ServerWeb; } object[] paramObjs = DtoObject.GenerateObjects(parameters); Object objResult = methodInfo.Invoke(null, paramObjs); Type returnType = methodInfo.ReturnType; if (returnType.IsInterface) { objResult = new DtoObject(objResult, objResult?.GetType() ?? returnType); returnType = typeof(DtoObject); } return(XmlConverter.Serialize(returnType, objResult)); } #endregion #region DtoGetString else if (type == typeof(DtoGetString)) { DtoGetString dtoGetString = (DtoGetString)dto; string[] fullNameComponents = GetComponentsFromDtoMeth(dtoGetString.MethodName); string assemblyName = fullNameComponents[0]; //OpenDentBusiness or else a plugin name string className = fullNameComponents[1]; string methodName = fullNameComponents[2]; Type classType = null; Assembly ass = Plugins.GetAssembly(assemblyName); if (ass == null) { classType = Type.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className + "," + assemblyName); } else //plugin was found { classType = ass.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className); } DtoObject[] parameters = dtoGetString.Params; Type[] paramTypes = DtoObject.GenerateTypes(parameters, assemblyName); MethodInfo methodInfo = classType.GetMethod(methodName, paramTypes); if (methodInfo == null) { throw new ApplicationException("Method not found with " + parameters.Length.ToString() + " parameters: " + dtoGetString.MethodName); } object[] paramObjs = DtoObject.GenerateObjects(parameters); string strResult = (string)methodInfo.Invoke(null, paramObjs); strResult = XmlConverter.XmlEscape(strResult); return(strResult); } #endregion #region DtoGetBool else if (type == typeof(DtoGetBool)) { DtoGetBool dtoGetBool = (DtoGetBool)dto; string[] fullNameComponents = GetComponentsFromDtoMeth(dtoGetBool.MethodName); string assemblyName = fullNameComponents[0]; //OpenDentBusiness or else a plugin name string className = fullNameComponents[1]; string methodName = fullNameComponents[2]; Type classType = null; Assembly ass = Plugins.GetAssembly(assemblyName); if (ass == null) { classType = Type.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className + "," + assemblyName); } else //plugin was found { classType = ass.GetType(assemblyName //actually, the namespace which we require to be same as assembly by convention + "." + className); } DtoObject[] parameters = dtoGetBool.Params; Type[] paramTypes = DtoObject.GenerateTypes(parameters, assemblyName); MethodInfo methodInfo = classType.GetMethod(methodName, paramTypes); if (methodInfo == null) { throw new ApplicationException("Method not found with " + parameters.Length.ToString() + " parameters: " + dtoGetBool.MethodName); } object[] paramObjs = DtoObject.GenerateObjects(parameters); bool boolResult = (bool)methodInfo.Invoke(null, paramObjs); return(boolResult.ToString()); } #endregion else { throw new NotSupportedException("Dto type not supported: " + type.FullName); } } catch (Exception e) { DtoException exception = new DtoException(); exception.ExceptionType = e.GetType().BaseType.Name; //Since the exception was down converted to a regular exception, we need the BaseType. if (e.InnerException == null) { exception.Message = e.Message; } else { exception.Message = e.InnerException.Message; } return(exception.Serialize()); } }
///<summary>Pass in a serialized dto. It returns a dto which must be deserialized by the client. ///Set serverMapPath to the root directory of the OpenDentalServerConfig.xml. Typically Server.MapPath(".") from a web service. ///Optional parameter because it is not necessary for Unit Tests (mock server).</summary> public static string ProcessDto(string dtoString, string serverMapPath = "") { try { #region Normalize DateTime if (!_isMiddleTierInitialized) { //If this fails, the exception will throw and be serialized and sent to the client. ODInitialize.Initialize(); //Because Security._curUserT is a thread static field, we need to make sure that any new threads that are spawned have that field set. ODThread.AddInitializeHandler <Userod>(() => Security.CurUser.Copy(), user => Security.CurUser = user); //Same thing for PasswordTyped. ODThread.AddInitializeHandler <string>(() => Security.PasswordTyped, password => Security.PasswordTyped = password); //Ditto for CurComputerName ODThread.AddInitializeHandler <string>(() => Security.CurComputerName, computerName => Security.CurComputerName = computerName); //Calling CDT.Class1.Decrypt will cause CDT to verify the assembly and then save the encryption key. This needs to be done here because //if we later call CDT.Class1.Decrypt inside a thread, we won't we able to find OpenDentalServer.dll in the call stack. ODException.SwallowAnyException(() => CDT.Class1.Decrypt("odv2e$fakeciphertext", out _)); _isMiddleTierInitialized = true; } #endregion #region Initialize Database Connection //Always attempt to set the database connection settings from the config file if they haven't been set yet. //We use to ONLY load in database settings when Security.LogInWeb was called but that is not good enough now that we have more services. //E.g. We do not want to manually call "Security.LogInWeb" from the CEMT when all we want is a single preference value. if (string.IsNullOrEmpty(DataConnection.GetServerName()) && string.IsNullOrEmpty(DataConnection.GetConnectionString())) { RemotingClient.RemotingRole = RemotingRole.ServerWeb; //the application virtual path is usually /OpenDentalServer, but may be different if hosting multiple databases on one IIS server string configFilePath = ""; if (!string.IsNullOrWhiteSpace(HostingEnvironment.ApplicationVirtualPath) && HostingEnvironment.ApplicationVirtualPath.Length > 1) { //There can be multiple config files within a physical path that is shared by multiple IIS ASP.NET applications. //In order for the same physical path to host multiple applications, they each need a unique config file for db connection settings. //Each application will have a unique ApplicationVirtualPath which we will use to identify the corresponding config.xml. configFilePath = ODFileUtils.CombinePaths(serverMapPath, HostingEnvironment.ApplicationVirtualPath.Trim('/') + "Config.xml"); } if (string.IsNullOrWhiteSpace(configFilePath) || !File.Exists(configFilePath)) //returns false if the file doesn't exist, user doesn't have permission for file, path is blank or null { //either configFilePath not set or file doesn't exist, default to OpenDentalServerConfig.xml configFilePath = ODFileUtils.CombinePaths(serverMapPath, "OpenDentalServerConfig.xml"); } Userods.LoadDatabaseInfoFromFile(configFilePath); } #endregion DataTransferObject dto = DataTransferObject.Deserialize(dtoString); DtoInformation dtoInformation = new DtoInformation(dto); if (dtoInformation.FullNameComponents.Length == 3 && dtoInformation.FullNameComponents[2].ToLower() == "hashpassword") { return(dtoInformation.GetHashPassword()); } //Set Security.CurUser so that queries can be run against the db as if it were this user. Security.CurUser = Userods.CheckUserAndPassword(dto.Credentials.Username, dto.Credentials.Password , Programs.UsingEcwTightOrFullMode()); Security.PasswordTyped = dto.Credentials.Password; //Set the computer name so securitylog entries use the client's computer name instead of the middle tier server name //Older clients might not include ComputerName in the dto, so we need to make sure it's not null. Security.CurComputerName = dto.ComputerName ?? ""; Type type = dto.GetType(); #region DtoGetTable if (type == typeof(DtoGetTable)) { DataTable dt = (DataTable)dtoInformation.MethodInfo.Invoke(null, dtoInformation.ParamObjs); return(XmlConverter.TableToXml(dt)); } #endregion #region DtoGetTableLow else if (type == typeof(DtoGetTableLow)) { DataTable dt = Reports.GetTable((string)dtoInformation.ParamObjs[0]); return(XmlConverter.TableToXml(dt)); } #endregion #region DtoGetDS else if (type == typeof(DtoGetDS)) { DataSet ds = (DataSet)dtoInformation.MethodInfo.Invoke(null, dtoInformation.ParamObjs); return(XmlConverter.DsToXml(ds)); } #endregion #region DtoGetSerializableDictionary else if (type == typeof(DtoGetSerializableDictionary)) { Object objResult = dtoInformation.MethodInfo.Invoke(null, dtoInformation.ParamObjs); Type returnType = dtoInformation.MethodInfo.ReturnType; return(XmlConverterSerializer.Serialize(returnType, objResult)); } #endregion #region DtoGetLong else if (type == typeof(DtoGetLong)) { long longResult = (long)dtoInformation.MethodInfo.Invoke(null, dtoInformation.ParamObjs); return(longResult.ToString()); } #endregion #region DtoGetInt else if (type == typeof(DtoGetInt)) { int intResult = (int)dtoInformation.MethodInfo.Invoke(null, dtoInformation.ParamObjs); return(intResult.ToString()); } #endregion #region DtoGetDouble else if (type == typeof(DtoGetDouble)) { double doubleResult = (double)dtoInformation.MethodInfo.Invoke(null, dtoInformation.ParamObjs); return(doubleResult.ToString()); } #endregion #region DtoGetVoid else if (type == typeof(DtoGetVoid)) { dtoInformation.MethodInfo.Invoke(null, dtoInformation.ParamObjs); return("0"); } #endregion #region DtoGetObject else if (type == typeof(DtoGetObject)) { if (dtoInformation.ClassName == "Security" && dtoInformation.MethodName == "LogInWeb") { dtoInformation.Parameters[2] = new DtoObject(serverMapPath, typeof(string)); //because we can't access this variable from within OpenDentBusiness. RemotingClient.RemotingRole = RemotingRole.ServerWeb; //We just changed the number of parameters so we need to regenerate ParamObjs. dtoInformation.ParamObjs = DtoObject.GenerateObjects(dtoInformation.Parameters); } Object objResult = dtoInformation.MethodInfo.Invoke(null, dtoInformation.ParamObjs); Type returnType = dtoInformation.MethodInfo.ReturnType; if (returnType.IsInterface) { objResult = new DtoObject(objResult, objResult?.GetType() ?? returnType); returnType = typeof(DtoObject); } return(XmlConverterSerializer.Serialize(returnType, objResult)); } #endregion #region DtoGetString else if (type == typeof(DtoGetString)) { string strResult = (string)dtoInformation.MethodInfo.Invoke(null, dtoInformation.ParamObjs); return(XmlConverter.XmlEscape(strResult)); } #endregion #region DtoGetBool else if (type == typeof(DtoGetBool)) { bool boolResult = (bool)dtoInformation.MethodInfo.Invoke(null, dtoInformation.ParamObjs); return(boolResult.ToString()); } #endregion else { throw new NotSupportedException("Dto type not supported: " + type.FullName); } } catch (Exception e) { DtoException exception = new DtoException(); if (e.InnerException == null) { exception = GetDtoException(e); } else { exception = GetDtoException(e.InnerException); } return(exception.Serialize()); } }