mickle026 650 Posted September 28, 2024 Posted September 28, 2024 (edited) @VicMoore I managed to get updates to work with a callback and a webroute , I am pretty sure I have already done this before somewhere, but this time it is working even if I navigate away and come back. (maybe an issue in chrome, but works in firefox) JS define(["require", 'mainTabsManager', "jQuery", "globalize", "emby-checkbox", "emby-select", "emby-linkbutton", "emby-input", "emby-button"], function (require, mainTabsManager, $, globalize) { var pluginUniqueId = "70F5C116-0D23-45E3-9FCA-A9EC6BF50ED9"; return function (page, params) { var IsReportUnlinkedPeopleRunning = false; var reportmessage = "Running Report....<br />This May Take a Long Time!! - On huge databases it can take Many Hours,<br />Please Wait until 'Completed' is shown."; page.addEventListener('pageshow', () => { ApiClient.getJSON(ApiClient.getUrl('/MechBox/UnLinkedActorsStatus')).then(response => { var dat = response; //if (dat.Running == true) { } console.log("[Mechbox Clean People Report] Status Query: Running= " + dat.Running); if (dat.Running == true) { IsReportUnlinkedPeopleRunning = true; var intervalID = window.setInterval(myCallback, 100); reply = reportmessage; document.getElementById("ReportUnLinkedActorsStatus").innerHTML = reply; document.getElementById("UnLinkedActorsStatusProgress").innerHTML = dat.Text; } else if (dat.Running == false) { document.getElementById("UnLinkedActorsStatusProgress").innerHTML = "Idle."; function myStopFunction() { clearInterval(myCallback) } } else { document.getElementById("UnLinkedActorsStatusProgress").innerHTML = "Error State."; function myStopFunction() { clearInterval(myCallback) }} }).catch(e => { console.log(e); }); page.querySelector('#ReportUnLinkedActors').addEventListener('click', () => { if (IsReportUnlinkedPeopleRunning == true) { return false; } // if running igonore button click if (confirm('Report UnLinked Actors!\n\nAre you sure you want to continue?')) { reply = reportmessage; document.getElementById("ReportUnLinkedActorsStatus").innerHTML = reply; ReportUnlinkedPeople(); } else { document.getElementById("ReportUnLinkedActorsStatus").innerHTML = "Cancelled"; } }); } ); function ReportUnlinkedPeople() { console.log("ReportUnLinkedActors Has Triggered"); var intervalID = window.setInterval(myCallback, 100); ApiClient.getJSON(ApiClient.getUrl('/MechBox/ReportUnLinkedActors')).then(response => { var dat = response; document.getElementById("ReportUnLinkedActorsStatus").innerHTML = dat.Text; }).catch(e => { console.log(e); }); function myStopFunction() { clearInterval(myCallback) }; }; function myCallback() { ApiClient.getJSON(ApiClient.getUrl('/MechBox/UnLinkedActorsStatus')).then(response => { var dat = response; document.getElementById("UnLinkedActorsStatusProgress").innerHTML = dat.Text; console.log("Status Query: " + dat.Text); if (dat.Running == false) { function myStopFunction() { clearInterval(myCallback) }; } }).catch(e => { console.log(e); }); } } } ); C# Where I can change the "status" variable anywhere in the code and thats the JSon that is returned. I added the Running bool, to global so that if the function is triggered I set it to true, then false when it ends, and I can detect that when I revisit my page, internal static string status; public static bool Running; [Route("/MechBox/ReportUnLinkedActors", "GET", Summary = "Report UnLinked Actors (ie, Not linked to a media item)")] public class getUnlinkedPeople : IReturn<object> { public bool Running { get; set; } public string status { get; set; } public string Text { get; set; } } [Route("/MechBox/UnLinkedActorsStatus", "GET", Summary = "Status Upadate Query")] public class UnLinkedActorsStatus : IReturn<object> { public bool Running { get; set; } public string status { get; set; } public string Text { get; set; } } public string Get(UnLinkedActorsStatus result) { return JsonSerializer.SerializeToString(new getUnlinkedPeople() { When I view my page I do an initial call to see what state it is in and act accordingly, video is mp4, right click and save as if it wont play, its less than 2mb. screenrecord.mp4 Edited September 28, 2024 by mickle026
VicMoore 754 Posted September 29, 2024 Author Posted September 29, 2024 @mickle026Just got power to my house restored. It was a bad storm. I will study your code and respond tomorrow (Sunday). Thanks for this code to study. Vic
VicMoore 754 Posted September 29, 2024 Author Posted September 29, 2024 (edited) @mickle026 I tried the code below to add an "endPoint" in Emby. I can now request information from the C# code from the JS code by making a GET request. How should I change the C# code below to POST a JSON object from the JavaScript code? I know how to POST from JS, but I am not fully confident about the C# code. I think I would start by changing "GET" to "POST", and changing the IReturn to IReturnVoid. Is this correct? I have learned so much from your code. Thanks so much, Vic p.s. The endpoint below does not show up in Swagger. C# code [Route("/PseudoTV/ReportScheduledEPGTasks", "GET", Summary = "Report PseudoTV Scheduled EPG Update")] public class EPG_Status : IReturn<object> { [ApiMember(Name = "status", Description = "Status", IsRequired = false, DataType = "string", ParameterType = "status", Verb = "GET")] public string Status { get; set; } } public string Get(EPG_Status result) { bool completed = true; return JsonSerializer.SerializeToString(new EPG_Status() { Status = $"Function Ended with {completed}" }); } Javascript ApiClient.getJSON(ApiClient.getUrl('/PseudoTV/ReportScheduledEPGTasks')).then(response => { console.log(">>>>>> Response from server = ", response); }).catch(e => { console.log(">>>>>> Error = ", e); }); Edited September 29, 2024 by VicMoore
mickle026 650 Posted September 29, 2024 Posted September 29, 2024 (edited) 2 hours ago, VicMoore said: @mickle026 I tried the code below to add an "endPoint" in Emby. I can now request information from the C# code from the JS code by making a GET request. How should I change the C# code below to POST a JSON object from the JavaScript code? I know how to POST from JS, but I am not fully confident about the C# code. I think I would start by changing "GET" to "POST", and changing the IReturn to IReturnVoid. Is this correct? I have learned so much from your code. Thanks so much, Vic p.s. The endpoint below does not show up in Swagger. C# code [Route("/PseudoTV/ReportScheduledEPGTasks", "GET", Summary = "Report PseudoTV Scheduled EPG Update")] public class EPG_Status : IReturn<object> { [ApiMember(Name = "status", Description = "Status", IsRequired = false, DataType = "string", ParameterType = "status", Verb = "GET")] public string Status { get; set; } } public string Get(EPG_Status result) { bool completed = true; return JsonSerializer.SerializeToString(new EPG_Status() { Status = $"Function Ended with {completed}" }); } Javascript ApiClient.getJSON(ApiClient.getUrl('/PseudoTV/ReportScheduledEPGTasks')).then(response => { console.log(">>>>>> Response from server = ", response); }).catch(e => { console.log(">>>>>> Error = ", e); }); This bit, the return is sending a JSON encoded object back to you JS, you are sending in a get request and recieving back JSON. public class EPG_Status : IReturn<object> { [ApiMember(Name = "status", Description = "Status", IsRequired = false, DataType = "string", ParameterType = "status", Verb = "GET")] public string Status { get; set; } public object EPG_DATA { get, set: } public object OtherData {get; set; } } return JsonSerializer.SerializeToString(new EPG_Status() { // all elements get json encoded // Status is simply a text element { stauts : "completed" } Status = $"Function Ended with {completed}", EPG_DATA, OtherData, // you can add more items and lists of items etc }); so you add your elements to your public class EPG_Status : IReturn<object> Im going to pm you a full plugin (source code) I wrote for someone else, in there is a cs file called RootObject.cs, in there you will see the basics for creating a full nested with higheracrchy object. THe code is for decoding the json, but you can write to these strings and lists internally the return the whole object by json encoding it. So in other words you can do the opposite of what the plugin code is doing. It is decoded via "var DecodedJson = JsonSerializer.DeserializeFromString<List<Root>>(ReceivedJsonData);" in the GetMetadata.cs file So when you "return JsonSerialiser", the following parenthesis { } enclose the objects to encode into json. if you used the example of a complicated class in the code I sent you return JsonSerializer.SerializeToString(new EPG_Status() { Root, }); You see the RootObject.cs is made up of classes, and the Root contains nested "other" classes for example in the root object is: public List<Director> Director { get; set; } and that refers to the class, so root containt Director, but Director contains type and name. public class Director { public string type { get; set; } public string name { get; set; } } the json object will encode this, you would add that as an object " public object Root { get; set; }" { "Director": { "type": "", "name","" } } There is also a bonus hack in there called LoadHTMLtoHTML.cs - gets from an Url and Loads to a div, to use it for images (this was modded for a page text) you need to base64 encode and wrap in the html tag and send back as text. You will see how usefull webroutes will be when you mind starts wandering what you could do with it I use a similar method to load html help pages from the plugin directory, so they are not embeded and I can update them without updating the plugin binary itself. To use images in this way they have to be added as base64 to the help pages, and not linked. Dont get too lost studying my code, thats quite a lot to take in - in one go! Edited September 29, 2024 by mickle026 fix dyslexic typos
mickle026 650 Posted September 29, 2024 Posted September 29, 2024 1 hour ago, VicMoore said: p.s. The endpoint below does not show up in Swagger. It will do somewhere probably under your plugins class name
VicMoore 754 Posted September 29, 2024 Author Posted September 29, 2024 @mickle026The C# code below mostly works. Both the GET and POST show up in Swagger. The Get works fine. The Post does not work. I can't figure out why. Do you have a code sample for POST ? using a route that has been set up? Vic C# code //--------------------------------------------------------------------------------------------------- // GET //--------------------------------------------------------------------------------------------------- [Route("/PseudoTV/ReportScheduledEPGTasks", "GET", Summary = "Report PseudoTV Scheduled EPG Update")] public class EPG_Status : IReturn<object> { [ApiMember(Name = "status", Description = "Status", IsRequired = false, DataType = "string", ParameterType = "status", Verb = "GET")] public string Status { get; set; } } public string Get(EPG_Status result) { bool completed = true; return JsonSerializer.SerializeToString(new EPG_Status() { Status = $"Function Ended with {completed}" }); } //--------------------------------------------------------------------------------------------------- // POST //--------------------------------------------------------------------------------------------------- [Route("/PseudoTV/ReportScheduledEPGTasks", "POST", Summary = "Update PseudoTV EPG")] public class EPG_Update : IReturnVoid { [ApiMember(Name = "update", Description = "update", IsRequired = false, DataType = "string", ParameterType = "status", Verb = "POST")] public string Update { get; set; } } public void Post(EPG_Update result) { this.Logger.Info("======PseudoTv POST Data = " + this.JsonSerializer.SerializeToString(result)); } //--------------------------------------------------------------------------------------------------- Javascript code //--------------------------------------------------------------------- // Get from the TV Platform //--------------------------------------------------------------------- ApiClient.getJSON(ApiClient.getUrl('/PseudoTV/ReportScheduledEPGTasks')).then(response => { console.log(">>>>>> Response from server = ", response); }).catch(e => { console.log(">>>>>> Error = ", e); }); //--------------------------------------------------------------------- // POST to the TV Platform //--------------------------------------------------------------------- let url = ApiClient.getUrl('/PseudoTV/ReportScheduledEPGTasks?api_key='+accessToken); console.log(">>>>>> url = ", url); var Http = new XMLHttpRequest(); Http.open('POST', ApiClient.getUrl(url)); let data = { Upload: true, }; let dataStr = JSON.stringify(data, null, 2); Http.send(dataStr); //---------------------------------------------------------------------
mickle026 650 Posted September 29, 2024 Posted September 29, 2024 (edited) 1 hour ago, VicMoore said: @mickle026The C# code below mostly works. Both the GET and POST show up in Swagger. The Get works fine. The Post does not work. I can't figure out why. Do you have a code sample for POST ? using a route that has been set up? Vic C# code //--------------------------------------------------------------------------------------------------- // GET //--------------------------------------------------------------------------------------------------- [Route("/PseudoTV/ReportScheduledEPGTasks", "GET", Summary = "Report PseudoTV Scheduled EPG Update")] public class EPG_Status : IReturn<object> { [ApiMember(Name = "status", Description = "Status", IsRequired = false, DataType = "string", ParameterType = "status", Verb = "GET")] public string Status { get; set; } } public string Get(EPG_Status result) { bool completed = true; return JsonSerializer.SerializeToString(new EPG_Status() { Status = $"Function Ended with {completed}" }); } //--------------------------------------------------------------------------------------------------- // POST //--------------------------------------------------------------------------------------------------- [Route("/PseudoTV/ReportScheduledEPGTasks", "POST", Summary = "Update PseudoTV EPG")] public class EPG_Update : IReturnVoid { [ApiMember(Name = "update", Description = "update", IsRequired = false, DataType = "string", ParameterType = "status", Verb = "POST")] public string Update { get; set; } } public void Post(EPG_Update result) { this.Logger.Info("======PseudoTv POST Data = " + this.JsonSerializer.SerializeToString(result)); } //--------------------------------------------------------------------------------------------------- Javascript code //--------------------------------------------------------------------- // Get from the TV Platform //--------------------------------------------------------------------- ApiClient.getJSON(ApiClient.getUrl('/PseudoTV/ReportScheduledEPGTasks')).then(response => { console.log(">>>>>> Response from server = ", response); }).catch(e => { console.log(">>>>>> Error = ", e); }); //--------------------------------------------------------------------- // POST to the TV Platform //--------------------------------------------------------------------- let url = ApiClient.getUrl('/PseudoTV/ReportScheduledEPGTasks?api_key='+accessToken); console.log(">>>>>> url = ", url); var Http = new XMLHttpRequest(); Http.open('POST', ApiClient.getUrl(url)); let data = { Upload: true, }; let dataStr = JSON.stringify(data, null, 2); Http.send(dataStr); //--------------------------------------------------------------------- Oh I see what you mean, like this? I have not checked any of this, just typing as I go public class ClassName: IReturnVoid, IRequiresRequestStream { [ApiMember(Name = "status", Description = "Status", IsRequired = false, DataType = "string", ParameterType = "status", Verb = "GET")] public Stream RequestStream { get; set; } // The data stream received , The keyword Stream is important and is a type like String public string Text { get; set; } } you can replace IReturnVoid To Return IReturn<object> public Task Post(ClassName request) { // the request is already JSON you should be able to this.Logger.Info("======PseudoTv POST Data = " + request.RequestStream; // you are using the request which contains all the values in you api route, and selecting the recieved data stream (the post data) var data= await _jsonSerializer.DeserializeFromStream(request.RequestStream,Type); // Type is the RootObject class you created to hold the values, depending on the json you sent, look at the code i sent you for an example. // you can also paste your json into an online json to c# convertor to create a root class, just delete the lines that start @ for it to work. // if you return an object you need to json serialise it, IReturn<object>, of course you can returnvoid which doesnt return anything. return JsonSerializer.SerializeToString(new ReportNameErrors() { Text = "whatever you are returning" }); } if your task is async "public Async Task" then you use an async deserialiser "DeserializeFromStreamAsync(input, output)" Although I have not checked any of this, you were pretty darn close! Not bad at all Edited September 29, 2024 by mickle026
VicMoore 754 Posted September 29, 2024 Author Posted September 29, 2024 @mickle026I will make changes to my code and try again. Vic
mickle026 650 Posted September 29, 2024 Posted September 29, 2024 7 minutes ago, VicMoore said: @mickle026I will make changes to my code and try again. Vic I have not actually used the POST method, this is how I understand it, and I do not have an example to give, so I really hope that it works Otherwise I will spend some time trying to figure it out aswell. It should work though, the stream is just like having JS open a text file and send it via json byte by byte or char by char, and at the c# end output it back to a text file. So you would have text(stream of 1 chars) + carriage return + text + End Of file etc. So request.RequestStream is that stream of bytes or chars. If the stream is a byte stream you might have to convert it back to string via StreamReader reader = new StreamReader(request.RequestStream); string ReceivedJsonText= reader.ReadToEnd();
VicMoore 754 Posted September 29, 2024 Author Posted September 29, 2024 (edited) @mickle026The code below works. The GET works perfectly. The POST code mostly works. The POST C# code gets executed and receives the payload from the JS. What does not work is the transfer of the JSON object to the C# EPG_Update request. Both GET and POST show up in Swagger. Vic C# code //--------------------------------------------------------------------------------------------------- // GET //--------------------------------------------------------------------------------------------------- [Route("/PseudoTV/ReportScheduledEPGTasks", "GET", Summary = "Report PseudoTV Scheduled EPG Update")] public class EPG_Status : IReturn<object> { [ApiMember(Name = "status", Description = "Status", IsRequired = false, DataType = "string", ParameterType = "status", Verb = "GET")] public string Status { get; set; } } public string Get(EPG_Status result) { bool completed = true; return JsonSerializer.SerializeToString(new EPG_Status() { Status = $"Function Ended with {completed}" }); } //--------------------------------------------------------------------------------------------------- // POST //--------------------------------------------------------------------------------------------------- [Route("/PseudoTV/ReportScheduledEPGTasks", "POST", Summary = "Update PseudoTV EPG")] public class EPG_Update : IReturnVoid { [ApiMember(Name = "update", Description = "update", IsRequired = false, DataType = "string", ParameterType = "status", Verb = "POST")] public string Update { get; set; } } public void Post(EPG_Update request) { this.Logger.Info("======PseudoTv POST Data = " + this.JsonSerializer.SerializeToString(request)); } //--------------------------------------------------------------------------------------------------- Javascript code //--------------------------------------------------------------------- // Request from the TV Platform the status of this test //--------------------------------------------------------------------- ApiClient.getJSON(ApiClient.getUrl('/PseudoTV/ReportScheduledEPGTasks')).then(response => { console.log(">>>>>> Response from server = ", response); }).catch(e => { console.log(">>>>>> Error = ", e); }); //--------------------------------------------------------------------- // POST to TV Platform //--------------------------------------------------------------------- let url = ApiClient.getUrl('/PseudoTV/ReportScheduledEPGTasks?api_key='+accessToken); console.log(">>>>>> url = ", url); var Http = new XMLHttpRequest(); Http.open('POST', url); let data = { Upload: true, }; let dataStr = JSON.stringify(data, null, 2); Http.send(dataStr); //--------------------------------------------------------------------- @mickle026The problem may be that I am not waiting for the promise to be fulfilled. Edited September 29, 2024 by VicMoore
mickle026 650 Posted September 30, 2024 Posted September 30, 2024 You haven't used the Requires Request Stream ? IRequiresRequestStream /--------------------------------------------------------------------------------------------------- // POST //--------------------------------------------------------------------------------------------------- [Route("/PseudoTV/ReportScheduledEPGTasks", "POST", Summary = "Update PseudoTV EPG")] public class EPG_Update : IReturnVoid, IRequiresRequestStream { [ApiMember(Name = "update", Description = "update", IsRequired = false, DataType = "string", ParameterType = "status", Verb = "POST")] public Stream Update { get; set; } // Stream (data stream in from the POST via JS) } then read the request sub element Update public void Post(EPG_Update request) { this.Logger.Info("======PseudoTv POST Data = " + request.Update); } See 4th post above this one /\ /\
VicMoore 754 Posted September 30, 2024 Author Posted September 30, 2024 The plugin code below has the GET and POST code in it. The line numbers are given below. to evoke the GET and POST test code, hold down the control key and click the green build EPG button. The results are in the Emby log and in the Browser console. PseudoTVTuner.cs lines 79 to 115 for the C# code Pseudotvconfig.js lines 1057 to 1078 for the JS code Vic PseudoTV.zip PseudoTV.dll
mickle026 650 Posted September 30, 2024 Posted September 30, 2024 This works, I used Swagger to send a stream (text file), in the text file was the text "testing api post", see success screenshot. [Route("/MechBox/TestPost", "POST", Summary = "Testing Post Data")] [Authenticated(Roles = "Admin")] public class Test : IReturn<object>, IRequiresRequestStream { public Stream RequestStream { get; set; } public string Text { get; set; } } public async Task<string> Post(Test request) { StreamReader reader = new StreamReader(request.RequestStream); string ReceivedJsonText = await reader.ReadToEndAsync().ConfigureAwait(true); return JsonSerializer.SerializeToString(new ReportNameErrors() { Text = "Received: " +ReceivedJsonText }); }
VicMoore 754 Posted September 30, 2024 Author Posted September 30, 2024 @mickle026WOW Congratulations!!! I cant get the IRequiresRequestStream to work. I keep getting the message "The IRequiresRequestStream interface is not implemented" Vic
mickle026 650 Posted September 30, 2024 Posted September 30, 2024 Are you putting it in the top outer class? It doesnt need to go there, only in the route class.
mickle026 650 Posted September 30, 2024 Posted September 30, 2024 like this namespace MechBox { public partial class MechBox : IService { private readonly IServerConfigurationManager configurationManager; private readonly IFileSystem _fileSystem; private readonly IJsonSerializer JsonSerializer; private readonly ILibraryManager libraryManager; private PluginConfiguration config { get; set; } private readonly IProviderManager providerManager; internal static string status; public static bool Running; internal static MechBox Current; internal string logname = "MechBox"; public MechBox(IProviderManager provManager, PluginConfiguration pconfig, IServerConfigurationManager serverConf, IFileSystem fileSystem, IJsonSerializer json, ILibraryManager libMan) { configurationManager = serverConf; _fileSystem = fileSystem; JsonSerializer = json; config = pconfig; libraryManager = libMan; providerManager = provManager; Current = this; } [Route("/MechBox/TestPost", "POST", Summary = "Testing Post Data")] [Authenticated(Roles = "Admin")] public class Test : IReturn<object>, IRequiresRequestStream { public Stream RequestStream { get; set; } // The data stream received , The keyword Stream is important and is a type like String public string Text { get; set; } } public async Task<string> Post(Test request) { StreamReader reader = new StreamReader(request.RequestStream); string ReceivedJsonText = await reader.ReadToEndAsync().ConfigureAwait(true); return JsonSerializer.SerializeToString(new ReportNameErrors() { Text = "Received: " +ReceivedJsonText });
VicMoore 754 Posted September 30, 2024 Author Posted September 30, 2024 Take a look at my C# code. I dont think I have the POST code in the right place. Vic
mickle026 650 Posted September 30, 2024 Posted September 30, 2024 (edited) 10 minutes ago, VicMoore said: Take a look at my C# code. I dont think I have the POST code in the right place. Vic I edited it, its fine where it is in the code //--------------------------------------------------------------------------------------------------- // POST //--------------------------------------------------------------------------------------------------- [Route("/PseudoTV/ReportScheduledEPGTasks", "POST", Summary = "Update PseudoTV EPG")] [Authenticated(Roles = "Admin")] public class EPG_Update : IReturnVoid, IRequiresRequestStream { public Stream RequestStream { get; set; } } public void Post(EPG_Update request) { StreamReader reader = new StreamReader(request.RequestStream); string ReceivedJsonText = reader.ReadToEnd(); this.Logger.Info("======PseudoTv POST Data = " + ReceivedJsonText); } //--------------------------------------------------------------------------------------------------- now you have the same as me (almost), this is not async. The string RecievedJsonText is not Deserialised, you can add that after you tested it. Edited September 30, 2024 by mickle026
mickle026 650 Posted September 30, 2024 Posted September 30, 2024 Thats me for tonight, its near 3am here and im at work later Have fun
VicMoore 754 Posted September 30, 2024 Author Posted September 30, 2024 @mickle026I added your edited code and [Route("/PseudoTV/ReportScheduledEPGTasks", "POST", Summary = "Update PseudoTV EPG")] [Authenticated(Roles = "Admin")] public class EPG_Update : IReturnVoid, IRequiresRequestStream { public Stream RequestStream { get; set; } } public void Post(EPG_Update request) { StreamReader reader = new StreamReader(request.RequestStream); string ReceivedJsonText = reader.ReadToEnd(); this.Logger.Info("======PseudoTv POST Data = " + ReceivedJsonText); } When I POST to the server I get a server error. Did you experience this? Vic
mickle026 650 Posted September 30, 2024 Posted September 30, 2024 2 minutes ago, VicMoore said: @mickle026I added your edited code and [Route("/PseudoTV/ReportScheduledEPGTasks", "POST", Summary = "Update PseudoTV EPG")] [Authenticated(Roles = "Admin")] public class EPG_Update : IReturnVoid, IRequiresRequestStream { public Stream RequestStream { get; set; } } public void Post(EPG_Update request) { StreamReader reader = new StreamReader(request.RequestStream); string ReceivedJsonText = reader.ReadToEnd(); this.Logger.Info("======PseudoTv POST Data = " + ReceivedJsonText); } When I POST to the server I get a server error. Did you experience this? Vic No, but i didnt try from the js, I'll try now this is what I get This is response from the GET request I need to sleep now, ill look further later .. and maybe build a spereate test plugin
VicMoore 754 Posted September 30, 2024 Author Posted September 30, 2024 Thanks @mickle026Good night. Vic
VicMoore 754 Posted September 30, 2024 Author Posted September 30, 2024 @mickle026It works - Yea !!!!! The code is attached below vic PseudoTV.dll PseudoTV.zip
mickle026 650 Posted October 1, 2024 Posted October 1, 2024 (edited) After scratching my head for a while, I realised that I had already read the filestream to a string. A proper duh! moment. Just simply needed to save the string. My test code JS return function (page, params) { page.addEventListener('viewshow', () => { document.getElementById("TestPOSTResult").innerHTML = "Result Will Appear Here"; page.querySelector('#TestPOST').addEventListener('click', () => { if (confirm('test POST\n\nAre you sure you want to continue?')) { reply = "Testing POST...<br />Please Wait until 'Received' is shown."; document.getElementById("TestPOSTResult").innerHTML = reply; TestPOSTMessage(); } else { document.getElementById("TestPOSTResult").innerHTML = "Cancelled"; } });; } ); function TestPOSTMessage() { let senddata = { Upload: true, Download: false, Whatever: "YouLike", }; var myposturl = '/MechBox/TestPost?api_key=' + apikey; var Http = new XMLHttpRequest(); Http.open('POST', myposturl); // convert to json let dataStr = JSON.stringify(senddata); console.log("TestPOSTResult Send: " + dataStr); // listen for the server response Http.onload = () => { if (Http.readyState == 4 && Http.status == 200) { const data = Http.response; console.log("Server Response: " + data); document.getElementById("TestPOSTResult").innerHTML = data; } else { console.log(`Error: ${Http.status}`); } } Http.send(dataStr); } } My C#, I am using my own logger here (it writes to my own seperate log file) [Route("/MechBox/TestPost", "POST", Summary = "Testing Post Data")] [Authenticated(Roles = "Admin")] public class Test : IReturn<object>, IRequiresRequestStream { public Stream RequestStream { get; set; } public string Text { get; set; } } public async Task<string> Post(Test request) { StreamReader reader = new StreamReader(request.RequestStream); string ReceivedJsonText = await reader.ReadToEndAsync().ConfigureAwait(true); config = Plugin.Instance.Configuration; Current = this; string LogPath = Current.configurationManager.ApplicationPaths.LogDirectoryPath; string currentlog = Path.Combine(LogPath, $"MechBox-[TESTING]" + DateTime.Now.ToString("dd.MMM.yyy-HH'.'mm'.'ss") + ".txt"); var log = new FileLogging(); log.LogToMyFile(currentlog, DateTime.Now.ToString("dd.MMM.yyy - HH':'mm':'ss") + $" ------------------- [ NEW TEST ] ---------------"); log.LogToMyFile(currentlog, DateTime.Now.ToString("dd.MMM.yyy - HH':'mm':'ss") + $" Recieved: {ReceivedJsonText}"); try { string CachePath = Current.configurationManager.CommonConfiguration.CachePath; log.LogToMyFile(currentlog, DateTime.Now.ToString("dd.MMM.yyy - HH':'mm':'ss") + $" CachePath: {CachePath}"); string SaveDirectory = Path.Combine(CachePath, "PseudoTV"); log.LogToMyFile(currentlog, DateTime.Now.ToString("dd.MMM.yyy - HH':'mm':'ss") + $" SaveDirectory: {SaveDirectory}"); string SaveFilePath = Path.Combine(CachePath, "PseudoTV", "PseudoTV-EPG.json"); log.LogToMyFile(currentlog, DateTime.Now.ToString("dd.MMM.yyy - HH':'mm':'ss") + $" SaveFilePath: {SaveFilePath}"); try { if (!Directory.Exists(SaveDirectory)) { Directory.CreateDirectory(SaveDirectory); log.LogToMyFile(currentlog, DateTime.Now.ToString("dd.MMM.yyy - HH':'mm':'ss") + $" Created directory: {SaveDirectory}"); } else { log.LogToMyFile(currentlog, DateTime.Now.ToString("dd.MMM.yyy - HH':'mm':'ss") + $" Directory Already Exists: {SaveDirectory}"); } } catch { log.LogToMyFile(currentlog, DateTime.Now.ToString("dd.MMM.yyy - HH':'mm':'ss") + $" Failed to create directory: {SaveDirectory}"); } try { File.WriteAllText(SaveFilePath, ReceivedJsonText, Encoding.UTF8); log.LogToMyFile(currentlog, DateTime.Now.ToString("dd.MMM.yyy - HH':'mm':'ss") + $" Saved file: {SaveFilePath}"); } catch { log.LogToMyFile(currentlog, DateTime.Now.ToString("dd.MMM.yyy - HH':'mm':'ss") + $" Failed to save filestream: {SaveFilePath}"); } } catch { } //file is now saved in Embys Cache path = cache\PseudtoTV\PseudoTV-EPG.json return JsonSerializer.SerializeToString(new Test() { Text = "Received: " + ReceivedJsonText }); My Log 01.Oct.2024 - 06:05:35 ------------------- [ NEW TEST ] --------------- 01.Oct.2024 - 06:05:35 Recieved: {"Upload":true,"Download":false,"Whatever":"YouLike"} 01.Oct.2024 - 06:05:35 CachePath: D:\cache 01.Oct.2024 - 06:05:35 SaveDirectory: D:\cache\PseudoTV 01.Oct.2024 - 06:05:35 SaveFilePath: D:\cache\PseudoTV\PseudoTV-EPG.json 01.Oct.2024 - 06:05:35 Directory Already Exists: D:\cache\PseudoTV 01.Oct.2024 - 06:05:35 Saved file: D:\cache\PseudoTV\PseudoTV-EPG.json The saved Json file The status update in my html before After Now that all works Edited October 1, 2024 by mickle026
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now