diff --git a/MagData/MagData.csproj b/MagData/MagData.csproj index 2eb06c17..e87689d8 100644 --- a/MagData/MagData.csproj +++ b/MagData/MagData.csproj @@ -178,6 +178,7 @@ + DS_Mag.xsd diff --git a/MapoDb/FluxArchive.cs b/MapoDb/FluxArchive.cs index 2cd6e1be..4ae32152 100644 --- a/MapoDb/FluxArchive.cs +++ b/MapoDb/FluxArchive.cs @@ -8,285 +8,312 @@ using System.Text; namespace MapoDb { - /************************************************************** - * Classe gestione FluxLog - * - * automaticamente gestisce dati su SqlServer / Redis (+recenti) - * oppure su MongoDB (+ vecchi) - * - * rif x mongoDB - * - * rif x windows setup (abilitazione firewall, remote access, auth...) - * - * https://docs.mongodb.com/manual/tutorial/configure-windows-netsh-firewall/ - * https://www.configserverfirewall.com/mongodb/mongodb-allow-remote-connections/ - * https://www.shellhacks.com/mongodb-allow-remote-access/ - * https://stackoverflow.com/questions/3891657/setup-mongodb-on-windows-server-2008 - * - * (conf file in C:\Program Files\MongoDB\Server\4.2\bin) - * - * - * test rilettura: https://stackoverflow.com/questions/2943222/find-objects-between-two-dates-mongodb - * https://studio3t.com/knowledge-base/articles/mongodb-find-method/ - * https://github.com/mongodb/mongo-csharp-driver - * http://www.binaryheap.com/tech/time-series-data-in-mongodb/ - * https://www.codeproject.com/Tips/760099/Resampling-and-merging-time-series-data-using-LINQ - * https://docs.microsoft.com/it-it/aspnet/core/tutorials/first-mongo-app?view=aspnetcore-3.0&tabs=visual-studio - * https://www.codementor.io/pmbanugo/working-with-mongodb-in-net-1-basics-g4frivcvz - * https://www.codementor.io/pmbanugo/working-with-mongodb-in-net-2-retrieving-mrlbeanm5 - * https://www.codementor.io/pmbanugo/working-with-mongodb-in-net-part-3-skip-sort-limit-and-projections-oqfwncyka - *************************************************************/ + /************************************************************** + * Classe gestione FluxLog + * + * automaticamente gestisce dati su SqlServer / Redis (+recenti) + * oppure su MongoDB (+ vecchi) + * + * rif x mongoDB + * + * rif x windows setup (abilitazione firewall, remote access, auth...) + * + * https://docs.mongodb.com/manual/tutorial/configure-windows-netsh-firewall/ + * https://www.configserverfirewall.com/mongodb/mongodb-allow-remote-connections/ + * https://www.shellhacks.com/mongodb-allow-remote-access/ + * https://stackoverflow.com/questions/3891657/setup-mongodb-on-windows-server-2008 + * + * (conf file in C:\Program Files\MongoDB\Server\4.2\bin) + * + * + * test rilettura: https://stackoverflow.com/questions/2943222/find-objects-between-two-dates-mongodb + * https://studio3t.com/knowledge-base/articles/mongodb-find-method/ + * https://github.com/mongodb/mongo-csharp-driver + * http://www.binaryheap.com/tech/time-series-data-in-mongodb/ + * https://www.codeproject.com/Tips/760099/Resampling-and-merging-time-series-data-using-LINQ + * https://docs.microsoft.com/it-it/aspnet/core/tutorials/first-mongo-app?view=aspnetcore-3.0&tabs=visual-studio + * https://www.codementor.io/pmbanugo/working-with-mongodb-in-net-1-basics-g4frivcvz + * https://www.codementor.io/pmbanugo/working-with-mongodb-in-net-2-retrieving-mrlbeanm5 + * https://www.codementor.io/pmbanugo/working-with-mongodb-in-net-part-3-skip-sort-limit-and-projections-oqfwncyka + *************************************************************/ - - /// - /// Classe che si occupa di gestire i dati di flusso - /// - i dati inizialmente sono in REDIS e DB quando accumulati da IOB - /// - successivamente i dati vengono archiviati come oggetti BSON in MongoDB - /// - public class FluxArchive - { + /// + /// Classe che si occupa di gestire i dati di flusso + /// - i dati inizialmente sono in REDIS e DB quando accumulati da IOB + /// - successivamente i dati vengono archiviati come oggetti BSON in MongoDB + /// + public class FluxArchive + { #if false string mdbConnString = "mongodb://W2019-MONGODB:27017"; //string mdbConnString = "mongodb://localhost:27017"; - MongoClient client; + MongoClient client; #endif - /// - /// Database corrente MongoDB - /// - IMongoDatabase database; - /// - /// Oggetto datalayer - /// - DataLayer DataLayerObj = new DataLayer(); - /// - /// Classe gestione archivio allarmi - /// - public FluxArchive() - { + + #region Private Fields + + /// + /// Database corrente MongoDB + /// + private IMongoDatabase database; + + /// + /// Oggetto datalayer + /// + private DataLayer DataLayerObj = new DataLayer(); + + #endregion Private Fields + + #region Public Fields + + public static FluxArchive man = new FluxArchive(); + + #endregion Public Fields + + #region Public Constructors + + /// + /// Classe gestione archivio allarmi + /// + public FluxArchive() + { #if false // rifare avvio con lettura da web.config... client = new MongoClient(mdbConnString); database = client.GetDatabase("MAPO"); #endif - database = memLayer.ML.getMongoDatabase("MAPO"); - // init oggetto datalayer - DataLayerObj = new DataLayer(); - } - public static FluxArchive man = new FluxArchive(); - /// - /// Effettua il trasferimento dati da SqlDB a MongoDB - /// - /// data di aprtenza - /// num giorni da trasferire - public exeResult trasferDataFromDb(DateTime data2transfer, int numDays) - { - exeResult answ = new exeResult(); - StringBuilder sb = new StringBuilder(); - Stopwatch sw = new Stopwatch(); - DateTime tStamp; + database = memLayer.ML.getMongoDatabase("MAPO"); + // init oggetto datalayer + DataLayerObj = new DataLayer(); + } - // oggetto gestione dati ts raggruppati - var collRawData = database.GetCollection("FluxLogRawData"); - var collHistData = database.GetCollection("FluxLogHistData"); - var builderRaw = Builders.Filter; - var builderHist = Builders.Filter; - string currDateStr = ""; - int startYMD = 0; - int endYMD = 0; - int currYMD = 0; + #endregion Public Constructors - // Effettuo eliminazione records x TUTTO il periodo dei dati RAW e stats... - string startDateStr = data2transfer.ToString("yyyyMMdd"); - string endDateStr = data2transfer.AddDays(numDays).ToString("yyyyMMdd"); - int.TryParse(startDateStr, out startYMD); - int.TryParse(endDateStr, out endYMD); - // filtri e delete - var filtRawOld = builderRaw.Gte(u => u.dateYMD, startYMD) & builderRaw.Lte(u => u.dateYMD, endYMD); - collRawData.DeleteMany(filtRawOld); - var filtHistOld = builderHist.Gte(u => u.dateYMD, startYMD) & builderHist.Lte(u => u.dateYMD, endYMD); - collHistData.DeleteMany(filtHistOld); + #region Protected Methods - // faccio ciclo su OGNI macchina - sw.Start(); - var elencoMacchine = DataLayerObj.taMacchine.GetData(); - foreach (var macchina in elencoMacchine) - { - sb.AppendLine($"Inizio processing macchina {macchina.IdxMacchina}"); - // faccio ciclo su gg richiesti... - for (int i = 0; i < numDays; i++) + /// + /// Calcola statistiche per i dati giornalieri processati + /// + /// + /// + protected histData getStats(List datiGiornalieri) { - tStamp = data2transfer.AddDays(i); - currDateStr = tStamp.ToString("yyyyMMdd"); - int.TryParse(currDateStr, out currYMD); - // leggo da DB i records... - DS_applicazione.FluxLogDataTable tabDati = DataLayerObj.taFL.getFiltOrd(macchina.IdxMacchina, tStamp, tStamp.AddDays(1), true); - // solo se ho dati... - if (tabDati.Count > 0) - { - // chiamo procedura x conversione - List risultato = convertTable(tabDati, tStamp, timeWindow.day); - // salvo in blocco - if (risultato.Count > 0) + // init oggetti + histData currHist; + varStats currStat; + List statistiche = new List(); + int sampleNumRec = 1; + float sampleTotal = 0; + float sampleMinVal = 0; + float sampleMaxVal = 0; + float sampleAvg = 0; + float currVal = 0; + bool fatto = false; + string macName = ""; + int dateYMD = 0; + // ciclo x ogni variabile + foreach (var item in datiGiornalieri) { - try - { - collRawData.InsertMany(risultato); - // calcolo la NUOVA statistica giornaliera... - var resStats = getStats(risultato); - // salvo! - collHistData.InsertOne(resStats); - } - catch (Exception exc) - { } + if (item.samples != null) + { + if (string.IsNullOrEmpty(macName)) + { + macName = item.macName; + dateYMD = item.dateYMD; + } + // reset vabiabili + sampleTotal = 0; + sampleMinVal = 0; + sampleMaxVal = 0; + sampleAvg = 0; + // calcolo statistiche + sampleNumRec = item.samples.Count; + foreach (var sample in item.samples) + { + fatto = float.TryParse(sample.value, out currVal); + if (fatto) + { + sampleTotal += currVal; + sampleMaxVal = sampleMaxVal < currVal ? currVal : sampleMaxVal; + sampleMinVal = sampleMinVal > currVal ? currVal : sampleMinVal; + } + } + if (sampleNumRec > 0) + { + sampleAvg = sampleTotal / sampleNumRec; + } + // salvo statistica + currStat = new varStats() + { + varName = item.varName, + numRec = sampleNumRec, + avg = sampleAvg, + min = sampleMinVal, + max = sampleMaxVal + }; + statistiche.Add(currStat); + } } - sb.AppendLine($"DB {tStamp}: {tabDati.Count}rec | MongoDb {risultato.Count} RAW DOC in {sw.ElapsedMilliseconds / 1000} sec"); - } - } - } - // restituisco messaggio... - answ.esito = esitoExec.ok; - answ.message = sb.ToString(); - return answ; - } - - /// - /// Converte una tabella dati da DB in una lista di oggetti pronti x salvataggio su MongoDb - /// - /// Tabelal dei dati RAW registrati - /// Data di riferimento - /// Periodo del campionamento desiderato (e passato coi dati che sono relativi a tale periodo...) - public List convertTable(DS_applicazione.FluxLogDataTable tabDati, DateTime tStamp, timeWindow periodo) - { - // init oggetti - List listaRecords = new List(); - rawData currRecord = null; - List valori = new List(); - rawSample campione = null; - string currFlux = ""; - string currMacc = ""; - string tStampString = tStamp.ToString("yyyyMMdd"); - int tStampYMD = 0; - int.TryParse(tStampString, out tStampYMD); - foreach (var item in tabDati) - { - // controllo flusso x nuovo record... - if (item.CodFlux != currFlux || item.IdxMacchina != currMacc) - { - // salvo il VECCHIO record... - if (currRecord != null) - { - currRecord.samples = valori; - listaRecords.Add(currRecord); - valori = null; - currRecord = null; - } - // nuovi record... - currFlux = item.CodFlux; - currMacc = item.IdxMacchina; - valori = new List(); - currRecord = new rawData() - { - macName = currMacc, - varName = currFlux, - varType = plcDataType.Real, // fare!!! - dateYMD = tStampYMD, - period = periodo - }; - } - campione = new rawSample() - { - timeStamp = item.dtEvento, - value = item.Valore - }; - // aggiunta sample ai record prec... - if (campione != null && currRecord != null) - { - valori.Add(campione); - campione = null; - } - } - // aggiungo ultimo... salvo il VECCHIO record... - if (currRecord != null) - { - currRecord.samples = valori; - listaRecords.Add(currRecord); - } - return listaRecords; - } - /// - /// Calcola statistiche per i dati giornalieri processati - /// - /// - /// - protected histData getStats(List datiGiornalieri) - { - // init oggetti - histData currHist; - varStats currStat; - List statistiche = new List(); - int sampleNumRec = 1; - float sampleTotal = 0; - float sampleMinVal = 0; - float sampleMaxVal = 0; - float sampleAvg = 0; - float currVal = 0; - bool fatto = false; - string macName = ""; - int dateYMD = 0; - // ciclo x ogni variabile - foreach (var item in datiGiornalieri) - { - if (item.samples != null) - { - if (string.IsNullOrEmpty(macName)) - { - macName = item.macName; - dateYMD = item.dateYMD; - } - // reset vabiabili - sampleTotal = 0; - sampleMinVal = 0; - sampleMaxVal = 0; - sampleAvg = 0; - // calcolo statistiche - sampleNumRec = item.samples.Count; - foreach (var sample in item.samples) - { - fatto = float.TryParse(sample.value, out currVal); - if (fatto) + currHist = new histData() { - sampleTotal += currVal; - sampleMaxVal = sampleMaxVal < currVal ? currVal : sampleMaxVal; - sampleMinVal = sampleMinVal > currVal ? currVal : sampleMinVal; - } - } - if (sampleNumRec > 0) - { - sampleAvg = sampleTotal / sampleNumRec; - } - // salvo statistica - currStat = new varStats() - { - varName = item.varName, - numRec = sampleNumRec, - avg = sampleAvg, - min = sampleMinVal, - max = sampleMaxVal - }; - statistiche.Add(currStat); + macName = macName, + varType = plcDataType.Real, + dateYMD = dateYMD, + period = timeWindow.day, + stats = statistiche + }; + // restituisco... + return currHist; } - } - currHist = new histData() - { - macName = macName, - varType = plcDataType.Real, - dateYMD = dateYMD, - period = timeWindow.day, - stats = statistiche - }; - // restituisco... - return currHist; + + #endregion Protected Methods + + #region Public Methods + + /// + /// Converte una tabella dati da DB in una lista di oggetti pronti x salvataggio su MongoDb + /// + /// Tabelal dei dati RAW registrati + /// Data di riferimento + /// Periodo del campionamento desiderato (e passato coi dati che sono relativi a tale periodo...) + public List convertTable(DS_applicazione.FluxLogDataTable tabDati, DateTime tStamp, timeWindow periodo) + { + // init oggetti + List listaRecords = new List(); + rawData currRecord = null; + List valori = new List(); + rawSample campione = null; + string currFlux = ""; + string currMacc = ""; + string tStampString = tStamp.ToString("yyyyMMdd"); + int tStampYMD = 0; + int.TryParse(tStampString, out tStampYMD); + foreach (var item in tabDati) + { + // controllo flusso x nuovo record... + if (item.CodFlux != currFlux || item.IdxMacchina != currMacc) + { + // salvo il VECCHIO record... + if (currRecord != null) + { + currRecord.samples = valori; + listaRecords.Add(currRecord); + valori = null; + currRecord = null; + } + // nuovi record... + currFlux = item.CodFlux; + currMacc = item.IdxMacchina; + valori = new List(); + currRecord = new rawData() + { + macName = currMacc, + varName = currFlux, + varType = plcDataType.Real, // fare!!! + dateYMD = tStampYMD, + period = periodo + }; + } + campione = new rawSample() + { + timeStamp = item.dtEvento, + value = item.Valore + }; + // aggiunta sample ai record prec... + if (campione != null && currRecord != null) + { + valori.Add(campione); + campione = null; + } + } + // aggiungo ultimo... salvo il VECCHIO record... + if (currRecord != null) + { + currRecord.samples = valori; + listaRecords.Add(currRecord); + } + return listaRecords; + } + + /// + /// Effettua il trasferimento dati da SqlDB a MongoDB + /// + /// data di aprtenza + /// num giorni da trasferire + public exeResult trasferDataFromDb(DateTime data2transfer, int numDays) + { + exeResult answ = new exeResult(); + StringBuilder sb = new StringBuilder(); + Stopwatch sw = new Stopwatch(); + DateTime tStamp; + + // oggetto gestione dati ts raggruppati + var collRawData = database.GetCollection("FluxLogRawData"); + var collHistData = database.GetCollection("FluxLogHistData"); + var builderRaw = Builders.Filter; + var builderHist = Builders.Filter; + string currDateStr = ""; + int startYMD = 0; + int endYMD = 0; + int currYMD = 0; + + // Effettuo eliminazione records x TUTTO il periodo dei dati RAW e stats... + string startDateStr = data2transfer.ToString("yyyyMMdd"); + string endDateStr = data2transfer.AddDays(numDays).ToString("yyyyMMdd"); + int.TryParse(startDateStr, out startYMD); + int.TryParse(endDateStr, out endYMD); + // filtri e delete + var filtRawOld = builderRaw.Gte(u => u.dateYMD, startYMD) & builderRaw.Lte(u => u.dateYMD, endYMD); + collRawData.DeleteMany(filtRawOld); + var filtHistOld = builderHist.Gte(u => u.dateYMD, startYMD) & builderHist.Lte(u => u.dateYMD, endYMD); + collHistData.DeleteMany(filtHistOld); + + // faccio ciclo su OGNI macchina + sw.Start(); + var elencoMacchine = DataLayerObj.taMacchine.GetData(); + foreach (var macchina in elencoMacchine) + { + sb.AppendLine($"Inizio processing macchina {macchina.IdxMacchina}"); + // faccio ciclo su gg richiesti... + for (int i = 0; i < numDays; i++) + { + tStamp = data2transfer.AddDays(i); + currDateStr = tStamp.ToString("yyyyMMdd"); + int.TryParse(currDateStr, out currYMD); + // leggo da DB i records... + DS_applicazione.FluxLogDataTable tabDati = DataLayerObj.taFL.getFiltOrd(macchina.IdxMacchina, tStamp, tStamp.AddDays(1), true); + // solo se ho dati... + if (tabDati.Count > 0) + { + // chiamo procedura x conversione + List risultato = convertTable(tabDati, tStamp, timeWindow.day); + // salvo in blocco + if (risultato.Count > 0) + { + try + { + collRawData.InsertMany(risultato); + // calcolo la NUOVA statistica giornaliera... + var resStats = getStats(risultato); + // salvo! + collHistData.InsertOne(resStats); + } + catch (Exception exc) + { + logger.lg.scriviLog($"trasferDataFromDb eccezione{Environment.NewLine}{exc}", tipoLog.EXCEPTION); + } + } + sb.AppendLine($"DB {tStamp}: {tabDati.Count}rec | MongoDb {risultato.Count} RAW DOC in {sw.ElapsedMilliseconds / 1000} sec"); + } + } + } + // restituisco messaggio... + answ.esito = esitoExec.ok; + answ.message = sb.ToString(); + return answ; + } + + #endregion Public Methods } - } -} +} \ No newline at end of file diff --git a/MapoDb/MapoDb.csproj b/MapoDb/MapoDb.csproj index 7569fd02..004f78ab 100644 --- a/MapoDb/MapoDb.csproj +++ b/MapoDb/MapoDb.csproj @@ -275,6 +275,7 @@ + diff --git a/MapoSDK/GlobalSuppressions.cs b/MapoSDK/GlobalSuppressions.cs index 6289bdd0..9aabb934 100644 --- a/MapoSDK/GlobalSuppressions.cs +++ b/MapoSDK/GlobalSuppressions.cs @@ -5,4 +5,4 @@ using System.Diagnostics.CodeAnalysis; -[assembly: SuppressMessage("Naming", "CA1707:Gli identificatori non devono contenere caratteri di sottolineatura", Justification = "", Scope = "type", Target = "~T:MapoSDK.VC_func")] +[assembly: SuppressMessage("Naming", "CA1707:Gli identificatori non devono contenere caratteri di sottolineatura", Justification = "", Scope = "type", Target = "~T:MapoSDK.VC_func")] \ No newline at end of file diff --git a/MapoSDK/Objects.cs b/MapoSDK/Objects.cs index d6385e15..3ceef8b4 100644 --- a/MapoSDK/Objects.cs +++ b/MapoSDK/Objects.cs @@ -16,6 +16,38 @@ namespace MapoSDK public int next_IdxMicroStato; #endregion Public Fields + + #region Public Methods + + public static bool operator !=(hwMachineState left, hwMachineState right) + { + return !(left == right); + } + + public static bool operator ==(hwMachineState left, hwMachineState right) + { + return left.Equals(right); + } + + public override bool Equals(object obj) + { + if (!(obj is hwMachineState item)) + return false; + + if (IdxTipoEvento != item.IdxTipoEvento) + return false; + if (next_IdxMicroStato != item.next_IdxMicroStato) + return false; + + return true; + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + + #endregion Public Methods } /// @@ -66,6 +98,50 @@ namespace MapoSDK public string[] wBrowsBoxUrls; #endregion Public Fields + + #region Public Methods + + public static bool operator !=(inputComandoMapo left, inputComandoMapo right) + { + return !(left == right); + } + + public static bool operator ==(inputComandoMapo left, inputComandoMapo right) + { + return left.Equals(right); + } + + public override bool Equals(object obj) + { + if (!(obj is inputComandoMapo item)) + return false; + + if (descrComando != item.descrComando) + return false; + if (idxTipoEvento != item.idxTipoEvento) + return false; + if (isValid != item.isValid) + return false; + if (needStatusRefresh != item.needStatusRefresh) + return false; + if (outValue != item.outValue) + return false; + if (precInput != item.precInput) + return false; + if (text2show != item.text2show) + return false; + if (wBrowsBoxUrls != item.wBrowsBoxUrls) + return false; + + return true; + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + + #endregion Public Methods } /// @@ -621,22 +697,6 @@ namespace MapoSDK public bool writable { get; set; } = false; #endregion Public Properties - -#if false - /// - /// Indica se il parametro sia stato salvato (value = newValue) oppure newValue NON impostato - /// - public bool saved - { - get - { - bool hasData = !string.IsNullOrWhiteSpace(value); - bool areEqual = value == newValue; - bool noWriteReq = string.IsNullOrWhiteSpace(newValue); - return (areEqual || (hasData && noWriteReq)); - } - } -#endif } /// @@ -780,18 +840,18 @@ namespace MapoSDK switch (vcType) { case plcDataType.Boolean: - bool.TryParse(strValue, out currBool); + _ = bool.TryParse(strValue, out currBool); answ = currBool; break; case plcDataType.Int: case plcDataType.DInt: - int.TryParse(strValue, out currInt); + _ = int.TryParse(strValue, out currInt); answ = currInt; break; case plcDataType.Real: - double.TryParse(strValue, out currDouble); + _ = double.TryParse(strValue, out currDouble); answ = currDouble; break; @@ -922,73 +982,4 @@ namespace MapoSDK #endregion Public Properties } - -#if false - /// - /// Calendario eventi - /// - public class EventsCalendar - { - /// - /// Lista di eventi - /// - public List EventsList { get; set; } - } -#endif -#if false -/// -/// Classe definizione parametri singolo ordine produzione -/// -public class OrdineProdArt -{ - /// - /// Codice univoco ordine - /// - public string OrdNum; - /// - /// Articolo associato ad ordine - /// - public Articolo ArtOrd; - /// - /// Quantità Articolo - /// - public int Qta; -} -/// -/// Oggetto generico articolo -/// -public class Articolo -{ - /// - /// Codice articolo - /// - public string Codice; - /// - /// Descrizione Articolo - /// - public string Descrizione; -} -/// -/// Classe definizione parametri ordine x KIT di articoli -/// -public class OrdineProdKit -{ - /// - /// Codice univoco ordine - /// - public string OrdNum; - /// - /// Codice KIT - /// - public string Codice; - /// - /// Vettore ordini articolo associati a KIT - /// - public List OrdiniArt; - /// - /// Quantità KIT - /// - public int Qta; -} -#endif } \ No newline at end of file diff --git a/MapoSDK/WebClientWT.cs b/MapoSDK/WebClientWT.cs index b09dd59c..866f6d38 100644 --- a/MapoSDK/WebClientWT.cs +++ b/MapoSDK/WebClientWT.cs @@ -2,28 +2,37 @@ using System.Net; namespace MapoSDK -{ - /// - /// Override metodo WebClient con gestione TimeOut corto - /// - public class WebClientWT : WebClient - { +{ /// - /// timeout da conf + /// Override metodo WebClient con gestione TimeOut corto /// - protected int urlCallTOut + public class WebClientWT : WebClient { - get - { - // 10 sec timeout - return 10000; - } + #region Protected Properties + + /// + /// timeout da conf + /// + protected static int urlCallTOut + { + get + { + // 10 sec timeout + return 10000; + } + } + + #endregion Protected Properties + + #region Protected Methods + + protected override WebRequest GetWebRequest(Uri address) + { + WebRequest wr = base.GetWebRequest(address); + wr.Timeout = urlCallTOut; // timeout in milliseconds (ms) + return wr; + } + + #endregion Protected Methods } - protected override WebRequest GetWebRequest(Uri address) - { - WebRequest wr = base.GetWebRequest(address); - wr.Timeout = urlCallTOut; // timeout in milliseconds (ms) - return wr; - } - } -} +} \ No newline at end of file