diff --git a/Samples/ClientInfoJs/ClientInfoJs.csproj b/Samples/ClientInfoJs/ClientInfoJs.csproj new file mode 100644 index 0000000..fa79304 --- /dev/null +++ b/Samples/ClientInfoJs/ClientInfoJs.csproj @@ -0,0 +1,31 @@ + + + netcoreapp2.0;net47 + + + + bin\ + + Exe + + + bin\$(TargetFramework)\ClientJs.xml + + + + + + + + + + + + + + Never + + + + + \ No newline at end of file diff --git a/Samples/ClientInfoJs/Program.cs b/Samples/ClientInfoJs/Program.cs new file mode 100644 index 0000000..5f1f644 --- /dev/null +++ b/Samples/ClientInfoJs/Program.cs @@ -0,0 +1,53 @@ +using SampleBase; +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using WebSocketRPC; + +namespace ClientInfoJs +{ + class PlatformInfo + { + internal async Task InitializeAsync() + { + var browserInfo = await RPC.For(this) + .CallAsync(x => x.GetBrowserInfo()); + + Console.WriteLine("\nBrowser info: " + browserInfo.First()); + } + + /* There are no public methods so the API is 'empty' from a client's perspective */ + } + + interface IBrowserInfo + { + string GetBrowserInfo(); + } + + class Program + { + //if access denied execute: "netsh http delete urlacl url=http://+:8001/" (delete for 'localhost', add for public address) + //open Index.html to run the client + static void Main(string[] args) + { + //generate js code (the API is empty) + File.WriteAllText($"./Site/{nameof(PlatformInfo)}.js", RPCJs.GenerateCaller()); + + //start server and bind its local and remote API + var cts = new CancellationTokenSource(); + var t = Server.ListenAsync("http://localhost:8001/", cts.Token, (c, ws) => + { + var pInfo = new PlatformInfo(); + c.Bind(pInfo); + c.OnOpen += pInfo.InitializeAsync; + }); + + Console.Write("{0} ", nameof(ClientInfoJs)); + Process.Start(new ProcessStartInfo(Path.GetFullPath("./Site/Index.html")) { UseShellExecute= true }); + AppExit.WaitFor(cts, t); + } + } +} diff --git a/Samples/ClientInfoJs/Site/Index.html b/Samples/ClientInfoJs/Site/Index.html new file mode 100644 index 0000000..57175ab --- /dev/null +++ b/Samples/ClientInfoJs/Site/Index.html @@ -0,0 +1,33 @@ + + + Client JS + + + + +

+ + + + + \ No newline at end of file diff --git a/Samples/README.md b/Samples/README.md index 429d64b..ad16a88 100644 --- a/Samples/README.md +++ b/Samples/README.md @@ -13,23 +13,29 @@ The recommendation is to run samples in the following order (from the more simpl Two way RPC: .NET <-> .NET. *Server is executing long running task on the client's request and sending progress notifications to to client.* -3. **ClientJs** +3. **ClientInfoJs** + Javascript client and C# server. + One way RPC: .NET -> Javascript. + *Server is calling a remote browser info function implemented on a JavaScript client. + Client's code is autogenerated.* + +4. **ClientJs** Javascript client and C# server. Two way RPC: .NET <-> Javascript. - *Server is executing long running task on the client's request and sending progress notifications to to client. + *Server is executing long running task on the client's request and sending progress notifications to to client. Client's code is autogenerated.* -4. **MultiService** +5. **MultiService** Javascript client(s) and C# server. Introduction to multi-services RPC. *Server has two services: numeric and text services / classes. Two Javascript files for each of the services are autogenerated.* -5. **Serialization** +6. **Serialization** Javascript client and C# server. Image serialization example. *Server has image-processing service which receives an image url and gives processed image back to a Javascript client.* -6. **AspRpc** +7. **AspRpc** Javascript client and C# server. ASP.NET library integration. *Server has reporting service initiatted and stopped on the client's request.* diff --git a/Samples/SampleBase/AppExit.cs b/Samples/SampleBase/AppExit.cs index ab481b5..d85e0eb 100644 --- a/Samples/SampleBase/AppExit.cs +++ b/Samples/SampleBase/AppExit.cs @@ -16,7 +16,7 @@ public static void WaitFor(CancellationTokenSource cts, params Task[] tasks) Task.Run(() => { - Console.WriteLine("------Press [Enter] or [Ctrl+C] to stop------"); + Console.WriteLine("------Press [Enter] to stop------"); Console.ReadLine(); cancelTasks(cts); diff --git a/Source/WebSocketRPC.AspCore/WebSocketRPC.AspCore.csproj b/Source/WebSocketRPC.AspCore/WebSocketRPC.AspCore.csproj index 5b06554..2b7eb34 100644 --- a/Source/WebSocketRPC.AspCore/WebSocketRPC.AspCore.csproj +++ b/Source/WebSocketRPC.AspCore/WebSocketRPC.AspCore.csproj @@ -32,7 +32,7 @@ websocket; ASP.NET; RPC; C#; .NET true - 1.0.5 + 1.0.6 ../../Deploy/Nuget/bin/ WebSocketRPC diff --git a/Source/WebSocketRPC.JS/RPCJs.cs b/Source/WebSocketRPC.JS/RPCJs.cs index 1de7289..4968de2 100644 --- a/Source/WebSocketRPC.JS/RPCJs.cs +++ b/Source/WebSocketRPC.JS/RPCJs.cs @@ -26,6 +26,7 @@ using System; using System.IO; using System.Linq; +using System.Linq.Expressions; using System.Reflection; using System.Text; @@ -42,14 +43,14 @@ public static class RPCJs /// Class or interface type. /// RPC-Js settings used for Javascript code generation. /// Javascript API. - public static string GenerateCaller(RPCJsSettings settings = null) + public static string GenerateCaller(RPCJsSettings settings = null) { settings = settings ?? new RPCJsSettings(); var (tName, mInfos) = JsCallerGenerator.GetMethods(settings.OmittedMethods); tName = settings.NameOverwrite ?? tName; var sb = new StringBuilder(); - if(settings.WithRequireSupport) sb.Append(JsCallerGenerator.GenerateRequireJsHeader(tName)); + if (settings.WithRequireSupport) sb.Append(JsCallerGenerator.GenerateRequireJsHeader(tName)); sb.Append(JsCallerGenerator.GenerateHeader(tName)); foreach (var m in mInfos) diff --git a/Source/WebSocketRPC.JS/Resources/ClientAPIBase.js b/Source/WebSocketRPC.JS/Resources/ClientAPIBase.js index f1e8604..69b2246 100644 --- a/Source/WebSocketRPC.JS/Resources/ClientAPIBase.js +++ b/Source/WebSocketRPC.JS/Resources/ClientAPIBase.js @@ -41,7 +41,7 @@ function onCallRequest(data, onError) } var r = null, errMsg = null; - try { obj[jsonFName].apply(obj, data.Arguments); } + try { r = obj[jsonFName].apply(obj, data.Arguments); } catch (e) { errMsg = e; } if (r === null || r === undefined) r = true; diff --git a/Source/WebSocketRPC.JS/WebSocketRPC.JS.csproj b/Source/WebSocketRPC.JS/WebSocketRPC.JS.csproj index 2ef3666..9decdcb 100644 --- a/Source/WebSocketRPC.JS/WebSocketRPC.JS.csproj +++ b/Source/WebSocketRPC.JS/WebSocketRPC.JS.csproj @@ -28,7 +28,7 @@ websocket; websocket-client; Javascript; RPC; C#; .NET true - 1.0.5 + 1.0.6 ../../Deploy/Nuget/bin/ WebSocketRPC diff --git a/Source/WebsocketRPC.Standalone/WebsocketRPC.Standalone.csproj b/Source/WebsocketRPC.Standalone/WebsocketRPC.Standalone.csproj index 8cce471..3b621c2 100644 --- a/Source/WebsocketRPC.Standalone/WebsocketRPC.Standalone.csproj +++ b/Source/WebsocketRPC.Standalone/WebsocketRPC.Standalone.csproj @@ -30,7 +30,7 @@ websocket; websocket-client; websocket-server; RPC; C#; .NET true - 1.0.5 + 1.0.6 ../../Deploy/Nuget/bin/ True diff --git a/WebsocketRPC.sln b/WebsocketRPC.sln index bdca177..5743e19 100644 --- a/WebsocketRPC.sln +++ b/WebsocketRPC.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.27130.2010 +VisualStudioVersion = 15.0.27130.2020 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{3CE373E0-6D9A-48C4-808D-510E6FB69D5C}" EndProject @@ -67,6 +67,8 @@ Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "SampleBase", "Samples\Sampl EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{96225EA6-4EA7-48AB-91F9-E53B0B5605F0}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClientInfoJs", "Samples\ClientInfoJs\ClientInfoJs.csproj", "{4F0482C4-83EE-4C2D-9B74-FE664179C891}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution Samples\SampleBase\SampleBase.projitems*{4c3c0292-f1f5-4997-8a0e-b4c7d05bb22f}*SharedItemsImports = 13 @@ -121,6 +123,10 @@ Global {96225EA6-4EA7-48AB-91F9-E53B0B5605F0}.Debug|Any CPU.Build.0 = Debug|Any CPU {96225EA6-4EA7-48AB-91F9-E53B0B5605F0}.Release|Any CPU.ActiveCfg = Release|Any CPU {96225EA6-4EA7-48AB-91F9-E53B0B5605F0}.Release|Any CPU.Build.0 = Release|Any CPU + {4F0482C4-83EE-4C2D-9B74-FE664179C891}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F0482C4-83EE-4C2D-9B74-FE664179C891}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F0482C4-83EE-4C2D-9B74-FE664179C891}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4F0482C4-83EE-4C2D-9B74-FE664179C891}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -142,6 +148,7 @@ Global {76FDC1DC-D80A-42E8-8A5D-2FE3462B9E3F} = {E5509F73-1E5E-45B4-AED7-4A38F8DF1DDE} {4C3C0292-F1F5-4997-8A0E-B4C7D05BB22F} = {E5509F73-1E5E-45B4-AED7-4A38F8DF1DDE} {96225EA6-4EA7-48AB-91F9-E53B0B5605F0} = {01049849-1A9A-4C3A-BD56-EA6B628F9F36} + {4F0482C4-83EE-4C2D-9B74-FE664179C891} = {E5509F73-1E5E-45B4-AED7-4A38F8DF1DDE} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {591A6475-8DF2-42DA-AFF1-8EF88BCF6EE4}