using GWMS.Data; using GWMS.Data.DatabaseModels; using GWMS.UI.Data; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using NLog; using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Reflection; using System.Threading.Tasks; using static GWMS.Data.IobObjects; // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 namespace GWMS.UI.Controllers { /// /// COntroller principale x dichiaraizone da IOB-WIN x GWMS /// /// per la conf dei verb http: /// https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-5.0 /// https://stormpath.com/blog/routing-in-asp-net-core /// /// [Route("api/[controller]")] [ApiController] public class IOBController : ControllerBase { #region Private Fields /// /// Classe per logging /// private static NLog.Logger Log = LogManager.GetCurrentClassLogger(); #endregion Private Fields #region Public Constructors public IOBController(GWMSDataService DataService) { _DataService = DataService; Log.Debug("Avvio classe IOBController"); } #endregion Public Constructors #region Protected Properties protected GWMSDataService _DataService { get; set; } #endregion Protected Properties #region Public Methods /// /// SALVA x macchina KVP parametro/valore: /// /// GET: IOB/addOptPar/SIMUL_03?pName=PZREQ&pValue=1000 /// /// /// /// /// [HttpGet("addOptPar/{id}")] public string addOptPar(string id, string pName, string pValue) { //Log.Debug($"Chiamata addOptPar | {id} | {pName} | {pValue}"); return $"N.A. | {id} | {pName} | {pValue}"; } /// /// AGGIUNGE TASK richiesto x macchina: /// /// GET: IOB/addTask2Exe/3010?taskName=startSetup&taskVal=T190406101512 /// GET: IOB/addTask2Exe/3010?taskName=stopSetup&taskVal=T190406101512 /// GET: IOB/addTask2Exe/SIMUL_03?taskName=setProg&taskVal=P00000001 /// GET: IOB/addTask2Exe/SIMUL_03?taskName=setComm&taskVal=ODL_0000123 /// GET: IOB/addTask2Exe/SIMUL_03?taskName=setArt&taskVal=ART_0000321 /// /// /// /// /// [HttpGet("addTask2Exe/{id}")] public async Task addTask2Exe(string id, string taskName, string taskVal) { Log.Info($"addTask2Exe | {id} | {taskName} | {taskVal}"); string answ = ""; // converto stringa in tipo task... taskType tName = taskType.nihil; try { bool fatto = Enum.TryParse(taskName, out tName); if (fatto) { await _DataService.addTask4Machine(id, tName, taskVal); } else { Log.Info($"addTask2Exe: impossibile riconoscere il comando {taskName} come uno dei tipi ammessi, NON aggiunto"); } } catch (Exception exc) { Log.Error($"addTask2Exe: Eccezione durante processing | idxMacchina {id} | taskName {taskName} | taskVal {taskVal}{Environment.NewLine}{exc}"); } answ = await getTask2Exe(id); return answ; } /// /// Controllo status Alive /// /// GET: IOB/version /// /// [HttpGet("alive")] public string alive() { //Log.Debug("Chiamata alive"); return $"OK"; } [HttpGet("version")] public string version() { var version = Assembly .GetExecutingAssembly() .GetName() .Version? .ToString() ?? "unknown"; return version; } /// /// Esegue verifica livelli ed eventuale creazione ordini refill /// /// GET: IOB/checkLevels/SIMUL_03 /// /// /// [HttpGet("checkLevels/{id}")] public async Task checkLevels(string id) { Log.Info($"checkLevels | {id}"); //Log.Debug($"Chiamata checkLevels | {id}"); bool fatto = false; // ...verifica per ricalcolo ordini... fatto = await _DataService.checkLevels(); if (fatto) { return "OK"; } else { return "NO"; } } // DELETE api/IOB/5 [HttpDelete("{id}")] public void Delete(int id) { //Log.Debug($"Chiamata Delete | {id}"); } /// /// Verifica abilitazione PLANT /// /// GET: IOB/enabled/SIMUL_03 /// /// /// [HttpGet("enabled/{id}")] public async Task enabled(string id) { Log.Debug($"Enabled | {id}"); string answ = "ND"; // se id nullo --> KO! if (id == null) { answ = "KO"; } else { var currPlant = await _DataService.PlantsGetByCodeAsync(id); answ = (currPlant != null && currPlant.PlantId > 0) ? "OK" : "NO"; } return answ; } /// /// Processa una chiamata POST per l'invio di un array Json di oggetti input (EVENTI) /// PUT: api/IOB/evListJson/SIMUL_03 /// /// ID dell'IOB /// [HttpPost("evListJson/{id}")] public string evListJson(string id, [FromBody] evJsonPayload rawData) { //Log.Debug($"Chiamata evListJson | {id}"); string answ = "KO"; #if false int insDone = 0; // se ho qualcosa da processare... if (fluxData != null) { // per ogni valore --> processo! try { foreach (var item in receivedData.eventList) { if (memLayer.ML.CRI("_logLevel") > 6) { Log.Info($"Valori letti: idxMacchina: {id} | valore: {item.valore}", tipoLog.Debug); } // formato datetime come yyyyMMddHHmmssfff -->es: 20181223180600000 answ = DataLayerObj.processInput(id, item.valore, item.dtEve.ToString("yyyyMMddHHmmssfff"), item.dtCurr.ToString("yyyyMMddHHmmssfff"), item.cnt.ToString()); insDone++; } // se vuoto --> OK! if (string.IsNullOrEmpty(answ)) { answ = $"OK {insDone} processed"; } } catch (Exception exc) { Log.Info($"Errore in fase invio valori inputJson{Environment.NewLine}{exc}"); answ = "NO"; } } #endif return answ; } /// /// Scrittura diretta di 1 singolo evento fluxLog /// /// GET: IOB/flog/SIMUL_03?flux=PROG&valore=P0001&dtEve=20161223180600000&dtCurr=20161223180600000&cnt=999 /// /// /// /// /// /// /// /// [HttpGet("flog/{id}")] public async Task flog(string id, string flux, string valore, string dtEve, string dtCurr, string cnt) { Log.Debug($"flog | {id} | {flux} | {valore} | {dtEve} | {dtCurr} | {cnt}"); bool fatto = false; // formato yyyymmddHHMMSSnnn ovvero da anno a millisecondi if (cnt == null) { cnt = "0"; } try { // 2017.09.14 trimmo eventualmente lo zero finale dalle date SE supera i millisecondi... dtEve = dtEve.Length > 17 ? dtEve.Substring(0, 17) : dtEve; dtCurr = dtCurr.Length > 17 ? dtCurr.Substring(0, 17) : dtCurr; DateTime dataOraEvento = DateTime.Now; DateTime dtEvento, dtCorrente; // controllo: se ho valori DtEvent x evento e orario DIVERSI per acquisitore IOB calcolo dataOraEvento corretto if (dtEve != dtCurr) { Int64 delta = 0; try { // se ho meno decimali x evento rispetto dtCorrente... if (dtEve.Length < dtCurr.Length) { dtEve = dtEve.PadRight(dtCurr.Length, '0'); } delta = Convert.ToInt64(dtCurr) - Convert.ToInt64(dtEve); // se meno di 60'000 ms ... if (delta < 59999) { dataOraEvento = dataOraEvento.AddMilliseconds(-delta); } else { // in questo caso elimino i MS dalle stringhe e converto i datetime.... CultureInfo provider = CultureInfo.InvariantCulture; string format = "yyyyMMddHHmmssfff"; dtEvento = DateTime.ParseExact(dtEve, format, provider); dtCorrente = DateTime.ParseExact(dtCurr, format, provider); Int64 tiks = dtCorrente.Ticks - dtEvento.Ticks; dataOraEvento = dataOraEvento.AddTicks(-tiks); } } catch (Exception exc) { Log.Error($"FLOG: Eccezione 01 | idxMacchina {id} | flux {flux} | valore {valore} | dtEve {dtEve} | dtCurr {dtCurr} | cnt {cnt}{Environment.NewLine}{exc}"); } } // recupero plant! var currPlant = await _DataService.PlantsGetByCodeAsync(id); if (currPlant != null && currPlant.PlantId > 0) { // converto in plantLogModel... PlantLogModel newItem = new PlantLogModel() { PlantId = currPlant.PlantId, FluxType = flux, ValNumber = _DataService.convStr2Double(valore), ValString = valore, DtEvent = dataOraEvento }; List newData = new List(); newData.Add(newItem); // insert! fatto = await _DataService.PlantLogInsertAsync(newData); // effettuo SEMPRE verifica per ricalcolo ordini... await _DataService.checkLevels(); } } catch (Exception exc) { fatto = false; Log.Error($"FLOG: Eccezione 02 | idxMacchina {id} | flux {flux} | valore {valore} | dtEve {dtEve} | dtCurr {dtCurr} | cnt {cnt}{Environment.NewLine}{exc}"); } if (fatto) { return "OK"; } else { return "NO"; } } /// /// Processa una chiamata POST per l'invio di un array Json di oggetti fluxLog /// PUT: api/IOB/flogJson/SIMUL_03 /// /// ID dell'IOB /// [HttpPost("flogJson/{id}")] public async Task flogJson(string id, [FromBody] flogJsonPayload rawData) { Log.Debug($"flogJson | {id} | {rawData.fluxData.Count} logs"); bool fatto = false; // verifico ci sia valore if (rawData != null && !string.IsNullOrEmpty(id)) { // recupero plant! var currPlant = await _DataService.PlantsGetByCodeAsync(id); if (currPlant != null && currPlant.PlantId > 0) { // conversione dati List plData = rawData.fluxData.Select(jpl => _DataService.convertFluxToPL(currPlant.PlantId, jpl)).ToList(); Log.Debug($"flogJson | {id} | Convertiti {plData.Count} record"); // insert! fatto = await _DataService.PlantLogInsertAsync(plData); Log.Debug($"flogJson | {id} | PlantLogInsertAsync --> esito: {fatto}"); // effettuo SEMPRE verifica per ricalcolo ordini... await _DataService.checkLevels(); Log.Debug($"flogJson | {id} | chiamata checkLevels"); // leggo parametri correnti... try { List currParams = await _DataService.getCurrObjItems(id); // ora per ogni valore RICEVUTO costruisco un oggetto in innovazioni da inviare...x salvare in stato parametri... List innovazioni = new List(); foreach (var item in rawData.fluxData) { // flux = uuid del parametro objItem trovato = currParams.Find(obj => obj.uid == item.flux.Trim()); // se lo trovo aggiorno... if (trovato != null) { // aggiorno valore e data trovato.value = item.valore; trovato.lastRead = DateTime.Now; // se fosse un valore WRITE e mi ha dato un valore vuoto --> mando un fix x riscrittura if (trovato.writable && string.IsNullOrEmpty(item.valore)) { taskType currTask = (taskType)Enum.Parse(typeof(taskType), trovato.uid); await _DataService.AddCheckTask4MachineAsync(id, currTask, item.valore); } } // altrimenti AGGIUNGO (READ ONLY)... else { trovato = new objItem { uid = item.flux, name = item.flux, value = item.valore, lastRead = DateTime.Now, writable = false }; } // lo carico in innovation innovazioni.Add(trovato); fatto = true; } // faccio upsert innovations! await _DataService.UpsertCurrObjItemsAsync(id, innovazioni); // ultimo step: controllo invio quotidiano parametri gestiti (compreso validità parametri setup) await _DataService.ParamsSendCheckAsync(); } catch (Exception exc) { Log.Info($"Errore in fase salvataggio innovazioni parametri correnti da flogJson{Environment.NewLine}{exc}"); fatto = false; } } } if (fatto) { return "OK"; } else { return "NO"; } } /// /// Chiude ODL precedente ed avvia uno nuovo (duplicandolo e sitemando quantità RIMANENTE), e CONFERMA produzione... /// /// GET: IOB/forceSplitOdl/SIMUL_03 /// /// /// /// Esito chiamata (OK/vuoto) [HttpPost("forceSplitOdl/{id}")] public string forceSplitOdl(string id) { Log.Debug($"Chiamata forceSplitOdl | {id}"); return "OK"; } /// /// Chiude ODL precedente ed avvia uno nuovo (duplicandolo e sitemando quantità RIMANENTE), e CONFERMA produzione... /// /// GET: IOB/forceSplitOdl/SIMUL_03?doConfirm=true&qtyFromLast=true&roundStep=150&extOrderCode=ABCDE1234 /// /// /// id impianto /// /// /// /// Cod esterno da legare all'ODL x tracciare lotti prod /// Esito chiamata (OK/vuoto) [HttpPost("forceSplitOdlFull/{id}")] public string forceSplitOdlFull(string id, bool doConfirm, bool qtyFromLast, int? roundStep, string keyRichiesta = "") { Log.Debug($"Chiamata forceSplitOdlFull | {id}"); return "OK"; } /// /// Classe di base usata come check alive /// /// GET: api/IOB /// /// [HttpGet] public string Get() { Log.Debug("Chiamata Get"); return "OK"; } /// /// Classe di base usata come check alive /// /// GET api/IOB/PIZ08 /// /// /// [HttpGet("{id}")] public string Get(int id) { Log.Debug($"Chiamata Get | {id}"); return "OK"; } /// /// Recupera COUNTER x macchina: /// /// GET: IOB/getCounter/5 /// /// /// /// [HttpGet("getCounter/{id}")] public string getCounter(string id) { Log.Debug($"Chiamata getCounter | {id}"); return "0"; } /// /// Recupera COUNTER x macchina dal CONTEGGIO dei TCRecorded: /// /// GET: IOB/getCounterTCRec/5 /// /// /// /// [HttpGet("getCounterTCRec/{id}")] public string getCounterTCRec(string id) { Log.Debug($"Chiamata getCounterTCRec | {id}"); return "0"; } /// /// Recupera DATI correnti x macchina: /// /// GET: IOB/getCurrData/SIMUL_03 /// /// /// /// Json contenente la riga di stato macchina [HttpGet("getCurrData/{id}")] public string getCurrData(string id) { Log.Debug($"Chiamata getCurrData | {id}"); return $"{id}"; } /// /// Recupera ODL corrente x macchina: /// /// GET: IOB/getCurrODL/SIMUL_03 /// /// /// /// [HttpGet("getCurrODL/{id}")] public string getCurrODL(string id) { Log.Debug($"Chiamata getCurrODL | {id}"); return "1"; } /// /// Restituisce intera riga dell'odl correntemente in lavorazione sulla macchina... /// GET: IOB/getCurrOdlRow/SIMUL_01 /// /// /// [HttpGet("getCurrOdlRow/{id}")] public string getCurrOdlRow(string id) { Log.Debug($"Chiamata getCurrOdlRow | {id}"); return ""; } /// /// Restituisce data-ora inizio dell'odl correntemente in lavorazione sulla macchina... /// es: http://url_site/MP/IO/IOB/getCurrOdlStart/SIMUL_03 /// /// /// [HttpGet("getCurrOdlStart/{id}")] public string getCurrOdlStart(string id) { Log.Debug($"Chiamata getCurrOdlStart | {id}"); return $"{DateTime.Now}"; } /// /// Restituisce intera riga dello stato di macchina... /// GET: IOB/getCurrStatoRow/SIMUL_01 /// /// /// [HttpGet("getCurrStatoRow/{id}")] public string getCurrStatoRow(string id) { Log.Debug($"Chiamata getCurrStatoRow | {id}"); return ""; } /// /// Restituisce un array JSon di files di una IOB /// PUT: api/IOB/getFiles/SIMUL_03 /// /// ID dell'IOB /// Oggetto Json in formato MapoSDK.fileEmbed [HttpGet("getFiles/{id}")] public string getFiles(string id) { Log.Debug($"Chiamata getFiles | {id}"); return ""; } /// /// Restituisce il valore dello stato di IDLE della macchina, quindi SOLO SE NON é in lavoro e già convertito in minuti... /// GET: IOB/getIdlePeriod/SIMUL_01 /// /// /// [HttpGet("getIdlePeriod/{id}")] public int getIdlePeriod(string id) { Log.Debug($"Chiamata getIdlePeriod | {id}"); return 0; } /// /// Restituisce il (primo) codice IOB da dover gestire (se un IOBMAN chiede di gestirne uno in +...) /// /// IP del Gateway /// [HttpGet("getIob2call/{id}")] public string getIob2call(string id) { Log.Debug($"Chiamata getIob2call | {id}"); return ""; } /// /// Restituisce dati di associazione tra macchina, device IOB chiamante e sue info /// /// Id della macchina /// [HttpGet("getM2IOB/{id}")] public string getM2IOB(string id) { Log.Debug($"Chiamata getM2IOB | {id}"); return ""; } /// /// restituisce elenco parametri correnti come una List Json di oggetti objItem /// GET: IOB/getObjItems/SIMUL_03 /// /// ID dell'IOB /// [HttpGet("getObjItems/{id}")] public async Task getObjItems(string id) { Log.Info($"getObjItems | {id}"); string answ = ""; if (string.IsNullOrWhiteSpace(id)) { answ = "Missing IOB"; } else { // procedo a recuperare l'oggetto... List currParams = new List(); try { // deserializzo currParams = await _DataService.getCurrObjItems(id); // se != null --> salvo! if (currParams != null) { answ = JsonConvert.SerializeObject(currParams); } } catch (Exception exc) { Log.Info($"Errore in getObjItems{Environment.NewLine}{exc}"); answ = "NO"; } } return answ; } /// /// restituisce elenco parametri CHE RICHIEDONO scrittura su PLC come una List Json di oggetti objItem /// GET: IOB/getObjItems2Write/SIMUL_03 /// /// ID dell'IOB /// [HttpGet("getObjItems2Write/{id}")] public async Task getObjItems2Write(string id) { Log.Info($"getObjItems2Write | {id}"); string answ = ""; if (string.IsNullOrWhiteSpace(id)) { answ = "Missing IOB"; } else { // procedo a recuperare l'oggetto... List currParams = new List(); try { // deserializzo currParams = await _DataService.getCurrObjItemsPendigWrite(id); // se != null --> salvo! if (currParams != null) { answ = JsonConvert.SerializeObject(currParams); } } catch (Exception exc) { Log.Info($"Errore in getCurrParams{Environment.NewLine}{exc}"); answ = "NO"; } } return answ; } /// /// Recupera TASK richiesto x macchina: /// /// GET: IOB/getTask2Exe/SIMUL_03 /// /// /// /// Json contenente 1..n task da eseguire [HttpGet("getTask2Exe/{id}")] public async Task getTask2Exe(string id) { Log.Info($"getTask2Exe | {id}"); string answ = ""; try { // leggo da REDIS eventuale elenco task x macchina... Dictionary valori = await _DataService.mTaskMacchina(id); answ = JsonConvert.SerializeObject(valori); } catch { } return answ; } /// /// Input singolo valore /// /// /// /// /// /// /// // GET: IOB/input/SIMUL_03?valore=3&dtEve=20181206180600000&dtCurr=20181206180600000&cnt=999 [HttpGet("input/{id}")] public string input(string id, string valore, string dtEve, string dtCurr, string cnt) { Log.Debug($"Chiamata input | {id} | {valore} | {dtEve} | {dtCurr} | {cnt}"); string answ = "OK"; #if false // formato yyyymmddHHMMSSnnn ovvero da anno a millisecondi if (cnt == null) { cnt = "0"; } DateTime dataOraEvento = DateTime.Now; if (memLayer.ML.CRI("_logLevel") > 6) { Log.Info($"Valori letti: idxMacchina: {id} | valore: {valore}", tipoLog.Debug); } try { DataLayer DataLayerObj = new DataLayer(); answ = DataLayerObj.processInput(id, valore, dtEve, dtCurr, cnt); } catch (Exception exc) { Log.Info(string.Format("Errore in processInput{0}{1}", Environment.NewLine, exc)); answ = "NO"; } #endif return answ; } // POST api/IOB [HttpPost] public void Post([FromBody] string value) { Log.Debug("Chiamata Post"); } // PUT api/IOB/5 [HttpPut("{id}")] public void Put(int id, [FromBody] string value) { Log.Debug($"Chiamata Put | {id}"); } /// /// ELIMINA TASK richiesto x macchina: /// /// GET: IOB/remTask2Exe/SIMUL_03?taskName=T180326160502 /// /// /// /// [HttpGet("remTask2Exe/{id}")] public async Task remTask2Exe(string id, string taskName) { Log.Info($"remTask2Exe | {id} | {taskName}"); string answ = ""; try { // converto stringa in tipo task... taskType tName = taskType.nihil; bool fatto = Enum.TryParse(taskName, out tName); if (fatto) { await _DataService.RemTask4MachineAsync(id, tName); } else { Log.Info($"remTask2Exe: impossibile riconoscere il comando {taskName} come uno deitipi ammessi, NON aggiunto"); } answ = await getTask2Exe(id); } catch (Exception exc) { Log.Error($"remTask2Exe: Eccezione durante processing | idxMacchina {id} | taskName {taskName}{Environment.NewLine}{exc}"); } return answ; } /// /// Processa una chiamata POST per l'invio di un array Json di oggetti plcMemConf /// PUT: api/IOB/saveConf/SIMUL_03 /// /// NB: implementato in 2 step x non usare solo System.Text.Json che nON gestisce gli ENUM /// /// /// ID dell'IOB /// [HttpPost("saveConf/{id}")] public async Task saveConf(string id, [FromBody] System.Text.Json.JsonElement rawQuery) { Log.Info($"saveConf | {id}"); // problema deserializzaizone ENUM con classe nuova dotnet 5: // https://github.com/graphql-dotnet/graphql-dotnet/issues/1439 string answ = ""; // recupero come stringa il json ricevuto string rawData = rawQuery.ToString(); if (!string.IsNullOrEmpty(rawData)) { if (string.IsNullOrWhiteSpace(id)) { answ = "Missing IOB"; } else { bool done = await _DataService.SaveMemMapAsync(id, rawData); answ = done ? "OK" : "ERROR"; } } return answ; } /// /// Registrazione variazione allarmi /// /// GET: IOB/sendAlarmBankUpdate/SIMUL_03 /// /// /// [HttpPost("sendAlarmBankUpdate/{id}")] public async Task sendAlarmBankUpdate(string id, string memAddr, int index, uint currStatus, [FromBody] List ActiveAlarms) { Log.Info($"sendAlarmBankUpdate | {id}"); string answ = "ND"; // se id nullo --> KO! if (id == null) { answ = "KO"; } else { // recupero plant... var currPlant = await _DataService.PlantsGetByCodeAsync(id); string alarmDecoded = "-"; if (ActiveAlarms != null && ActiveAlarms.Count > 0) { alarmDecoded = String.Join(" | ", ActiveAlarms); } AlarmLogModel newAlarm = new AlarmLogModel() { PlantId = currPlant.PlantId, DtEvent = DateTime.Now, MemAddress = memAddr, Index = index, Status = currStatus, ValDecoded = alarmDecoded }; var done = await _DataService.AlarmLogInsert(newAlarm); answ = done ? "OK" : "NO"; } return answ; } /// /// Salva IP e macchina /// /// IP del Gateway /// [HttpGet("sendReboot")] public async Task sendReboot(string idxMacchina, string mac) { Log.Warn($"sendReboot | {idxMacchina} | {mac}"); string answ = ""; try { // registrazione startup IOB-WIN e macchina RebootLogModel newItem = new RebootLogModel() { DtEvent = DateTime.Now, Item = idxMacchina, Payload = mac }; await _DataService.RebootLogInsertAsync(newItem); answ = "OK"; } catch { } return answ; } /// /// Processa una chiamata POST per l'invio di una List Json di oggetti objItem /// POST: api/IOB/setObjItems/SIMUL_03 /// /// ID dell'IOB /// [HttpPost("setObjItems/{id}")] public async Task setObjItems(string id, [FromBody] List currParams) { Log.Info($"setObjItems | {id}"); string answ = ""; if (string.IsNullOrWhiteSpace(id)) { answ = "Missing IOB"; } else { // se != null --> salvo! if (currParams != null) { await _DataService.SetCurrObjItemsAsync(id, currParams); answ = "OK"; } } return answ; } /// /// Processa una chiamata POST per l'invio di un SET di file "a nome" di un IOB, formato MapoSDK.fileEmbed /// POST: api/IOB/uploadFile/SIMUL_03 /// /// ID dell'IOB /// [HttpPost("uploadFile/{id}")] public string uploadFile(string id) { Log.Debug($"Chiamata uploadFile | {id}"); string answ = ""; #if false // questa classe è derivata da Controller.Response... x cui recupero lo stream in altro modo... string content = ""; System.Web.HttpContext.Current.Request.InputStream.Position = 0; using (var reader = new StreamReader(Request.InputStream, System.Text.Encoding.UTF8, true, 4096, true)) { content = reader.ReadToEnd(); } //Rest System.Web.HttpContext.Current.Request.InputStream.Position = 0; // procedo a deserializzare in blocco l'oggetto... try { // deserializzo. fileEmbed receivedData = JsonConvert.DeserializeObject(content); // salvo nella cartella di Upload... string basePath = Server.MapPath(memLayer.ML.CRS("uploadFileDir")); string dirPath = $"{basePath}\\{id}"; // fix directory... Directory.CreateDirectory(dirPath); foreach (var item in receivedData.fileList) { // scrivo! System.IO.File.WriteAllText($"{dirPath}\\{item.fileName}", item.content); } answ = "OK"; } catch (Exception exc) { Log.Info($"Errore in uploadFile{Environment.NewLine}{exc}"); answ = "NO"; } #endif return answ; } /// /// Processa una chiamata POST per l'invio di una List Json di UNO O PIU' oggetti objItem /// POST: api/IOB/upsertObjItems/SIMUL_03 /// /// ID dell'IOB /// [HttpPost("upsertObjItems/{id}")] public async Task upsertObjItems(string id, [FromBody] List innovazioni) { Log.Info($"upsertObjItems | {id}"); string answ = ""; if (string.IsNullOrWhiteSpace(id)) { answ = "Missing IOB"; } else { // se != null --> salvo! if (innovazioni != null) { // salvo await _DataService.UpsertCurrObjItemsAsync(id, innovazioni); answ = "OK"; } } return answ; } #endregion Public Methods } }